xindy et hyperref

, par Maïeul

Nous arrivons maintenant à un point délicat dans l’utilisation de xindy : sa compatibilité avec le package hyperref. Ce dernier insère en effet des liens hypertextes dans l’index : chaque référence pointe vers la page correspondante. Cependant l’insertion de ces liens utilisent les mécanismes de makeindex et pas ceux de xindy ce qui n’est pas sans poser quelques petits problèmes.

Un exemple qui marche …

Reprenons l’exemple de l’article précédent mais en activant hyperref :

\documentclass{article}

\usepackage{fontspec}
\usepackage{polyglossia}
\setmainlanguage{french}
\setmainfont{Linux Libertine O}
\usepackage{setspace}
\onehalfspacing
\usepackage[xindy]{indextools}%On précise qu'on veut utiliser xindy
\makeindex[name=animal,title=Animaux,columnseprule]

% Personnaliser l'apparence de lettergroup
\newcommand{\lettergroup}[1]{%
  {\centering\large---\emph{#1}---\par}%
}
\apptocmd{\subitem}{$\rightarrow$\,}{}{}


\begin{document}


On va parler de 
chats sauvages\index[animal]{chat!sauvage} et domestiques\index[animal]{chat!domestique},
de tortues marines\index[animal]{tortue!marine} et terrestres\index[animal]{tortue!terrestre},
d'élèphant d'Asie\index[animal]{élèphant!d'Asie} et d'Afrique\index[animal]{élèphant!d'Afrique},
et soyons fou, d'élans de Sibérie\index[animal]{élan!de Sibérie} et d'Amérique\index[animal]{élan!d'Amérique}.

\newpage

On va parler sur la page suivante des même animaux. C'est à dire : de 
chats sauvages\index[animal]{chat!sauvage} et domestiques\index[animal]{chat!domestique},
de tortues marines\index[animal]{tortue!marine} et terrestres\index[animal]{tortue!terrestre},
d'élèphant d'Asie\index[animal]{élèphant!d'Asie} et d'Afrique\index[animal]{élèphant!d'Afrique},
et soyons fou, d'élans de Sibérie\index[animal]{élan!de Sibérie} et d'Amérique\index[animal]{élan!d'Amérique}.

\newpage

Et pour la bonne cause, on va aussi parler de chats sauvages\index[animal]{chat!sauvage} qui se disputent avec les chiens errants\index[animal]{chien!errant}.
\printindex[animal]
\end{document}

Cela produit le PDF ci-dessous.

xindy + hyperref : exemple qui fonctionne

Comme vous pouvez constater, tout semble fonctionner : notre index est correct et les liens internes fonctionnent.

… mais c’est tout

Les problèmes surviennent lorsqu’on tente de marquer une référence comme importante, par exemple avec |textbf.
Ainsi :

Et pour la bonne cause, on va aussi parler de chats sauvages\index[animal]{chat!sauvage|textbf} qui se disputent avec les chiens errants\index[animal]{chien!errant}.
\printindex[animal]

Lors de la compilation texindy vous obtenez le message suivant :

WARNING : unknown cross-reference-class `hyperindexformat’ !

Et de fait, la référence marquée par |textbf est absente de l’index final.

xindy + hyperref + |textbf ne fonctionne pas

La cause du problème

Rappelons que xindy se « contente » de transformer un fichier .idx en un fichier .ind. Ouvrons le fichier .idx pour comprendre comment cela.

À côté de ligne sans qui ne posent pas de soucis telle que :

\indexentry{chat!sauvage|hyperpage}{1}

Nous y trouvons la ligne problématique :

\indexentry{chat!sauvage|hyperindexformat{\textbf}}{3}

Et nous voici en face de deux limites de xindy [1] :

  • alors que makeindex transforme toute syntaxe de type |xxx en la commande correspondante, il n’en va pas de même avec xindy, qui nécessite qu’on lui déclare ces commandes manuellement. En effet, xindy, qui n’est pas conçue uniquement pour LaTeX, considère que la syntaxe |xxx après une entrée dans le fichier .idx correspond à un attribut de localisation, c’est à dire une propriété associée à la localisation d’une entrée. Certains de ces attribut de localisation sont déclarés dans le fichier base/latex-loc-fmts.xdy que texindy charge par défaut.
  • ces attributs ne peuvent pas recevoir d’arguments. Ainsi, même si nous déclarions hyperindexformat, cela ne nous arrangerait pas. En effet, les commandes avec arguments sont considérés par \xindy comme des marqueurs de renvois au sein de l’index, alors que makeindex est plus souple sur la question.

Solution

Comment résoudre ce problème ? En demandant à hyperref de ne pas intervenir dans la gestion du .idx et en gérant nous même cela via le fichier de configuration .xdy

Désactiver la modification de l’index par hyperref

Il suffit simplement de charger le package avec l’option hyperindex=false :

\usepackage[hyperindex=false]{hyperref}

Vous constaterez alors que le fichier .ind ne contient plus que des lignes de type :

\indexentry{chat!sauvage}{1}

et

\indexentry{chat!sauvage|textbf}{3}

qui sont très bien interprétés par xindy, mais sans évidemment que les liens hypertextes ne soit intégrés.

Configuration de xindy

Pour résoudre ce problème, il nous suffit d’ajouter dans le fichier de configuration .xdy les lignes suivantes :

La première ligne permet de définir l’attribut emph qui n’est pas défini par défaut dans texindy alors qu’il est plus sémantique que l’attribut textit.

Dans les quatres lignes nous réglons la propriété markup-locref pour l’attribut de localisation indiqué entre guillemets après le :attr, sachant que l’attribut defaut est – comme son nom l’indique – celui utilisé si aucun attribut n’est mentionné.

Pour chaque attribut nous définissons via :open un marqueur à insérer avant la localisation, et via :close nous définissons un marqueur à insérer après la localisation.

Avec un tel système, notre fichier .idx deviendra un fichier .ind contenant des lignes telles que

\subitem sauvage\dotfill \hyperpage{1}--\hyperpage{2}, \textbf{\hyperpage{3}}

Ce qui est parfaitement compris par LaTeX lors de compilation suivante, \hyperpage insérant un lien hypertexte vers une page.

Cela nous permet d’obtenir le fichier ci-dessous, contenant de liens internes, y compris en gras.

xindy + hyperref + |textbf exemple qui fonctionne

Notes

[1Bien tenues par rapport à ses avantages, puisqu’on peut facilement les contourner.