Documentation

Automatiser la génération de
documentation
L'automatisation a normalement pour but de faire gagner du temps ou de simplifier des choses.
Mais je m’en fiche — je le fais parce que le processus est farfelu et que j’aime le défi. De plus, beaucoup de logiciels manquent de documentation explicative, notamment les miens.
Je souhaite décrire les outils que j'utilise pour générer rapidement et à grande échelle de documentation logicielle. Les objectifs sont divers, et je ne suis pas sûre des priorités dès le départ. C'est pourquoi je le considère comme un “Work in Progress” jusqu'à nouvel ordre.
Les fichiers que je crée nécessitent une séquence particulière de programmes, mais vous pouvez considérer la chaîne d'outils présentée ci-dessous comme une pile d'utilitaires et de techniques. Certains logiciels sont décrits séparément, et vous pouvez d'en choisir uniquement ceux qui répondent à vos besoins. Je propose également des alternatives à la fin de la page pour ceux qui souhaitent explorer d'autres options.
Aujourd’hui, je peux écrire un seul fichier texte, lancer une seule commande dans le terminal et obtenir plusieurs fichiers différents. Le document original, au format reStructuredText (reST), est converti directement en page man et en fichier HTML. Ensuite, le HTML sert de base pour générer un PDF.
Certains outils de cette chaîne sont standards (par exemple
rst2html5
, rst2man
), tandis que d’autres sont des
scripts personnalisés (manheader
, htidy
,
make_doc
). Cette chaîne est conçue pour mon usage
personnel et peut ne pas être portable ni reproductible dans
d’autres environnements.
| Un fichier au format reStructuredText est écrit dans n’importe quel éditeur de texte simple (pas dans un traitement de texte). | Vim |
Exemple : flnews_post_proc.rst (reStructuredText) |
Le seul autre outil que j’utilise directement depuis la
ligne de commande est un petit script shell personnel,
make_doc. Je le lance dans un dossier donné, et il y cherche tous les fichiers reST pour les traiter un par un. |
make_doc
(Mon script) ↓ |
|
make_docappelle rst2manafin de produire une page man à partir du fichier original au format reStructuredText. |
rst2man (Docutils) ↓ |
|
Il manque encore, dans la page man générée par
rst2man, les valeurs des champs date,
section, version et
category. Bien que rst2manpuisse en définir quelques-uns automatiquement, je préfère vérifier qu’ils sont tous bien présents en appelant mon ruby-script manheader. |
manheader (Mon
script) ↓ |
|
| La page finale est comprimée avec gzip. | gzip (GNU) |
Exemple: flnews_post_proc.1.gz (man page) |
make_docappelle rst2html5qui produit un fichier HTML. J’impose que le code d’une feuille de style explicitement nommée soit intégré. |
rst2html5
(Docutils) CSS (feuille de style) ↓ |
|
Pour normaliser le HTML5 généré et améliorer la
conformité avec XHTML5, j’utilise HTML Tidy. Un petit
script htidyrassemble certaines déclarations et paramètres de configuration. |
htidy (Mon script) ↓ |
Exemple: flnews_post_proc.html |
Pour la création d’un fichier PDF, je lance Apache
FOP sur le fichier HTML créé précédemment, en
utilisant une feuille de style XSL-FO préparée soit pour
le projet, soit pour un usage général. Dans
l’environnement FOP/Java, deux actions sont exécutées, et
il semble normal qu’il n’existe pas encore de réponse
simple à la question qui fait quoi:
|
FOP
(Apache) stylesheet.xsl (feuille de style XSL-FO) html2Pdf.xsl (feuille de style XSL-FO ) ↓ |
|
| Le premier PDF est converti en un nouveau, revendiquant la compatibilité avec la version 2.0, à l’aide de Ghostscript. | ghostscript (Artifex) manuel en Français ↓ | |
| Quelques champs de métadonnées sont ensuite paramétrés avec l’outil cpdf | cpdf (Coherent Graphics) |
Exemple : flnews_post_proc.pdf |
J’ai choisi des procédures qui me laissent une grande
liberté pour mettre en forme les documents finaux comme je
l’entends. Compte tenu de la diversité des outils disponibles,
j’ai d’abord dû déterminer lesquels répondaient réellement à
mes besoins.
Puis, après en avoir pesé les qualités et les limites, j’ai
organisé leur interaction et ajusté leur configuration par
essais et erreurs, jusqu’à obtenir un résultat acceptable.
Vous pouvez toujours saisir n’importe quel outil, lui fournir votre contenu et vous satisfaire du résultat imposé par défaut. Mais si vous voulez contrôler l’apparence des documents finaux, vous constaterez que l’individualisme a un prix : faciliter une tâche implique généralement de renoncer à certaines libertés.
Au début, je ne m’intéressais pas aux outils ; je voulais simplement des documents à peu près lisibles et – pourquoi pas – agréablement mis en forme.
Le document HTML généré est mis en forme à l’aide d’une feuille de style CSS externe que je maintiens. Il existe une feuille de style de base, d’application générale, qui peut être utilisée telle quelle ; dans d’autres cas, elle est adaptée aux besoins d’un projet particulier. Chaque document fait donc référence à une feuille CSS spécifique au projet, modifiée ou non.
Le document HTML est généré directement à partir de la
source reStructuredText à l’aide de rst2html5
,
un outil fourni par le package Docutils. J’exécute ensuite HTML
Tidy sur le résultat — principalement pour normaliser et épurer
le balisage avant la conversion en PDF.
Cette commande génère du HTML à partir de reST. Les options
de rst2html5
sont listées lorsque vous exécutez le
programme avec l’argument habituel --help. Je ne les détaille
pas ici.
capitalizeest un script Ruby que j’ai écrit pour me rappeler cette ligne de code :
puts ARGV.collect {|w| w.capitalize}.join('
')Le fichier crée de cette manière est basé sur un modèle qui établie la structure du code HTML. Vous pouvez vous contenter du modèle par défaut. Ceci est installé avec docutils mais il peut être utile d'écrire votre propre modèle. Le texte suivant est un modèle tout à fait complet, qui ajoute à la partie <head/> du code HTML les meta-balises pour le préchargement des polices et pour un favicon:
%(head_prefix)s
<rlink rel="preload" as="font" crossorigin=""
href="https://my_site/fonts/Classica/Classica-Book.ttf" type="font/ttf" />
<link rel="preload" as="font" crossorigin=""
href="https://my_site/fonts/Classica/Classica-Bold.ttf" type="font/ttf" />
<link rel="preload" as="font" crossorigin=""
href="https://my_site/fonts/Classica/Classica-BookOblique.ttf" type="font/ttf" />
<link rel="preload" as="font" crossorigin=""
href="https://my_site/fonts/Fertigo_PRO.otf" type="font/otf" />
<link rel="icon" type="/image/x-icon" href="images/favicon_Schreibfeder.ico" />
%(head)s
%(stylesheet)s
%(body_prefix)s
%(body_pre_docinfo)s
%(docinfo)s
%(body)s
%(body_suffix)s
Si vous avez une feuille de style pour la définition des polices, vous devrez l'ajouter ce fichier à l'option stylesheet de rst2html5, ensemble avec votre modèle:
Tidy veille à ce que le code HTML soit produit dans un style
XHTML (plus ou moins, selon le prestige momentané du Living Standard
) et supprime la
déclaration DOCTYPE, qui interférerait autrement lors de
l’appel ultérieur à FOP pour la génération d’un
PDF.
Mon PDF intègre des sous-ensembles de polices et ressemble beaucoup à la sortie HTML. En revanche, toute la mise en forme doit être codée dans la feuille de style XSL-FO. Lorsque FOP est invoqué, deux transformations sont effectuées successivement. Il est donc plus juste de parler d’un processeur XSL-FO.
Une autre caractéristique du fichier PDF est la présence
d’une arborescence de signets. C'est la structure arborescente
qui peut être affichée à la place des vignettes des pages dans
la barre latérale du lecteur PDF. Elle vous permet de naviguer
dans le document sans devoir revenir à la table des matières
ou à un élément
équivalent. Cette structure est définie explicitement dans la
feuille de style XSL-FO. J’ai choisi un code réutilisable dans
différents projets et je n’investis pas de temps ni d’effort
supplémentaires dans la régénération de l’arborescence de
signets chaque fois que des chapitres sont supprimés, ajoutés
ou renommés. Beaucoup d’exemples que je trouve sur le Web ne
sont pas écrits ainsi. Les auteurs ont plutôt choisi de cibler
directement des titres de chapitres. Mais cela n’est guère
pratique lorsqu'il faut modifier ces titres ou les déplacer. Ma
première version d’une telle arborescence de signets dynamique
date d’avant 2010. À
l’époque, j’étais rémunéré pour son développement. Que cette
possibilité soit encore largement ignorée me surprend beaucoup.
Utiliser une technologie conçue pour l’automatisation, pour
ensuite en contrecarrer l’objectif, remet en question la valeur
même d’une telle technologie.
Pour des raisons de sécurité, FOP refuse par défaut les feuilles de style imbriquées. Une fois ces options activées, elles sont de nouveau acceptées. Ceux d’entre vous qui apprécient un défi conceptuel peuvent ajouter des options à FOP afin de confier la première étape de la transformation XSL-FO à un autre processeur XSL. Vous saurez ainsi — une bonne fois pour toutes — quel outil fait quoi.
J’utilise une version récente d’Apache FOP que j’ai installée dans mon répertoire personnel. Bien qu’il s’agisse de la seule version installée sur cet ordinateur, je souhaite éviter tout conflit éventuel si elle devait un jour coexister avec une version plus ancienne provenant des dépôts Debian.
-dEmbedAllFonts=true
-dSubsetFonts=false -dPDFSETTINGS=/prepress \Cet appel à Ghostscript convertit le premier fichier PDF en un format qui devrait se rapprocher autant que possible de la version 2.0 du standard PDF. Il supprime également la balise de métadonnées XMP, qui n’est pas nécessaire dans ce type de fichier PDF (je sais qu’elle ne l’est pas — mais vous pourriez aimer XMP pour une raison insondable). Pour une conformité complète avec PDF 2.0, d’autres outils seraient nécessaires.
"$PDF"
-set-creator "$VIM, $DOCUTILS" AND \cpdf
est un autre outil puissant, mais je ne
l’utilise que pour attribuer des valeurs raisonnables à
quelques champs de métadonnées (hors XMP). Ghostscript (voir
plus haut) peut le faire également, à l’exception du champ
Producer
. Avec
cpdf
, il est possible de copier des métadonnées XMP
depuis un fichier, mais je considère cet effort inutile pour le
moment — et je tiens XMP pour un standard idiot.
Les fichiers de documentation peuvent être créés de bien d’autres manières que celles décrites ci-dessus.
Vous pouvez générer un PDF directement en
utilisant l’un des outils appelés rst2pdf
. L’un
fait partie du paquet Docutils, l’autre est un projet
totalement indépendant. Je n’aime pas le rendu produit par
l’outil fourni avec Docutils.
Si vous n’avez pas encore décidé quelle technologie utiliser, vous pouvez éventuellement essayer l’outil disponible sur rst2pdf.org. Il permet de définir des feuilles de style personnalisées. Ces feuilles de style sont des fichiers en texte brut au format YAML.
Comme vous l’avez remarqué dans la description de la chaîne
d’outils plus haut, j’écris déjà des
feuilles de style CSS pour le HTML et des feuilles de style XSL
pour les PDF. Bien que j’aie déjà écrit du
YAML pour la configuration de logiciels, cela commence à
ressembler à un joyeux zoo de langages de style. Je me limite
pour le moment au XSLT et n’inclurai pas rst2pdf
dans ma
chaîne d’outils. Les transformations XSL-FO sont ce que je
connais le mieux lorsqu’il faut automatiser la production de
PDF.
Si vous voulez utiliser une version open source et récente du
processeur XSLT et XQuery Saxon,
peut-être parce que vous avez besoin de XSLT 3.0 ou parce que
la manière dont FOP transforme tous les <xsl:message/> en
Warning
vous dérange,
une manière simple de remplacer
le processeur XSL
(peu importe ce que cela signifie), consiste à l’exécuter avec
le fichier d’entrée comme argument afin de produire un fichier
FO, puis à appeler FOP uniquement pour la conversion finale du
fichier FO en PDF. Pas de bricolage avec le classpath, les
options Java ou la définition des FOP_OPTS, mentionnée plus
haut.
Cette commande appelle le processeur Saxon sur le fichier d’entrée infile.html et produit un fichier FO, en appliquant les règles de mise e forme définies dans stylesheet.xsl. Vous pouvez passer des valeurs de variables au processus XSLT, comme loglevel, si la feuille de style les définit en interne. Le résultat peut ensuite être transmis à FOP pour la production d’un fichier PDF.
La bibliothèque LibTIFF
est accompagnée de quelques programmes
utilitaires qui transforment des images au format TIFF en
PDF. Ces fichiers ne peuvent pas être modifiés autrement qu’au
moyen d’un logiciel graphique.
Cela ne suffit pas à justifier la procédure. Mais il n’y aura
pas non plus de problèmes d’affichage sur des ordinateurs qui
ne disposent pas des polices nécessaires, ni avec des
imprimantes qui auraient du mal à gérer certains glyphes si la
police est intégrée dans un fichier PDF.
Selon vos habitudes et votre expérience, les fichiers créés
avec les outils LibTIFF seront plus grands ou plus petits. Un
traitement de texte, par exemple, peut intégrer beaucoup
d’informations dans un fichier PDF, dont certaines inutiles ou
redondantes. Dans ce cas, transformer chaque page d’un fichier
PDF en image, puis à nouveau en fichier PDF, peut réduire
considérablement la taille du fichier.
D’autre part, un PDF généré par une transformation XSL-FO,
comme décrit plus haut, est déjà très petit, surtout s’il ne
contient pas d’images supplémentaires. Ici, la conversion vers
des images, puis à partir de celles-ci, peut faire exploser la
taille du fichier jusqu’à plusieurs fois celle du fichier
d’origine.
Cet appel à gs
crée une image Tiff pour chaque page
du fichier PDF infile.pdf
.
Si le fichier PDF était
flnews_post_proc.pdf, le résultat serait 7 fichiers Tiff,
chacun portant un suffixe numérique indiquant la position de la
page correspondante dans le PDF.
tiffcp
assemble un fichier Tiff multicouche
à partir de tous les fichiers Tiff créés précédemment.
Enfin, à partir de toutes les pages transformées en images,
puis en couches d’un grand fichier TIFF, un nouveau fichier PDF
est créé. L’argument -z
de
tiff2pdf
impose l’application d’une compression
ZIP. Comme indiqué précédemment, si le fichier PDF original
était très petit, celui créé à partir des images peut devenir
extrêmement grand : la nouvelle version flnews_post_proc_b.pdf est un
fichier de 1,6 M, soit 18 fois la taille de celui généré avec
XSL-FO.
Pour beaucoup de gens, écrire
quelque chose
signifie utiliser un traitement de
texte.
Et la majorité des personnes qui savent rédiger une
documentation parfaitement structurée et compréhensible ne sont
pas des passionnés d’informatique et ne souhaitent peut-être
pas maîtriser une pile technologique comme celle que je
présente sur cette page.
La bonne nouvelle est que les traitements de texte écrivent aujourd’hui du XML, sauf indication contraire. Chaque traitement de texte peut avoir un type de fichier considéré comme standard, mais la plupart peuvent également produire d’autres formats XML.
OOXML. Les fichiers ont normalement l’extension docx et sont compressés. Lorsqu’on extrait un fichier de ce type, le contenu textuel se trouve dans le fichier document.xml du sous-répertoire
word.
Open Document Format. L’extension des fichiers est odt. Ces fichiers sont normalement compressés au format ZIP ; après extraction, le contenu textuel se trouve dans content.xml.
Tous les programmes listés ci-dessus peuvent écrire des fichiers au format OOXML (docx) et ODF (odt).
Pendant que la majorité des traitements de texte — peut-être tous — font un bon travail pour l’export en PDF, les pages de manuel (man) sont pour eux un univers étranger. Le choix d’un format XML, pourtant, laisse la possibilité de convertir les productions des traitements de texte en tout ce que vous voulez…
Vous pouvez — par exemple — transformer un fichier AbiWord en instructions de composition Troff, et donc en page de manuel. Bonne chance avec ça ! (Je ne doute pas une fraction de seconde qu’il existe des personnes qui prétendent que coder en Troff est la seule manière acceptable d’écrire des pages de manuel.)
Mais vous pouvez aussi, tout simplement, produire du reStructuredText à partir de l’un des formats XML listés ci-dessus. Comme vous y êtes, vous pouvez identifier des parties du document original qui ne doivent pas être incluses dans la documentation pour l’utilisateur final, et encourager l’auteur à se servir des formats de paragraphes et de caractères dédiés à la communication des explications à un potentiel traducteur.
Voici un exemple de code XML produit par AbiWord : flnews_post_proc.abw, et
voici la feuille de style XSLT : abw2reST.xsl. Lorsqu’on les présente
au processeur XSL Saxon, ils deviennent ce document
reStructuredText : test.rst.
Notez que, encore une fois, la déclaration DOCTYPE doit
être supprimée dans le document d’entrée.
Notez que AbiWord peut convertir des documents au format XSL‑FO, et ainsi vous épargner de la moitié du travail pour la production d'un fichier PDF. Cependant le succès de cette opération dépend de la manière comment le document d'origine est rédigé et mis en page : Lors de mes propres tests, AbiWord a souvent planté et n'a pas généré de fichier XSL-FO
Lorsque divers documents sont basés sur le même modèle, ces
modèles sont détectables dans les fichiers XML résultants.
Plusieurs transformations en reStructuredText (et en pages de
manuel) peuvent alors bénéficier du même travail préparatoire
et de la même feuille de style XSL. Il n’est jamais nécessaire
de connaître les définitions précises des mises en forme
configurées dans le traitement de texte d’origine. Tout ce qui
est nécessaire est le nom d’un style afin de reconstituer la
structure d’un document. La feuille de style XSL n’a pas besoin
de reproduire les styles du traitement de texte.
En même temps, comme les feuilles de style peuvent être
imbriquées, rien ne vous empêche de préparer un traitement
spécial pour quelques documents, indépendamment du modèle dont
ils sont dérivés.
Vous pouvez toujours demander à une IA de convertir tout ce que vous voulez en TROFF et en être fier.