Pular para o conteúdo

O que é a linguagem PDFLang?

PDFLang é uma linguagem de script com uma função só: escrever como é um PDF correto, para que uma máquina possa conferir arquivos contra essa descrição.

Os scripts usam a extensão .pdfl. Quem os executa é o pdfl, uma ferramenta de linha de comando escrita em Rust.

Alguém precisa decidir se um PDF pode ir para a gráfica, ser protocolado ou seguir para o cliente.

As regras por trás dessa decisão são concretas. Cobertura de tinta abaixo de 300%. Todas as fontes embutidas. Trim box em todas as páginas. O código de barras batendo com o número impresso ao lado. Nenhuma página girada por acidente.

Essas regras costumam morar em três lugares ao mesmo tempo: na cabeça de quem faz o trabalho há mais tempo, num checklist que ninguém abre e num script que só o autor consegue manter. Aí a pessoa sai, o checklist envelhece e o script vira intocável.

PDFLang existe para que as regras morem num arquivo só, que quem as conhece consiga ler.

profile "press-ready" {
check "Tinta dentro do limite" tags: ["prepress"] {
require prepress::validate_tac_limits(300)
}
check "Fontes embutidas" {
doc.fonts.each { |font|
assert font.is_embedded, "A fonte #{font.name} não está embutida"
}
}
}

Quatro palavras sustentam a maior parte da linguagem:

  • profile agrupa os checks e nomeia o conjunto.
  • check é uma regra, e vira uma seção do relatório.
  • require interrompe o check quando uma precondição não se cumpre.
  • assert registra uma ocorrência, com a mensagem que você escreveu.

Sem classes, sem herança, sem declaração de tipos, sem ponto e vírgula. Isso é decisão, não omissão: o leitor para quem ela foi desenhada entende de pré-impressão, não de programação.

A mesma intenção aparece em detalhes menores. Páginas começam em 1, como todo mundo fora de um compilador conta. Medidas aceitam 3mm e 1in direto. Porcentagens se escrevem 300%.

Sete namespaces, um por tipo de trabalho:

  • text:: — extração, normalização, busca, validações, dados pessoais
  • struct:: — objetos, metadados, XMP, segurança, hashes
  • visual:: — resolução, comparação visual, hash perceptual, qualidade
  • prepress:: — cobertura de tinta, separações, cores especiais, fontes, boxes
  • codes:: — detecção, decodificação e validação de códigos de barras e QR
  • fix:: — boxes, páginas, marcas d’água, junção e divisão, otimização
  • data:: — glossários, datasets e tabelas de consulta vindos de fora do arquivo

Um relatório. De forma abreviada, um check que falha aparece assim:

{
"script_name": "prepress.pdfl",
"input_file": "magazine.pdf",
"status": "FAIL",
"error_count": 2,
"diagnostics": [
{
"id": "PDFL-093751a2",
"severity": "error",
"check_name": "Ink coverage",
"message": "page 7: 324% ink (limit 300%)"
}
]
}

Repare nesse message. Não é um stack trace. É uma frase que alguém pode encaminhar ao fornecedor que mandou o arquivo — e é por isso que a linguagem faz você escrevê-la, ao lado da regra a que ela pertence.

JSON é o padrão. CSV, HTML e PDF existem para quem precisa ler o relatório em vez de interpretá-lo, e SARIF e JUnit para quando a ocorrência precisa aparecer onde o time já olha.

Terminal window
pdfl run press-ready.pdfl magazine.pdf > report.json

O código de saída carrega o veredito, então um shell script ou um job de CI decide em cima dele sem interpretar nada:

Código Significado
0 passou tudo
1 apenas avisos
2 erros de validação
3 erro de sintaxe no script
10 o documento não pôde nem ser lido

A ferramenta fala inglês, seus scripts não precisam

Seção intitulada “A ferramenta fala inglês, seus scripts não precisam”

As mensagens que o próprio pdfl imprime — diagnósticos, erros, ajuda da linha de comando — são em inglês, como é hábito em ferramentas de linha de comando. Esta documentação está traduzida em sete idiomas, mas um check que falha ainda reporta page 7: 324% ink (limit 300%).

As mensagens dentro dos seus scripts são suas. Escreva no idioma de quem vai ler o relatório.

O manual da linguagem é o capítulo que vale ler do começo ao fim. Tudo depois dele é referência: um capítulo por namespace, os comandos do CLI e as receitas, montadas em cima de casos completos — uma gráfica, uma editora jurídica, um laboratório, um pipeline de CI.

Se você prefere ler código a ler prosa, os exemplos são perfis executáveis com os comentários preservados.

DigitalOceanObrigado à DigitalOcean pela hospedagem deste site.