Ir al contenido

Agregar marcadores y una tabla de contenido

En esta recipe se agrega un esquema jerárquico del documento basado en marcadores. La aplicación lectora muestra estas entradas en su barra lateral de navegación, donde también funcionan como una tabla de contenido navegable. Un valor entero de nivel controla el anidamiento. La recipe se basa en examples/12-bookmarks-and-toc.php.

ISO 32000-2 denomina esto esquema del documento: una jerarquía con estructura de árbol compuesta por elementos de esquema que funciona como una tabla de contenido visual.

Ventana de terminal
composer require nextpdf/core:^3

No se requiere ninguna extensión opcional. La API de marcadores es estable desde la 1.0.0 y funciona con la matriz de backport 8.1–8.4.

bookmark($title, $level, $y) agrega un elemento de esquema vinculado a la página actual. El vínculo usa la Y actual o una Y explícita. $level define la profundidad de anidamiento: el nivel 0 corresponde a un capítulo de nivel superior, el nivel 1 a una sección bajo el elemento de nivel 0 más reciente, y así sucesivamente. El motor construye automáticamente el árbol del esquema. ISO 32000-2 encadena los elementos mediante Prev/Next en cada nivel y los anida mediante First/Last, con la entrada Outlines del catálogo como raíz.

Cada elemento incluye un destino, de modo que el lector salta a la página correcta cuando se hace clic en el marcador. ISO 32000-2 §12.3.2 indica que los destinos pueden asociarse con elementos de esquema. La misma llamada también proporciona datos al constructor de la tabla de contenido de NextPDF, de modo que el esquema y la tabla de contenido renderizada permanecen sincronizados.

La superficie de la API se genera automáticamente a partir del PHPDoc. Esta recipe usa un solo método:

  • bookmark(string $title, int $level = 0, float $y = -1): static — agrega un elemento de esquema en $level vinculado a la página actual. $y = -1 usa la Y actual del cursor. Pasar una Y no negativa permite fijar un destino preciso.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->addPage();
$doc->bookmark('Chapter 1', level: 0);
$doc->setFont('helvetica', 'B', 18);
$doc->cell(0, 12, 'Chapter 1', newLine: true);
$doc->bookmark('Section 1.1', level: 1); // nested under Chapter 1
$doc->setFont('helvetica', '', 11);
$doc->multiCell(0, 7, 'Section body.');
$doc->addPage();
$doc->bookmark('Chapter 2', level: 0);
$doc->setFont('helvetica', 'B', 18);
$doc->cell(0, 12, 'Chapter 2', newLine: true);
$doc->save(getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/bookmarks.pdf');

Este es el ejemplo completo, listo para el arnés de pruebas. Respeta NEXTPDF_COOKBOOK_OUTPUT sin introducir entropía propia.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Bookmarks and Navigation');
$doc->setPrintHeader(false);
$doc->setPrintFooter(false);
$doc->setAutoPageBreak(true, margin: 25);
// Chapter 1
$doc->addPage();
$doc->bookmark('Chapter 1: Introduction', level: 0);
$doc->setFont('helvetica', 'B', 18);
$doc->cell(0, 12, 'Chapter 1: Introduction', newLine: true);
$doc->ln(3);
$doc->bookmark('What is NextPDF?', level: 1);
$doc->setFont('helvetica', 'B', 14);
$doc->cell(0, 10, 'What is NextPDF?', newLine: true);
$doc->setFont('helvetica', '', 11);
$doc->multiCell(0, 7, 'NextPDF is a modern PDF 2.0 library for PHP 8.4+. '
. 'It generates standards-targeting documents with typography, '
. 'graphics, and signatures.');
$doc->ln(5);
$doc->bookmark('Key Features', level: 1);
$doc->setFont('helvetica', 'B', 14);
$doc->cell(0, 10, 'Key Features', newLine: true);
$doc->setFont('helvetica', '', 11);
$doc->multiCell(0, 7, 'HTML rendering, barcodes, PAdES signatures, '
. 'and a worker-safe architecture.');
// Chapter 2
$doc->addPage();
$doc->bookmark('Chapter 2: Getting Started', level: 0);
$doc->setFont('helvetica', 'B', 18);
$doc->cell(0, 12, 'Chapter 2: Getting Started', newLine: true);
$doc->ln(3);
$doc->bookmark('Installation', level: 1);
$doc->setFont('helvetica', 'B', 14);
$doc->cell(0, 10, 'Installation', newLine: true);
$doc->setFont('helvetica', '', 11);
$doc->multiCell(0, 7, 'Install via Composer: composer require nextpdf/core');
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: __DIR__ . '/bookmarks.pdf';
$doc->save($out);
echo "Created bookmarks.pdf with a 2-level outline\n";
  • Saltos de nivel. Un salto del nivel 0 al nivel 2 sin un nivel 1 intermedio produce una jerarquía que algunos lectores muestran como malformada. Aumentar el nivel como máximo de uno en uno en cada paso.
  • Marcador antes del contenido. Debe llamarse a bookmark() en el punto donde se desea ubicar el destino. En la mayoría de los casos, conviene colocar la llamada justo antes del encabezado. Una llamada colocada después del encabezado fija el destino ligeramente por debajo de él.
  • Y explícita para destinos precisos. Con $y = -1, el destino es la Y actual del cursor. Pasar una Y explícita permite obtener un destino estable. Por ejemplo, una Y explícita fija la parte superior de una sección sin importar cuánto contenido la preceda.
  • El soporte del esquema es universal, pero la presentación varía. Los lectores pueden renderizar el esquema contraído o expandido. La API no puede forzar un estado abierto o cerrado por elemento.

Cada llamada a bookmark() añade un elemento de esquema y una entrada de tabla de contenido, lo que supone trabajo O(1). El árbol del esquema se finaliza una sola vez en save(). Cientos de marcadores se mantienen con holgura dentro del presupuesto de 2000 ms / 64 MB.

Los títulos de los marcadores se muestran en la interfaz de navegación del lector. Si un título contiene datos controlados por el usuario, limitar su longitud y sanearlo como cualquier otra cadena visible. Esta recipe no realiza ningún análisis de la entrada ni accede a la red.

EnunciadoEspecificaciónCláusulareference_id
El esquema del documento es un árbol de elementos de esquema que funciona como una TOC visual.ISO 32000-2§12.3.3
Los elementos de esquema se encadenan mediante Prev/Next y se anidan mediante First/Last.ISO 32000-2§12.3.3
El diccionario de esquema es la entrada Outlines del catálogo.ISO 32000-2§7.7.2
Los destinos pueden asociarse con elementos de esquema.ISO 32000-2§12.3.2

Perfil de reproducibilidad — estructural. El /ID del tráiler y los átomos de fecha varían en cada guardado, por lo que el arnés elimina esos átomos y compara la estructura normalizada por qpdf. Esta recipe describe cómo NextPDF produce esa estructura. No afirma la conformidad con ISO 32000-2 como declaración general.

No aplica. El esquema del documento y la tabla de contenido son capacidades del núcleo (Core) sin ninguna restricción de nivel Premium.