Pular para o conteúdo

Motores de layout personalizados e interceptação de texto durante o layout

O NextPDF não expõe uma interface para motor de layout plugável. Use o contrato público de extensão de layout, TextPreprocessorInterface, para interceptar texto durante o layout. Os eventos de ciclo de vida do conteúdo permitem observar o que o layout produz.

Terminal window
composer require nextpdf/core:^3

O pipeline de layout é interno. Ele abrange o layout de glifos, o subconjunto de fontes, a saída do CMap ToUnicode e a árvore de estrutura. O NextPDF não permite que você substitua esse pipeline. A saída de bytes estável e a conformidade com PDF marcado dependem de um único build controlado.

O NextPDF, porém, expõe o ponto antes do layout: TextPreprocessorInterface. Uma implementação recebe o texto bruto e retorna um resultado segmentado antes que esse texto entre no layout de glifos, no subconjunto de fontes, no CMap ToUnicode ou na árvore de estrutura. Use esse caminho suportado para alterar o conteúdo do texto sem mexer no motor de layout.

O PHPDoc original define uma regra rígida: uma implementação não deve alterar o funcionamento do layout. Ela não deve adicionar caracteres que afetem o layout, como avanço de linha, retorno de carro ou tabulação, e deve preservar a ordem lógica de leitura. O pré-processador declara uma substituição de conteúdo; ele não toma decisões de layout. Respeite essa regra; caso contrário, a saída estável e a acessibilidade serão comprometidas.

Para observar o resultado do layout sem alterá-lo, use os eventos de ciclo de vida do conteúdo em Gatilhos de ação e ouvintes de eventos. O ContentRenderedEvent é disparado depois que o conteúdo é desenhado em uma página. O FontLoadedEvent é disparado uma vez por família e estilo de fonte.

NextPDF\Contracts\TextPreprocessorInterface (estável, desde a 1.9.0):

MétodoRetornaFinalidade
process(string $text)TextPreprocessResultTransformar o texto bruto antes do pipeline de renderização e retornar um resultado segmentado com metadados de censura.

O NextPDF\Contracts\TextPreprocessResult retornado é um objeto de valor congelado. A assinatura do construtor e as propriedades públicas são estáveis e não mudam em uma versão menor ou de correção. Novos métodos podem ser adicionados.

O pequeno pré-processador abaixo mascara um token fixo. Ele não adiciona caracteres que afetem o layout e mantém a ordem de leitura.

<?php
declare(strict_types=1);
use NextPDF\Contracts\TextPreprocessorInterface;
use NextPDF\Contracts\TextPreprocessResult;
use NextPDF\Contracts\TextSegment;
final class TokenMaskingPreprocessor implements TextPreprocessorInterface
{
public function process(string $text): TextPreprocessResult
{
$masked = \str_replace('SECRET-TOKEN', '••••••••••••', $text);
return new TextPreprocessResult([
new TextSegment($masked, redacted: $masked !== $text),
]);
}
}

Um pré-processador de produção mantém as regras de correspondência em um só lugar. Diante de um padrão inválido, ele falha de modo fechado e nunca registra o texto original.

<?php
declare(strict_types=1);
use NextPDF\Contracts\TextPreprocessorInterface;
use NextPDF\Contracts\TextPreprocessResult;
use NextPDF\Contracts\TextSegment;
use Psr\Log\LoggerInterface;
final class PatternRedactionPreprocessor implements TextPreprocessorInterface
{
/**
* @param non-empty-string $pattern A valid PCRE pattern for sensitive spans
*/
public function __construct(
private readonly string $pattern,
private readonly LoggerInterface $logger,
) {}
public function process(string $text): TextPreprocessResult
{
$result = \preg_replace($this->pattern, '[REDACTED]', $text);
if ($result === null) {
// Fail closed: never emit unredacted text on a pattern error.
$this->logger->error('Redaction pattern failed; substituting empty text');
return new TextPreprocessResult([new TextSegment('', redacted: true)]);
}
return new TextPreprocessResult([
new TextSegment($result, redacted: $result !== $text),
]);
}
}
  • Sem substituição de layout. Você não pode substituir o layout de caixas, a quebra de linha ou a paginação por meio deste contrato. Conectar um motor de layout de terceiros está fora de escopo por decisão de design.
  • Aplicação da regra. Se você adicionar \n, \r ou \t em process(), isso corrompe o layout e quebra a saída estável. O motor confia nessa regra; ele não revalida a saída em busca de caracteres que afetem o layout.
  • Ordem de leitura. Se você reordenar os segmentos, você quebra a ordem de leitura do PDF marcado e a conformidade com PDF/UA.
  • Uma única responsabilidade. O pré-processador declara uma substituição de conteúdo. Use os eventos de ciclo de vida para observar e não introduza efeitos colaterais por meio de process().

process() é executado uma vez para cada trecho de texto no caminho crítico do layout. Mantenha baixo o uso de memória. Compile os padrões uma única vez no construtor, não a cada chamada. Os eventos de ciclo de vida do conteúdo não têm custo quando nenhum ouvinte está vinculado.

Use TextPreprocessorInterface para remover conteúdo sensível antes que ele chegue ao fluxo de conteúdo, aos subconjuntos de fontes ou aos metadados. Como a execução ocorre antes do subconjunto de fontes e do CMap ToUnicode, os glifos censurados nunca entram no arquivo. Trate uma falha do pré-processador como falha fechada e emita texto vazio ou mascarado em vez do original.

Esta página não faz nenhuma afirmação normativa sobre assinatura ou arquivamento. A regra de ordem de leitura alinha o contrato às necessidades de PDF marcado. A referência de acessibilidade abrange a conformidade no nível de marcação.

O NextPDF Pro oferece estratégias de pré-processamento de texto prontas para produção, incluindo censura de informações de identificação pessoal (PII) ajustada para tipos comuns de documento. No Core, você mesmo implementa TextPreprocessorInterface, ou usa um build verificado da edição paga por meio do mesmo contrato público.

O glossário define pré-processador de texto e ponto de extensão; consulte o glossário publicado para cada definição canônica.