Як працювати зі структурою PDF у TypeScript

Як працювати зі структурою PDF у TypeScript

Цей посібник показує, як створити навігацію по документу та логічну структуру у PDF-файлах за допомогою Aspose.PDF FOSS для TypeScript: інтерактивний зміст на сторінці, огляд закладок на рівні документа, іменовані призначення та позначене дерево структури для доступності. Потрібен Node.js 22 або новіший.

Покроковий посібник

Крок 1: Встановити пакет

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

Перевірте встановлення, імпортуючи клас Document у новий файл TypeScript — цей рядок має успішно виконатися без помилок після встановлення пакету:

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

Крок 2: Імпортувати необхідні класи

Імпортуйте Document, щоб відкрити файл, і OutlineItem для записів закладок, створених у кроці 4:

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

Крок 3: Додати зміст

Page.AddTOC() приймає масив записів { title, page }, обмежувальний rect та параметри стилю; він створює пунктирні лідери та клікабельні посилання на цільові сторінки:

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 },
);

Крок 4: Додати закладки

Document.SetOutlines() замінює панель закладок документа масивом об’єктів OutlineItem. Кожен елемент може містити Dest (призначення сторінки), стилізацію (Color, Bold) та вкладений Children для розкривного дерева:

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);

Крок 5: Зчитати контури та іменовані призначення

Document.GetOutlines() повертає поточне дерево закладок. Document.GetNamedDestinations() повертає всі іменовані призначення, зареєстровані в документі — це корисно для перевірки, чи кожна ціль контуру та посилання змісту дійсно ведуть до реальної сторінки:

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());

Крок 6: Побудувати тегове дерево структури

Document.GetStructTree() повертає існуюче дерево структури (або null, якщо документ ще не був позначений). StructTreeRoot.Append(tag) додає дочірній елемент, такий як 'H2' або 'P', і повертає StructElement, а StructElement.MarkContent(page, quad) пов’язує цей елемент із вмістом сторінки, який він описує:

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);
  }
}

Типові проблеми та їх вирішення

Document.GetStructTree() returns null. Документ ще не був позначений — викличте Document.CreateStructTree() (або Document.AutoTag()) перед ручним створенням елементів за допомогою StructTreeRoot.Append() / StructElement.MarkContent().

Пункт структури не переходить на потрібну сторінку. OutlineItem.Dest повинен вказати пункт призначення, який дійсно існує — перевірте item.Dest.name against Document.GetNamedDestinations() перед збереженням, як показано у кроці 5.

Page.AddTOC() записи вказують на неправильну сторінку. page у кожному записі змісту вказано номер сторінки цільової сторінки — підтвердіть його проти page.Number на фактичному цільовому об’єкті Page, не передбачуваний індекс масиву.

Закладки зникають після пізнішого Document.SetOutlines() виклику. SetOutlines() замінює все дерево закладок — прочитайте поточне дерево за допомогою Document.GetOutlines() спочатку змініть масив, потім передайте весь масив назад, якщо закладки додаються, а не замінюються.

Часті запитання

Чи може закладка відкриватися вже розгорнутою?

Так — встановіть Open: true у OutlineItem, щоб діти цього вузла були видимими за замовчуванням у панелі закладок.

У чому різниця між закладкою та іменованим призначенням?

Закладка (OutlineItem) — це видимий запис у панелі навігації; іменоване призначення (Document.GetNamedDestinations() / SetNamedDestination()) — це внутрішня, багаторазова ціль сторінки, на яку можуть посилатися закладка, запис змісту (TOC) або аннотація-посилання за назвою.

Чи впливає тегування документа на його вигляд?

Ні — дерево структури (StructTreeRoot, StructElement) є паралельним логічним шаром, що описує порядок читання та семантику; воно не змінює видимий вміст сторінки.

Чи можу я вкладавати закладки?

Так — встановіть Children у OutlineItem в масив наступних об’єктів OutlineItem, щоб створити згортне багаторівневе дерево.

Дивіться також

 Українська