Pro edition
Table of contents
At a glance
Section titled “At a glance”NextPDF\Pro\Toc collects H1–H6 headings from HTML and renders a paginated,
multi-level table of contents as PDF content-stream operators. Page numbers
are caller-supplied (or sequential placeholders); the module does not resolve
live document cross-references.
Availability & licensing
Section titled “Availability & licensing”This capability ships in NextPDF Pro (nextpdf/pro) and activates with a
Pro-tier license envelope. A deployment without that entitlement does not load the capability’s classes. The Toc classes load
whenever nextpdf/pro is installed; no runtime capability flag gates the
module. Compare editions and get a license.
Install
Section titled “Install”composer require nextpdf/pro:^3Conceptual overview
Section titled “Conceptual overview”The workflow has two phases:
- Collection.
AutoTocCollector::extract($html, maxDepth)scans the HTML for<h1>–<h6>tags up to the depth limit, strips inner markup, decodes entities, normalizes whitespace, and emitsTocHeadingvalue objects (level 0 = H1). It can assign sequential page numbers or apply a caller-provided index-to-page map. - Rendering.
AutoTocRenderer::render($headings, $config)produces one PDF content-stream string per TOC page, with indentation per level, optional dot leaders, and optional page numbers. Each visible line is emitted as aTjtext-showing operation per ISO 32000-2:2020 §9.4.
AutoTocConfig is an immutable, fluently-configured value object controlling
title, depth, fonts, spacing, margins, colors, page size, and whether dot
leaders and page numbers are shown.
Why it works this way
Section titled “Why it works this way”The load-bearing decision is that the module never invents a page number it
cannot know. True target pages depend on the final laid-out document, which the
caller owns; a guess would drift silently whenever pagination changed. So
collection and rendering stay decoupled from layout. AutoTocCollector emits
headings with null or placeholder pages; real page numbers arrive only through a
caller-supplied assignPageNumbers() map. Rendering then produces plain
content-stream operators, leaving page placement to the caller. The result stays
deterministic and honest: the module states what it does not know rather than
fabricating it.
Design background: An API that refuses to guess.
Behavior contract
Section titled “Behavior contract”- Input. HTML (collection) and a list of
TocHeading(rendering). - Output.
list<TocHeading>from collection;list<string>of PDF content-stream operators (one per TOC page) from rendering. - Page numbers. Either assigned sequentially, supplied via an index-to-page map, or left null. The module does not compute true target pages from a laid-out document; it does not resolve cross-references.
- Depth.
maxDepthis clamped to 1–6. Headings deeper than the configured depth are skipped. - Determinism. For identical HTML and configuration, collected headings and rendered operators are stable.
Public API surface
Section titled “Public API surface”| Type | Kind | Key members |
|---|---|---|
NextPDF\Pro\Toc\AutoTocCollector | final class | static extract(string $html, int $maxDepth = 6): list<TocHeading>, scan(string $html): void, assignSequentialPages(int $startPage = 1): list<TocHeading>, assignPageNumbers(array $pageMap): list<TocHeading> |
NextPDF\Pro\Toc\AutoTocRenderer | final class | static render(array $headings, ?AutoTocConfig $config = null): list<string> |
NextPDF\Pro\Toc\AutoTocConfig | final readonly class | default(), landscape(), letter(), withTitle(), withMaxDepth(), withFontSize(), withDotLeader(), withPageNumbers(), withIndentPerLevel(), entriesPerPage(): int |
NextPDF\Pro\Toc\TocHeading | final readonly class | string $title, int $level, ?int $pageNumber, float $y, withPageNumber(), withPosition(), hasPageNumber(): bool |
Code sample — Quick start
Section titled “Code sample — Quick start”<?php
declare(strict_types=1);
use NextPDF\Pro\Toc\AutoTocCollector;use NextPDF\Pro\Toc\AutoTocRenderer;
$headings = AutoTocCollector::extract($html, maxDepth: 3);$streams = AutoTocRenderer::render($headings);
echo count($streams), " TOC page(s) of content-stream operators\n";Code sample — Production
Section titled “Code sample — Production”<?php
declare(strict_types=1);
use NextPDF\Pro\Toc\AutoTocCollector;use NextPDF\Pro\Toc\AutoTocConfig;use NextPDF\Pro\Toc\AutoTocRenderer;
function buildToc(string $html, array $headingPageMap): array{ $collector = new AutoTocCollector(maxDepth: 4); $collector->scan($html);
// Caller supplies real page numbers from its own layout pass. $headings = $collector->assignPageNumbers($headingPageMap);
$config = AutoTocConfig::default() ->withTitle('Contents') ->withMaxDepth(4) ->withDotLeader(true) ->withPageNumbers(true);
return AutoTocRenderer::render($headings, $config);}Edge cases & gotchas
Section titled “Edge cases & gotchas”- Empty heading text (after tag stripping) is skipped.
maxDepthis clamped to 1–6 at both collector and config; out-of-range values are corrected, not rejected.- Page numbers are placeholders unless the caller supplies a real map; the module does not run a layout pass to discover true target pages.
- The renderer emits content-stream operators for placement onto a page; the caller is responsible for adding those pages to the document.
Performance
Section titled “Performance”Collection is one regular-expression pass over the HTML. Rendering is linear
in heading count, paginated by entriesPerPage(). See performance_budget.
Security notes
Section titled “Security notes”HTML is scanned with a bounded heading regular expression and tag stripping; no HTML is executed and no external references are followed. Rendered text is escaped for content-stream string syntax.
Conformance
Section titled “Conformance”| Claim | Spec clause | Status |
|---|---|---|
TOC lines emitted as Tj text-showing operations | ISO 32000-2:2020 §9.4 | Verified (unit suite) |
| Live document cross-reference resolution | — | Not supported (caller-supplied page numbers) |
Core fallback / alternative
Section titled “Core fallback / alternative”There is no Core TOC generator. Heading source HTML typically comes from the Core HTML pipeline. See /modules/core/html/.
Enterprise boundary note
Section titled “Enterprise boundary note”This module collects headings and renders TOC operators. It does not perform document-wide cross-reference resolution, index generation, or bookmark-tree synchronization; those concerns are out of scope.
Publication boundary
Section titled “Publication boundary”This page documents externally observable behavior and the supported public API surface only. Internal namespace paths, helper classes, mechanism tables, runbook filenames, and ticket prefixes are out of scope.