Skip to content

Latest commit

 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

merge-pdf

Monta um PDF único a partir de uma planilha e uma pasta de certificados, na ordem que você definir — extraindo automaticamente a sua página de certificados emitidos em lote.

Feito para entrega de atividades complementares (ACC / AACC / ATPA / horas extracurriculares), onde a secretaria pede "tudo num arquivo só, na ordem da planilha".

O problema

Muita instituição emite certificado em lote: um único PDF com uma página por aluno da turma. Um certificado de mostra de trabalhos pode ter 140 páginas, das quais só uma é sua.

Juntar os arquivos direto — em qualquer ferramenta de merge — produz um documento com centenas de páginas de outras pessoas. Este projeto localiza a sua página pelo nome e descarta o resto.

Instalação

git clone <url-do-repositorio>
cd merge-pdf
npm install
cp config.example.js config.js

Edite o config.js com o seu nome e os caminhos. Ele não é versionado.

Uso

node build.js

Gera o arquivo definido em config.arquivoSaida. É idempotente — rode quantas vezes quiser.

Estrutura dos documentos

dados/
├── planilha.pdf
└── certificados/
    ├── 1 - Participação em eventos/
    │   ├── 1 - Primeiro evento.pdf
    │   ├── 2 - Segundo evento.pdf
    │   └── 10 - Décimo evento.pdf
    ├── 2 - Cursos online/
    │   └── 1 - Algum curso.pdf
    └── 3 - Estágio/
        └── 1 - Termo de estágio.pdf

Os prefixos numéricos definem a ordem no documento final — pastas primeiro, depois arquivos dentro de cada pasta. 10 vem depois de 9, não depois de 1.

Para inserir um certificado no meio, renumere os arquivos. Nada mais muda.

O que ele faz

Extrai a sua página de certificados em lote

PDFs acima de limitePaginasSemFiltro páginas são varridos em busca do seu nome; só as páginas encontradas entram.

A busca ignora acentos, espaços e maiúsculas — necessário porque certificados em lote costumam ter kerning agressivo, e o extrator devolve o nome quebrado (Ma ria d a Sil va San tos). Também aceita várias grafias, já que emissores diferentes escrevem o mesmo nome de formas diferentes.

A regra é conservadora, para nunca perder comprovação:

Situação O que acontece
PDF pequeno (≤ limite) entra inteiro, sem filtro
PDF grande, nome encontrado entram só as páginas do titular
PDF grande, nome ausente (escaneado) entra inteiro e emite aviso

Padroniza o tamanho das páginas

Acervos misturam A4, Letter, A3 e tamanhos avulsos, o que faz o leitor de PDF reajustar o zoom a cada página. Tudo vira A4, preservando a orientação de cada página — paisagem continua paisagem. Nada é rotacionado ou cortado.

Preserva selos de assinatura digital

Esta é a parte mais delicada do projeto.

Selos de assinatura digital (gov.br, ICP-Brasil) vivem em anotações (/Annots) da página, não no conteúdo. Isso importa porque:

  • copyPages preserva anotações
  • embedPages descarta anotações

Por isso a normalização para A4 é feita no próprio documento, com scale + setMediaBox, e não reconstruindo o PDF com embedPages. Uma implementação ingênua faz documentos assinados saírem com as linhas de assinatura em branco — comprovação sem assinatura nenhuma.

O build.js imprime a contagem de anotações ao final. Se cair, algo quebrou.

Limitação incontornável: a validade criptográfica se perde em qualquer merge — a assinatura cobre o arquivo original inteiro, então juntar arquivos a invalida por definição. O que fica é o selo visual, com nome, data e link de verificação. Se alguém exigir a validação criptográfica, os originais precisam ser entregues à parte.

Converte imagens

JPG e PNG viram página A4, na orientação da própria imagem.

Gera índice navegável

O PDF sai com marcadores de dois níveis (categoria → certificado) e abre com o painel visível. Não altera nada do conteúdo.

Comprime para envio

Sistemas acadêmicos costumam ter limite de upload. Certificados chegam como imagem sem perda (Flate + PNG Predictor) em resolução alta — ótimo para arquivamento, exagerado para enviar.

node scripts/comprimir.js [qualidade] [dpiMaximo]   # padrão: 82 e 200

Gera um arquivo -compacto.pdf sem tocar no original. Na prática corta cerca de metade do peso sem diferença visível: a resolução é mantida, o que muda é o método de compressão. Texto e QR codes de validação continuam nítidos.

Duas salvaguardas:

  • Imagem com transparência real é preservada intacta. A conversão só acontece quando o canal alfa é inteiramente opaco — nesse caso descartá-lo é idêntico ao original.
  • A troca só é feita quando o resultado é ao menos 10% menor.

Marcadores, selos de assinatura, contagem de páginas e tamanho passam intactos — vale conferir depois de comprimir.

Diagnóstico

node scripts/analisar.js "termo de busca"   # revela PDFs que são lote de turma
node scripts/assinaturas.js                 # lista documentos assinados digitalmente
node scripts/conferir.js                    # titular e carga horária, página a página

A saída do conferir.js contém dados pessoais — não cole em issue, PR ou qualquer lugar público.

O conferir.js é o que se usa antes de enviar: ele lista cada página do documento final com o titular detectado e a carga horária declarada, para cruzar com a planilha.

Arquitetura

build.js              receita: monta o documento na ordem das pastas
config.example.js     template de configuração
src/
  config.js           carrega o config.js local, com erro claro se faltar
  coletar.js          descobre e ordena pastas e arquivos
  filtrar.js          localiza as páginas do titular
  normalizar.js       converte para A4 sem destruir anotações
  marcadores.js       índice navegável
  predictor.js        desfaz o PNG Predictor de imagens Flate
scripts/
  analisar.js         identifica PDFs que são lote de turma
  assinaturas.js      lista documentos assinados digitalmente
  conferir.js         confere página a página antes do envio
  comprimir.js        gera versão compacta para upload

src/ é genérico e reaproveitável. build.js é a receita específica — é o arquivo a adaptar para outro tipo de dossiê.

Privacidade

Certificados são dado pessoal, e os emitidos em lote contêm o nome de dezenas ou centenas de outras pessoas — além de CPF em atestados e termos.

O .gitignore bloqueia o diretório de dados, PDFs, imagens, compactados e o config.js. Confira antes do primeiro push:

git status --ignored --short | grep '^!!'   # o que está sendo ignorado
git ls-files                                 # o que será versionado

Requisitos

Node.js 18+. Dependências: pdf-lib (manipulação) e pdf-parse (extração de texto).

Licença

MIT — veja LICENSE.

About

Monta um PDF unico a partir de uma planilha e certificados, extraindo sua pagina de certificados emitidos em lote e preservando selos de assinatura digital (gov.br/ICP-Brasil).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages