Signets et métadonnées

Prenez un document LaTeX qui charge hyperref, effacez les fichiers auxiliaires et compilez une seule fois. Le PDF obtenu ne contient aucun signet : le plan n’apparaît qu’à la deuxième passe. La raison tient à la fabrication des signets : hyperref écrit les titres dans un fichier annexe nommé jobname.out et le relit au début de la compilation suivante avant de rien placer dans le PDF. Cette page suit ce mécanisme, puis le paquet bookmark qui jette carrément le fichier .out et réussit dès la première passe, les métadonnées PDF réglées par \hypersetup, le point d’entrée plus récent \DocumentMetadata, et le charabia qui gâche les signets japonais — chaque affirmation vérifiée sur une vraie sortie de pdfinfo.

hyperref construit les signets à partir des titres

Il suffit d’écrire \usepackage{hyperref} pour que \chapter, \section et \subsection deviennent un plan PDF. Le réglage passe par les options du paquet ou par \hypersetup{}, et quatre clés couvrent l’essentiel : bookmarks (actif par défaut), bookmarksnumbered (reprendre les numéros de section dans les signets), bookmarksopen (démarrer déplié) et bookmarksopenlevel=N (jusqu’à quelle profondeur). Ouvrez le fichier intermédiaire jobname.out : vous y trouverez une suite d’appels de macros LaTeX — et les chaînes n’y sont pas en clair mais en UTF-16BE, si bien qu’un titre anglais s’écrit \376\377\000C\000o\000v\000e\000r, avec un \000 devant chaque caractère. Le \376\377 initial est la marque d’ordre des octets UTF-16 : c’est ainsi que PDF définit ses chaînes de texte.

latex
\usepackage[bookmarksnumbered,bookmarksopen,bookmarksopenlevel=1]{hyperref}
% or set the same keys later
\hypersetup{bookmarksopenlevel=1}
log
% report.out after three passes — hyperref stores the outline here
\BOOKMARK [0][]{cover.0}{\376\377\000C\000o\000v\000e\000r}{}% 1
\BOOKMARK [0][]{chapter.1}{...1 Foundations...}{}% 2
\BOOKMARK [1][-]{section.1.1}{...1.1 First section...}{chapter.1}% 3
\BOOKMARK [2][-]{subsection.1.1.1}{...1.1.1 A subsection...}{section.1.1}% 4

La profondeur par défaut ne vient pas du mécanisme des signets mais de la table des matières. La classe report fixe tocdepth à 2 (jusqu’à subsection), de sorte qu’un \subsubsection n’atteint jamais le plan. C’est voulu : les deux listes doivent avoir la même granularité. Pour des signets plus profonds que la table, utilisez bookmarksdepth — à la mesure, ajouter bookmarksdepth=4 a fait apparaître un \subsubsection dans le plan alors qu’il restait absent de la table des matières. Inversement, bookmarksdepth=1 replie le plan au niveau des sections.

OptionEffetPar défaut
bookmarksproduire ou non le plantrue
bookmarksnumberedinclure les numéros de section dans les libellésfalse
bookmarksopenafficher l’arbre déplié à l’ouverturefalse
bookmarksopenlevelcombien de niveaux démarrent dépliéstous
bookmarksdepthniveau le plus profond admis dans le plansuit tocdepth

Poser un signet là où il n’y a pas de titre : \pdfbookmark

Pour les endroits qui ne passent par aucune commande de sectionnement — page de couverture, table des matières, préface non numérotée —, écrivez directement \pdfbookmark[level]{texte visible}{anchor}. Le niveau du premier argument est un nombre (\chapter vaut 0, \section vaut 1) et l’ancre du troisième doit être unique dans le document, sinon les destinations entrent en conflit. Pour ajouter une entrée au niveau courant, il y a \currentpdfbookmark{texte}{anchor}, et un cran plus bas \belowpdfbookmark{texte}{anchor}. L’usage le plus fréquent est de poser un signet sur la table des matières elle-même : une ligne avant \tableofcontents. Faute de quoi on livre ce PDF singulier où le lecteur peut sauter partout sauf revenir au sommaire.

latex
\begin{document}
\pdfbookmark[0]{Cover}{cover}      % level 0, same rank as \chapter
\maketitle
\clearpage
\pdfbookmark[1]{Contents}{toc}     % the classic missing bookmark
\tableofcontents
\chapter{Foundations}

Le paquet bookmark : jeter le fichier .out et réussir en une passe

Chargez le paquet bookmark de Heiko Oberdiek après hyperref (TeX Live 2024 fournit la v1.31 du 10/12/2023) et tout le mécanisme des signets est remplacé. La mesure le montre aussitôt : avec hyperref seul, le PDF de la première passe depuis un répertoire propre ne contient aucun objet /Outlines, et seule la deuxième passe apporte les sept entrées. Avec bookmark, les sept sont là dès la première passe. L’astuce est simple : bookmark n’écrit pas de fichier .out (vérifiable, aucun n’apparaît dans le répertoire). Il fait transiter le plan par le fichier .aux, ce qui supprime l’étape du fichier annexe périmé. Les signets propres à hyperref se désactivent d’eux-mêmes : aucun conflit.

Le second gain est l’apparence. \bookmarksetup{} accepte numbered (reprendre les numéros de section), open et openlevel, ainsi que le style entrée par entrée : color=blue, bold, italic. En ouvrant le PDF produit, chaque élément du plan porte effectivement une entrée de couleur /C [ … ]. Pour ne modifier qu’une entrée, placez juste avant elle \bookmarksetupnext{color=red}. Dans un long rapport, ne colorer que les annexes et l’index rend la barre latérale nettement plus lisible d’un coup d’œil.

latex
\usepackage{hyperref}
\usepackage{bookmark}      % must come after hyperref
\bookmarksetup{numbered, open, openlevel=1, color=blue}

% one entry only
\bookmarksetupnext{color=red, bold}
\chapter{Appendix}

Métadonnées PDF : déclarer titre et auteur avec \hypersetup

Ce que le lecteur affiche sous « Propriétés du document » dépend de quatre clés de \hypersetup{} : pdftitle, pdfauthor, pdfsubject et pdfkeywords. Elles ne sont pas recopiées depuis \title et \author : il faut écrire les deux, car hyperref a besoin des valeurs avant l’exécution de \maketitle. Un seul appel à pdfinfo dit si cela a fonctionné. Les champs pdfcreator et pdfproducer désignent le logiciel producteur et se remplissent d’ordinaire tout seuls : pdfLaTeX avec hyperref indique Creator: LaTeX with hyperref et Producer: pdfTeX-1.40.26. On peut les écraser, mais on efface alors la seule trace de la fabrication du fichier : mieux vaut y renoncer.

latex
\usepackage{hyperref}
\hypersetup{
  pdftitle={Measured Bookmarks},
  pdfauthor={Ada Lovelace},
  pdfsubject={PDF navigation},
  pdfkeywords={LaTeX, hyperref, bookmarks}
}
terminal
$ pdfinfo report.pdf
Title:           Measured Bookmarks
Subject:         PDF navigation
Keywords:        LaTeX, hyperref, bookmarks
Author:          Ada Lovelace
Creator:         LaTeX with hyperref
Producer:        pdfTeX-1.40.26
Pages:           5
Page size:       595.276 x 841.89 pts (A4)
PDF version:     1.5

Les caractères accentués s’écrivent désormais tels quels. La version 7.01h de hyperref, livrée avec TeX Live 2024, active par défaut \Hy@unicodetrue en interne : pdftitle={Théorie des catégories — Übersicht} ressort intact de pdfinfo, même sous pdfLaTeX, et l’option unicode autrefois indispensable ne l’est plus. Ce qui mord encore, c’est que les valeurs de \hypersetup sont écrites telles quelles comme chaînes dans le PDF : la règle pratique est donc de n’y mettre aucune macro. pdftitle={Utiliser \LaTeX{}} invite à un échec d’expansion, là où un simple pdftitle={Utiliser LaTeX} passe toujours.

\DocumentMetadata : la nouvelle porte d’entrée des métadonnées et du balisage

