Як працювати зі структурою 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, щоб створити згортне багаторівневе дерево.