Structure

Structure

Эта страница охватывает навигацию по документу и логическую структуру: оглавления (закладки), таблицы содержимого, именованные назначения и помеченное дерево структуры, используемое для доступности и перераспределения.


Оглавления (закладки)

Document.GetOutlines() возвращает текущее дерево оглавления как OutlineItem[] ([], когда нет /Outlines); Document.SetOutlines() заменяет его — передача [] полностью удаляет оглавление. Каждый OutlineItem имеет Title, Dest (номер страницы или именованное назначение), необязательный Children для вложенности и стилизацию (Color, Bold, Italic, Open).

const items: OutlineItem[] = sections.map((s) => {
  const item: OutlineItem = { Title: s.title, Dest: { name: s.dest } };
  if (s.subtype === 'sales') {
    item.Open = true;
    item.Children = ['Pasta', 'Pizza', 'Antipasti']
      .map((cat) => ({ Title: cat, Dest: { name: s.dest } }));
  }
  return item;
});
doc.SetOutlines(items);

Оглавление

Page.AddTOC() отображает список объектов TOCEntry — каждый с title и целевым номером page — в прямоугольнике на странице, с переносом заголовков, точечными лидерами и выровненными по правому краю метками страниц. Он возвращает AddTOCResult, сообщающий, сколько записей было отрисовано, и, если коробка слишком мала, remainder, которые не поместились.

page.AddTOC(
  sections.map((s, i) => ({ title: `${i + 1}. ${s.title}`, page: s.page.Number })),
  [72, 160, 400, 400],
  { font: 'Helvetica', fontSize: 13, rowGap: 18 },
);

Именованные назначения

Document.GetNamedDestinations() возвращает каждое именованное назначение — объединяя дерево имён /Names /Dests и наследующий словарь /Dests — в виде пар { name, dest }, где dest является PageDest ({ page, view }). Это те же именованные цели, которые OutlineItem.Dest или аннотация ссылки могут ссылаться по имени вместо явного номера страницы.

const destNames = new Set(doc.GetNamedDestinations().map((d) => d.name));
for (const { name, dest } of doc.GetNamedDestinations()) {
  console.log(name, '-> page', dest.page);
}

Дерево помеченной структуры

Document.AutoTag() выводит и создает /StructTreeRoot из макета страницы — заголовки по кластеризации размеров шрифта, абзацы по блокам текста, таблицы по геометрии линий, а для каждого изображения — решения /Figure vs. /Artifact — и возвращает AutoTagReport с подсчётами для каждого типа элемента. Document.GetStructTree() считывает полученный StructTreeRoot, или null, если документ не помечен.

const report = doc.AutoTag({ lang: 'en-US', title: 'Quarterly Report', tables: true });
console.log(report.headings, report.paragraphs, report.tables, report.figures);

const tree = doc.GetStructTree();
console.log(tree ? tree.GetText() : '(no structure tree)');

Содержимое, добавленное после выполнения AutoTag() — например, страница, заполненная позже — не охватывается этим проходом и не будет двойного помечания. StructTreeRoot.Append() и StructElement.MarkContent() представляют собой ручные API авторства наряду с эвристическим: Append() добавляет дочерний элемент заданного типа, а MarkContent() отмечает область страницы как принадлежащую этому элементу.


Советы и лучшие практики

  • Запустите Document.AutoTag() один раз, после того как содержимое страницы окончательно — он не пере-помечает добавленное позже содержимое, поэтому вручную пометьте всё, что добавлено позже, с помощью StructTreeRoot.Append() / StructElement.MarkContent().
  • Передайте opts.title в AutoTag() — это также устанавливает /ViewerPreferences /DisplayDocTitle, которое PDF/UA требует вместе с заголовком документа.
  • OutlineItem.Dest может указывать либо на явную страницу, либо на именованное назначение ({ name: '...' }) — используйте именованные назначения, когда номер целевой страницы может измениться при изменении содержимого.
  • Проверьте AddTOCResult.remainder, когда автопагинация отключена — поле оглавления, слишком маленькое для каждой записи, тихо прекращает отрисовку вместо переполнения поля.

Распространённые проблемы

ПроблемаПричинаИсправление
Document.GetStructTree() возвращает nullДокумент не был помеченСначала вызовите Document.AutoTag() или Document.CreateStructTree()
Ссылка элемента оглавления не разрешаетсяЕё Dest указывает на пункт назначения, которого нет в Document.GetNamedDestinations()Подтвердите, что указанное назначение существует, или используйте вместо этого явную страницу Dest
Page.AddTOC() останавливается перед последним разделомЦелевой rect слишком мал для каждой записи, а autoPaginate отключёнУвеличьте rect, передайте autoPaginate: true или обработайте AddTOCResult.remainder
Содержимое, добавленное после AutoTag(), отсутствует в дереве структурыAutoTag() только отмечает содержимое, присутствующее в момент его выполненияРучным образом пометьте последующее содержимое с помощью StructTreeRoot.Append() / StructElement.MarkContent()

FAQ

Как добавить закладки в PDF?

Создайте массив объектов OutlineItem (Title, Dest, опциональный Children) и передайте его в Document.SetOutlines().

Может ли оглавление растягиваться на несколько страниц?

Да — передайте autoPaginate: true в опциях Page.AddTOC(), либо проверьте AddTOCResult.remainder и вызовите AddTOC() снова на новой странице для того, что не поместилось.

Как сделать PDF доступным (с тегами)?

Вызовите Document.AutoTag(), который выводит заголовки, абзацы, таблицы и рисунки из макета страницы. Для добавленного позже контента или когда результат эвристики требует исправления, используйте непосредственно StructTreeRoot.Append() и StructElement.MarkContent() напрямую.

В чём разница между назначением по номеру страницы и именованным назначением?

Назначение по номеру страницы (PageDest) указывает на конкретную страницу, нумерация которой начинается с 1. Именованное назначение (NamedDest) указывает на имя, которое просмотрщик разрешает с помощью таблиц именованных назначений документа — полезно, когда целевая страница может переместиться.


API Reference Сводка

Класс/МетодОписание:
Document.GetOutlines() / Document.SetOutlines()Читать или заменять дерево оглавления (закладки) документа
OutlineItemОдин узел оглавления: Title, Dest, необязательный Children
Page.AddTOC()Отрисовать оглавление в прямоугольнике страницы
TOCEntry / AddTOCResultДанные строки TOC и результат её отрисовки
Document.GetNamedDestinations()Перечислите все именованные назначения в документе
Document.AutoTag()Сформируйте и создайте теговое дерево структуры на основе макета страницы
Document.GetStructTree() / Document.CreateStructTree()Прочитайте или создайте StructTreeRoot документа
StructTreeRoot.Append() / StructElement.Append() / StructElement.MarkContent()Вручную создайте или расширьте дерево структуры

См. также:

 Русский