\DocumentMetadata{…} est une déclaration plus récente du noyau LaTeX, à placer avant \documentclass. Elle fonctionne réellement sous TeX Live 2024 et accepte des clés telles que lang=en-GB (la langue du document), pdfversion=2.0, pdfstandard=A-2B (le niveau PDF/A, de A-1B à A-4) et uncompress (couper toute compression). Une seule ligne a déjà un effet visible : dans pdfinfo, Metadata Stream passe de no à yes, le PDF portant désormais un flux de métadonnées XMP. Les clés \hypersetup existantes continuent de fonctionner à côté, et les deux jeux de valeurs se retrouvent bien dans le PDF.

Au-delà se trouve le PDF balisé. Ajoutez testphase={phase-III}, compilez deux fois avec pdflatex, et pdfinfo annonce Tagged: yes : LaTeX a commencé à inscrire la structure des paragraphes et des titres dans l’arbre de structure du PDF. Comme le nom de la clé l’indique, c’est encore une phase de test, à ne pas activer sans réflexion dans une version finale destinée à la soumission ; mais il vaut la peine de savoir qu’une version fonctionnelle est déjà livrée avec TeX Live standard. Notez aussi que \DocumentMetadata a un effet de bord sur le format de papier : vérifiez les dimensions du PDF en l’ajoutant à un document existant — les détails figurent dans « Produire et contrôler le PDF ».

latex
\DocumentMetadata{pdfversion=2.0, lang=en-GB, testphase={phase-III}}
\documentclass{article}
\usepackage{hyperref}
\hypersetup{pdftitle={Tagged Test}, pdfauthor={Ada Lovelace}}
% pdfinfo then reports: Tagged: yes / Metadata Stream: yes / PDF version: 2.0

Quand les signets japonais deviennent illisibles : pxjahyper et l’option dvipdfmx

Obtenir des signets japonais corrects avec upLaTeX et dvipdfmx demande deux correctifs distincts. Le premier consiste à indiquer à hyperref pour quel pilote il écrit. Avec un simple \usepackage{hyperref}, le journal affiche Package hyperref Info: Driver (default): hdvips. : on produit du DVI, mais hyperref émet des \special destinés à dvips. Donnez ce DVI à dvipdfmx et défilent dvipdfmx:warning: Unknown token "SDict" puis Interpreting special command ps: (ps:) failed., pour un PDF sans le moindre signet ni lien. Écrivez plutôt \usepackage[dvipdfmx]{hyperref} : le journal indique Driver: hdvipdfm. et il ne reste aucun avertissement.

Le second correctif porte sur l’encodage des caractères. Une fois le pilote rectifié, le plan revient, mais un titre japonais arrive sous la forme æ鞥æ鲬èꪞã膮èꚋå螺ã膗. Le fichier .out en donne la raison : 日 devrait devenir les deux octets \145\345 en UTF-16BE, alors que ses trois octets UTF-8 sont traités chacun comme un caractère distinct et gonflés en \000\346\000\227\000\245. Ajoutez \usepackage{pxjahyper} (de Takayuki Yato ; TeX Live 2024 fournit la v1.3) et le .out devient un UTF-16BE correct — \376\377\145\345\147\054\212\236… — tandis que pdfinfo annonce un Title: 日本語のタイトル lisible. Point décisif : cela répare pdftitle et pdfauthor en même temps que les signets.

latex
% upLaTeX -> dvipdfmx: both lines are needed
\documentclass{ujarticle}
\usepackage[dvipdfmx]{hyperref}   % without this: dvipdfmx warning, no outline
\usepackage{pxjahyper}            % without this: mojibake in the outline
\hypersetup{pdftitle={...}, pdfauthor={...}}

Ce double correctif ne concerne que la voie DVI de (u)pLaTeX. LuaLaTeX avec LuaTeX-ja y parvient avec un simple \usepackage{hyperref} : le journal indique Driver (autodetected): hluatex. et le fichier .out est en UTF-16BE correct dès le départ. XeLaTeX avec xeCJK donne pareillement des signets lisibles sans paquet supplémentaire. Si les signets japonais illisibles vous poursuivent, changer de moteur est souvent la sortie la plus courte. Une remarque d’ordre : hyperref se charge le plus tard possible, mais cleveref doit venir après hyperref ; l’inverse arrête la compilation sur ! Package cleveref Error: cleveref must be loaded after hyperref!. Si varioref s’en mêle, l’ordre est hyperref, puis varioref, puis cleveref.