Como Trabalhar com Anotações em TypeScript
Este guia mostra como adicionar, flatten e pesquisar anotações PDF com Aspose.PDF FOSS para TypeScript. A classe Page expõe um método Add* por subtipo de anotação — markup (highlight, underline, strikeout, squiggly), shapes (square, circle, line, polygon, ink), text (sticky note, free text) e links — cada um retornando um manipulador tipado Annotation que pode ser lido novamente ou flatten posteriormente. Requer Node.js 22 ou posterior.
Guia passo a passo
Etapa 1: Instalar o pacote
git clone https://github.com/aspose-pdf-foss/Aspose.PDF-FOSS-for-TypeScript.git
cd Aspose.PDF-FOSS-for-TypeScript
npm install
npm run buildVerifique a instalação importando a classe Document em um novo arquivo TypeScript — esta linha deve ser resolvida sem erro depois que o pacote for instalado:
import { Document } from '@asposefoss/pdf';Etapa 2: Importar classes necessárias
Importe Document para abrir o arquivo e Page para as assinaturas dos tipos de anotação usadas nas etapas abaixo:
import { Document, Page } from '@asposefoss/pdf';Etapa 3: Adicionar Anotações de Marcação
Page.AddHighlight(), Page.AddUnderline(), Page.AddSquiggly() e Page.AddStrikeOut() aceitam todos um array quads — um quad de 8 números (x1,y1,x2,y2,x3,y3,x4,y4) por região de texto destacado — além de um color e opcionalmente um contents. A biblioteca gera o fluxo de aparência (/AP) para os quatro subtipos automaticamente:
import { Document } from '@asposefoss/pdf';
const doc = Document.OpenFile('input.pdf');
const page = doc.Pages[0];
page.AddHighlight({
quads: [72, 700, 300, 700, 72, 685, 300, 685],
color: [1, 1, 0],
contents: 'Yellow highlight',
});
page.AddUnderline({
quads: [72, 660, 300, 660, 72, 645, 300, 645],
color: [0, 0, 1],
});
page.AddStrikeOut({
quads: [72, 620, 300, 620, 72, 605, 300, 605],
color: [1, 0, 0],
});
doc.WriteTo('annotated.pdf');Etapa 4: Adicionar Anotações de Forma e Tinta
Page.AddSquare() e Page.AddCircle() aceitam um rect delimitador mais color (traçado) e opcionalmente fill. Page.AddLine() aceita um line de 4 números (x1,y1,x2,y2) e terminações de seta opcionais. Page.AddInk() aceita paths — um array de arrays planos de pares de pontos, um por traço de caneta:
page.AddSquare({ rect: [100, 500, 220, 560], color: [0.8, 0, 0], fill: [1, 1, 0.5], width: 2 });
page.AddCircle({ rect: [250, 500, 370, 560], color: [0, 0.5, 0], width: 2 });
page.AddLine({
line: [100, 470, 370, 470],
color: [0, 0, 0.7],
width: 2,
startEnding: 'OpenArrow',
endEnding: 'ClosedArrow',
});
page.AddInk({
paths: [[100, 400, 130, 430, 160, 390, 190, 420]],
color: [0.6, 0, 0.6],
width: 2,
});Etapa 5: Adicionar um Post-it e Texto Livre
Page.AddTextNote() coloca um ícone clicável que abre um pop-up de comentário. Page.AddFreeText() desenha texto diretamente na página dentro de seu rect:
page.AddTextNote({
rect: [400, 700, 420, 720],
icon: 'Note',
author: 'Reviewer',
contents: 'This is a sticky-note annotation.',
});
page.AddFreeText({
rect: [400, 600, 550, 660],
contents: 'FreeText sample',
fontSize: 10,
align: 'center',
fill: [1, 1, 0.8],
width: 1,
});Etapa 6: Achatar uma Anotação em Conteúdo Estático
Cada manipulador de anotação retornado por uma chamada Add* possui um método Flatten() que incorpora a aparência da anotação ao fluxo de conteúdo da página e a remove de /Annots. Após o achatamento não resta nada para clicar ou editar em um visualizador:
const note = page.AddFreeText({
rect: [210, 535, 470, 590],
contents: 'Sticky note — flattened into the page.',
fontSize: 11,
align: 'left',
});
note.Flatten(); // -> boolean; bakes the annotation, unwires itself from /Annots
Etapa 7: Pesquisar texto da anotação
Page.SearchAnnotationText() and Page.SearchAnnotations() são disjuntos em ambas as direções: SearchAnnotationText() corresponde a metadados de anotação literal (/Contents, /T, /Subj), enquanto SearchAnnotations() corresponde ao rendered texto de anotações de marcação como FreeText:
const metadataHits = page.SearchAnnotationText('confidential');
for (const hit of metadataHits) {
console.log(hit.key, hit.value); // e.g. 'Contents', 'confidential'
}
const renderedHits = page.SearchAnnotations('confidential');
console.log(renderedHits.length);Problemas comuns e correções
Page.AddHighlight() (ou outro método de marcação) desenha no lugar errado. quads é um array plano de 8 números (x1,y1,x2,y2,x3,y3,x4,y4), não um rect — passar um retângulo de 4 números produz um quad degenerado ou ausente. Crie um quad por linha de texto destacado.
Uma anotação achatada ainda é clicável. Flatten() deve ser chamado no objeto retornado por Add* chamada, e o documento deve ser salvo (doc.WriteTo() / doc.Save()) após o achatamento — a alteração só existe na memória até que o arquivo seja gravado novamente.
SearchAnnotationText() não retorna resultados mesmo que o texto esteja visível na página. Ele só procura nos campos de metadados da anotação (/Contents, /T, /Subj) — texto de marcação visível renderizado a partir da própria aparência da anotação (por exemplo, um FreeText corpo) é encontrado por SearchAnnotations() em vez disso, e não procura conteúdo de página comum (use Page.GetText() or Page.Search() para isso).
Marcas de redação não aparecem ao pesquisar anotações. Page.AddRedact() cria um RedactAnnotation, um subtipo distinto das anotações de markup/shape/text abordadas aqui — veja o Redaction guia.
Perguntas Frequentes
Quantos subtipos de anotação o Page suporta?
A biblioteca gera aparências para markup (highlight, underline, strikeout, squiggly), shapes (square, circle, line, polygon, ink), text (sticky note, free text), links e stamps — além de anotações de file attachment e redaction, que são abordadas em seus próprios how-to guides.
Posso ler anotações que já existem em uma página?
Sim — Page.Annotations devolve as anotações existentes como um array de handles tipados que você pode inspecionar, editar ou flatten, e Page.RemoveAnnotation(a) remove uma.
Qual é a diferença entre flattening uma anotação e aplicar uma redaction?
Flatten() processa a anotação’s appearance na página e remove o objeto de anotação, mas qualquer conteúdo de texto ou imagem abaixo dele permanece intacto. ApplyRedactions() reescreve destrutivamente o fluxo de conteúdo, de modo que o próprio conteúdo coberto desaparece — veja o Redaction guide para detalhes.
As anotações são preservadas durante uma sequência de salvar/abrir?
Sim — anotações adicionadas antes de doc.WriteTo() / doc.Save() são gravadas no PDF e lidas corretamente na próxima Document.Open() / Document.OpenFile().