Jak pracować ze strukturą PDF w TypeScript

Jak pracować ze strukturą PDF w TypeScript

Ten przewodnik pokazuje, jak zbudować nawigację w dokumencie i logiczną strukturę w plikach PDF przy użyciu Aspose.PDF FOSS dla TypeScript: klikalny spis treści na stronie, spis zakładek na poziomie dokumentu, nazwane cele oraz oznaczony drzewo struktury dla dostępności. Wymaga Node.js 22 lub nowszej wersji.

Przewodnik krok po kroku

Krok 1: Zainstaluj pakiet

git clone https://github.com/aspose-pdf-foss/Aspose.PDF-FOSS-for-TypeScript.git
cd Aspose.PDF-FOSS-for-TypeScript
npm install
npm run build

Zweryfikuj instalację, importując klasę Document w nowym pliku TypeScript — ta linia powinna zostać rozwiązana bez błędu po zainstalowaniu pakietu:

import { Document } from '@asposefoss/pdf';

Krok 2: Zaimportuj wymagane klasy

Importuj Document, aby otworzyć plik i OutlineItem dla wpisów zakładek utworzonych w Kroku 4:

import { Document, OutlineItem } from '@asposefoss/pdf';

Krok 3: Dodaj spis treści

Page.AddTOC() przyjmuje tablicę wpisów { title, page }, ograniczający rect oraz opcje stylu; rysuje przerywane prowadnice i klikalne odnośniki do stron docelowych:

const page = doc.Pages[0];

page.AddTOC(
  [
    { title: '1.  Introduction', page: 2 },
    { title: '2.  Methodology', page: 5 },
    { title: '3.  Results', page: 9 },
  ],
  [72, 160, 400, 600],
  { font: 'Helvetica', fontSize: 13, color: [0.1, 0.1, 0.15], rowGap: 18 },
);

Krok 4: Dodaj zakładki

Document.SetOutlines() zastępuje panel zakładek dokumentu tablicą obiektów OutlineItem. Każdy element może zawierać Dest (cel strony), stylizację (Color, Bold) oraz zagnieżdżone Children tworzące zwijalne drzewo:

const items: OutlineItem[] = [
  { Title: 'Sales', Dest: { name: 'section.sales' }, Open: true, Color: [0.1, 0.4, 0.1] },
  { Title: 'Appendix', Dest: { name: 'section.appendix' } },
];

doc.SetOutlines(items);

Krok 5: Odczytaj spisy i nazwane cele

Document.GetOutlines() zwraca aktualne drzewo zakładek. Document.GetNamedDestinations() zwraca wszystkie nazwane cele zarejestrowane w dokumencie — przydatne do weryfikacji, czy każdy cel spisu i odnośnik w spisie treści rzeczywiście prowadzi do istniejącej strony:

const destNames = new Set(doc.GetNamedDestinations().map((d) => d.name));

const walk = (nodes: OutlineItem[]): void => {
  for (const item of nodes) {
    if (item.Dest && 'name' in item.Dest) {
      console.log(destNames.has(item.Dest.name), item.Title);
    }
    if (item.Children) walk(item.Children);
  }
};
walk(doc.GetOutlines());

Krok 6: Zbuduj tagowane drzewo struktury

Document.GetStructTree() zwraca istniejące drzewo struktury (lub null, jeśli dokument nie został otagowany). StructTreeRoot.Append(tag) dodaje element podrzędny, taki jak 'H2' lub 'P', i zwraca StructElement, a StructElement.MarkContent(page, quad) kojarzy ten element z treścią strony, którą opisuje:

function tagPage(doc: Document, page: Page, headingText: string): void {
  const root = doc.GetStructTree();
  if (!root) throw new Error('tagPage: the document is not tagged yet');

  for (const block of page.GetStructuredText()) {
    const text = block.text.trim();
    if (text.length === 0) continue;
    const el = root.Append(text.startsWith(headingText) ? 'H2' : 'P');
    el.MarkContent(page, block.quad);
  }
}

Typowe problemy i rozwiązania

Document.GetStructTree() returns null. Dokument nie został jeszcze otagowany — wywołaj Document.CreateStructTree() (lub Document.AutoTag()) przed ręcznym tworzeniem elementów z StructTreeRoot.Append() / StructElement.MarkContent().

Element konspektu nie przeskakuje do właściwej strony. OutlineItem.Dest musi wskazywać docelowy punkt, który rzeczywiście istnieje — sprawdź krzyżowo item.Dest.name against Document.GetNamedDestinations() przed zapisaniem, jak pokazano w Kroku 5.

Page.AddTOC() pozycje wskazują niewłaściwą stronę. page w każdej pozycji spisu treści jest własny numer strony docelowej — potwierdź to względem page.Number na rzeczywistym celu Page, a nie przypuszczalny indeks tablicy.

Zakładki znikają po późniejszym Document.SetOutlines() wywołaniu. SetOutlines() zastępuje całe drzewo zakładek — odczytaj bieżące drzewo za pomocą Document.GetOutlines() najpierw, zmodyfikuj tablicę, a następnie przekaż całą tablicę z powrotem, jeśli zakładki są dodawane, a nie zastępowane.

Najczęściej zadawane pytania

Czy zakładka może otworzyć się już rozwinięta?

Tak — ustaw Open: true na OutlineItem, aby dzieci tego węzła były domyślnie widoczne w panelu zakładek.

Jaka jest różnica między zakładką a nazwanym miejscem docelowym?

Zakładka (OutlineItem) jest widocznym wpisem w panelu nawigacji; nazwane miejsce docelowe (Document.GetNamedDestinations() / SetNamedDestination()) jest wewnętrznym, wielokrotnego użytku celem strony, na który mogą wskazywać zakładka, wpis spisu treści lub adnotacja linku, używając nazwy.

Czy tagowanie dokumentu wpływa na jego wygląd?

Nie — drzewo struktury (StructTreeRoot, StructElement) jest równoległą warstwą logiczną opisującą kolejność czytania i semantykę; nie zmienia ono widocznej zawartości strony.

Czy mogę zagnieżdżać zakładki?

Tak — ustaw Children na OutlineItem jako tablicę dalszych obiektów OutlineItem, aby zbudować zwijalne, wielopoziomowe drzewo.

Zobacz także

 Polski