Adoptez la Documentation as Code avec AsciiDoc

Sommaire
- Introduction
- Documentation : le changement d’outillage, et l’émergence de Confluence
- Guide étape par étape : écrire de l’AsciiDoc pour générer de la documentation Confluence
- Des outils d’édition, de rendu et de conversion pour AsciiDoc
- Perspectives et enseignements tirés d’asciidoc
- Annexes
Introduction
Dans beaucoup de projets rencontrés lors de mes missions, la question de la documentation était traitée en second plan, après le développement. Les salariés plutôt « fonctionnels » y accordaient une grande importance, mais les développeurs le voyaient comme une tâche ingrate, voire comme une corvée. Cela s’est accentué avec l’agilité, car l’une des 4 grandes valeurs du manifeste Agile rappelle qu’il faut un «logiciel opérationnel plus qu’une documentation exhaustive».
Pour autant on constate souvent le besoin de regrouper à minima dans un même endroit les règles métiers d’un logiciel (on pourra dire aussi les capacités) et un descriptif des cas particuliers (explication du fonctionnement précis du logiciel dans un cas non nominal). En tout cas, en tant que lead dev, je n’aime pas devoir signaler à un utilisateur (testeur ou client) : pour savoir ce que le logiciel fait, il faut regarder le code source. Je préfère lui indiquer : on est dans cas où la règle PORT_ECRAN_28-1 s’applique.
Dans cet article je détaille une solution de documentation nommée AsciiDoc, accessible à des développeurs, et qui via un plugin maven nommé confluence-publisher, peut être exportée vers Confluence. Cette capacité permet d’obtenir un emplacement unique pour la documentation technique, fonctionnelle et opérationnelle d’un logiciel.
Je détaille la syntaxe, les qualités, parfois les bizarreries, et surtout le résultat.
J’explique plus globalement pourquoi une démarche « docs-as-code » (à l’instar de « Infrastructure-as-Code ») est nécessaire pour un logiciel.
Documentation : le changement d’outillage, et l’émergence de Confluence
D’aussi loin que je me souvienne
Petit, je me souviens d’un oncle qui travaillait en développement (pour le centre de recherche de France Télécom), et le code source en C était optimisé et parfaitement lisible, et les spécifications rédigées dans des traitements de texte et imprimées. On avait l’impression d’une grande qualité dans tout ce qui était produit (je dis impression car je n’ai pas analysé finement, mais vu leurs réalisations, je pense qu’ils étaient très pros).
Je vais faire un saut de 20 ans et arriver sur mes années de développement dans une vingtaine d’équipes de développement (débutant, puis lead tech seul ou à plusieurs).
J’ai pu constater que les spécifications techniques étaient rédigées le plus souvent en Word.
Les spécifications fonctionnelles sont historiquement en Word, parfois en SharePoint désormais, mais la tendance récente est de tout regrouper dans Confluence, quitte à mettre des documents Word (ou leurs exportations en PDF) en pièce jointe des pages.
Eh oui, depuis plus de 5 ans, la solution Confluence semble se dégager nettement. Car il n’y a pas de problème de droits en écriture, d’écriture partagée et de document verrouillé par un autre, de mise en forme incompréhensible (numérotation, blocs qui se décalent, tableaux compliqués). Bref il est simple à utiliser, et le résultat est beau.
A noter que l’éditeur de Confluence est Atlassian, qui édite la solution elle aussi populaire « Jira ».
Introduction à Confluence : les points essentiels
Confluence est, rappelons-le, une solution d’hébergement et d’édition intégrée de documentation.
Il permet de créer des pages et d’y ajouter des pièces jointes (presque tous les formats sont autorisés). L’éditeur est intuitif, rendant l’utilisation accessible aux non-développeurs contrairement aux langages de type Wiki.
Les pages et leurs pièces jointes sont historisées, ce qui évite les pertes de contenu dues à des corruptions de fichiers. Je n’ai jamais entendu quelqu’un se plaindre « j’ai tout perdu » grâce à cette fonctionnalité.
La navigation entre les pages se fait automatiquement via un menu situé à gauche. Confluence dispose également d’un outil de recherche interne puissant qui permet de trouver rapidement les contenus en fonction des mots-clés (tags), du contenu des pages ou des pièces jointes.
Voici quelques-unes des nombreuses autres fonctionnalités offertes par Confluence :
- Un menu automatique,
- Des libellés (tags) ajoutés aux pages,
- Des blocs de code source,
- Des inclusions de pages,
- Des blocs en accordéon,
- Des liens vers les tickets JIRA (récupération en temps réel du titre, et du statut),
- Des blocs d’alertes (avec automatiquement une icône ⚠️ ou ℹ️…),
- Des diagrammes (avec désormais un bon éditeur intégré),
- La possibilité d’avoir des pages privées.
Confluence pour la documentation technique
Selon moi une bonne documentation technique doit être bien structurée (un sommaire), facile à trouver, facile à modifier, inclure du code source, des tableaux (plus facile à lire que des longues phrases) et des schémas.
Il faut aussi pouvoir poser des labels et des résumés des pages pour comprendre leurs contenus sans les parcourir.
Tout ceci est directement intégré dans Confluence.
La démarche Documentation as code (docs-as-code)
Documenter, pour les développeurs
De façon personnelle,
- J’ai connu le temps de la Javadoc systématique, et de son déploiement via des outils comme DelphiDoc (un programme de génération de documentation pour les projets Delphi, à partir de la Javadoc)
- J’ai noté que, avec le Craft et le “Clean Code”, on recommande de ne pas toujours documenter une méthode.
- Les développeurs ne connaissent pas tous les diagrammes UML (pourtant bien utiles pour expliquer des algorithmes).
Il me semble qu’il est nécessaire d’arriver à une évolution saine de la perception de la documentation : ni trop, ni trop peu. Et pour moi la “documentation as code” le permet.
Mais au fait c’est quoi “documentation as code” ?
La « documentation as code » consiste à traiter la documentation comme du code source. Voici ce que cela implique :
- Utilisation de langages de balisage léger : Au lieu d’utiliser des éditeurs comme Word, on utilise des langages simples comme Markdown. Cela permet de se concentrer sur le contenu sans se soucier de la mise en page.
- Stockage dans des outils de gestion de code source : La documentation est enregistrée avec le code, généralement sur des plateformes comme Git. Cela permet de suivre les modifications et de collaborer facilement.
- Les développeurs rédigent la documentation : Souvent, ce sont les développeurs qui écrivent la documentation, car ils connaissent le mieux le logiciel.
- Intégration dans la chaîne d’intégration continue (CI/CD) : Comme la documentation est traitée comme du code, elle peut être testée et mise à jour automatiquement avec le logiciel.
Les avantages
Selon moi, les avantages de la “documentation as code” sont :
- Pouvoir partager la responsabilité de la documentation avec une relecture croisée (Merge Request ou Pull Request). Attention, en mode comparaison avant-après, on peut comparer la source “AsciiDoc”, pas son rendu. J’espère que l’évolution des outils Github et Gitlab le permettra dans l’avenir.
- Conserver un historique des modifications.
- La documentation est associée au code source, donc si l’on n’intègre pas l’évolution de code source au livrable (“Merge de la branche feature sur la branche develop”), on n’intègre pas non plus l’évolution de documentation.
- On a un outil qui permet facilement de vérifier que la documentation est réalisée en même temps que le développement, et on peut donc inclure “documentation technique réalisée” dans le Définition of Done (DoD) de la tâche de développement.
- La documentation ne peut pas être perdue, car elle est intégrée au gestionnaire de version du code source.
- La même documentation peut être exportée sous plusieurs formats : HTML, PDF, Word, Confluence, manpage (pour les linuxiens)…
- La présence de modifications dans la documentation technique est vérifiable par le responsable d’application, ou par le Producteur Owner si l’on est en mode de projet Agile.
La documentation apporte de la valeur. Elle fait partie du produit.
Au-delà des avantages mentionnés ci-dessus, l’essentiel est surtout que la documentation soit considérée comme “faisant partie du logiciel” car apportant autant de valeurs au projet que de nouvelles fonctionnalités, ou que des correctifs.
Je mentionne ceci non pas comme un principe abstrait, mais car j’ai pu constater que désormais les personnes qui fabriquent un programme sont rarement celles qui le maintiennent : les programmes sont souvent “transférés” vers des TMA; ou alors les programmes sont transférés d’une équipe à l’autre, et la documentation technique de départ n’est pas actualisée convenablement car les personnes chargées des évolutions ne s’en sentent pas responsables, considèrent la documentation existante comme pas à jour, ou car elles n’ont pas les outils de modification ou pas les accès.
Et donc, selon moi, la “documentation as code” améliore la maintenance du logiciel.
Quand et pourquoi a été créé AsciiDoc
Mais au fait, d’où vient AsciiDoc ? Un peu de généalogie.
- LaTeX est apparu vers 1980 et a été très utilisé pour les publications scientifiques. Je l’avais utilisé pour la rédaction d’un rapport de stage, et j’ai été marqué par la précision du rendu syntaxique mais aussi par la difficulté pour faire un document complet et riche. Bref trop beau mais trop compliqué au quotidien.
- DocBook, pensé vers 1991 par l’Open Software Foundation pour écrire les manuels UNIX. L’objectif était de rédiger des livres ou des manuels, séparant totalement le texte de sa mise en forme. Ainsi, dans sa version de base, DocBook n’a pas de balise pour le gras, mais uniquement pour l’italique (<emphatize>…</emphatize> qui signifie “mettre en avant”).
- OpenDocument, toujours pensé par l’Open Software Foundation, est destiné à créer des documents, dans un format directement lisible dans l’éditeur. On mélange donc le contenu et la mise en forme (gras, italique, souligné, couleurs…). OpenDocument est basé sur le XML.
C’est toujours dans cette approche de simplification que 2 langages de balisages sont apparus quasi-simultanément :
- AsciiDoc, en 2002, est en quelque sorte le fils spirituel de DocBook (cette formule n’engage que moi) car il est destiné à créer des manuels techniques.
- Markdown, en 2004, a pour objectif d’être le plus léger possible : il est plus simple et destiné davantage à des documents.
Portrait robot de AsciiDoc
AsciiDoc a été créé en 2002 par Stuart Rackham.
Il repose sur des fichiers “plats” (que l’on peut voir dans un éditeur de texte) qui possèdent l’extension “.adoc”.
Ces fichiers ont une syntaxe qui inclut un langage de balisage (en anglais “markup”) : par exemple *frite* est affiché avec du gras, donc frites .
Le traitement qui transforme les fichiers .adoc en rendu (par défaut en HTML) se nomme Asciidoctor. On peut parler de compilation.
Asciidoctor a été écrit en ruby (c’est une réécriture de AsciiDOc.py écrit en python).
Il peut être exporté, et cette liste n’est pas exhaustive, en HTML5, PDF, DocBook 5, EPUB et les “manpage” Unix.
Et si on comparaît AsciiDoc avec Markdown ?
Avec du recul je considère que les 2 produits sont très différents, mais au départ ça n’est pas évident.
Pour commencer, on peut mentionner que pour obtenir la même chose, AsciiDoc est soit aussi concis que Markdown, soit plus (le plus souvent).
AsciiDoc est orienté “documentation complète” donc proposera (nativement) la pagination, le sommaire, les renvois…
AsciiDoc est beaucoup (beaucoup) plus complet en terme de fonctionnalités : définir des variables, inclure du code source depuis un fichier externe, avoir un accordéon (titre cliquable avec détail)…
Certaines de ces fonctionnalités sont disponibles sous forme d’extension à Markdown, alors qu’elles sont directement intégrées dans AsciiDoc.
Asciidoctor peut faire des diagrammes
Comme toute solution évoluée, Asciidoctor a ses extensions, même si en l’occurrence presque tout est nativement présent dans Asciidoctor. Mais j’ai dû ajouter l’extension AsciiDoctor Diagram pour les schémas (asciidoc-diagram), notamment les diagrammes UML avec PlantUML.
AsciiDoctor Diagram regroupe une quinzaine de langages (GraphViz, AsciiToSVG, PlantUML…) permettant de générer des schémas à partir de code source brut.
Un petit regret cependant : certains des éditeurs/visualiseurs (voir le chapitre 3) ne gèrent que Asciidoctor, mais pas cette extension Asciidoctor Diagram.
La solution : un plugin maven (ou Gradle) pour générer des pages HTML Confluence depuis Asciidoc
Asciidoctor, moteur de compilation et d’export des fichiers .adoc , n’a pas été prévu pour exporter vers Confluence.
Il convient d’utiliser un plugin maven nommé “confluence-publisher”. Il s’agit d’un logiciel libre (sous licence Apache 2) apparu en 2016. La version actuelle (en avril 2024) est la 0.22.0 qui est compatible avec Confluence 6.0.5 (2017).
Confluence Publisher repose sur la transformation des pages HTML5 (générée par Asciidoctor) en XHTML qui est le format de Confluence.
La grande majorité des capacités de Asciidoctor sont prises en charge dans les exports (elles sont détaillées dans le chapitre 2) : les inclusions, les sections, les mises en forme, les tableaux, les images, les listes, les admonitions, les liens, les diagrammes PlantUML (ouf !), les pièces jointes, les tables des matières, et quelques fonctionnalités avancées.
La prise en charge est réelle : par exemple une pièce jointe (un lien vers un élément externe, voir en 2.1) dans un fichier AsciiDoc sera convertie en pièce jointe dans Confluence.
Je recommande de parcourir la page officielle pour connaître ce qui est supporté (et du coup on peut déduire ce qui ne l’est pas).
Attention danger : peu de contributeurs sur ce plugin maven
Hébergé sous github, le projet « confluence-publisher », né en 2016 et écrit en Java, n’a actuellement qu’un seul contributeur/intégrateur important (Christian Stettler, architecte sénior, suisse), et une poignée de personnes qui proposent des correctifs.
J’ai pu retrouver dans la liste des anomalies connues beaucoup des dysfonctionnements que j’avais constaté. La plupart « traînent » depuis longtemps, sans qu’il soit probablement prévu de réellement les corriger.
Parmi les bugs constatés :
- Les admonitions WARNING et CAUTION ont le même rendu (anomalie 210 )
- Le surlignage (jaune fluo) #texte# ne montre pas de surlignage.
- Le barré [line-through]#texte# ne fonctionne pas.
- Les cases à cocher sont affichées sous forme d’une liste, sans les ▯
- Les renvois de bas de pages footnote ne fonctionnent pas.
- Pour PlantUML, il faut éviter le caractère inférieur. on devra donc mettre le supérieur et inverser les ordres. B <- A devient A -> B
Il ne faut donc pas s’attendre à de véritables évolutions, sauf à espérer l’arrivée de sympathiques et compétents bénévoles, ou un fork du projet. C’est la joie et la malédiction des projets open-source.
Plus les plus curieux, voici le code source et le détail des contributions du projet.
Guide étape par étape : écrire de l’AsciiDoc pour générer de la documentation Confluence
L’objectif ici est de générer une documentation complète, avec plusieurs pages, des inclusions de code source… et de l’exporter dans Confluence
Rédaction des pages au format AsciiDoc
Les premiers éléments de votre page (résumé, sommaire, mots clés et auteur) :
Une bonne page est selon moi constituée d’un résumé (permettant de connaître rapidement son contenu et à qui elle est destinée) et un sommaire.
Cela se fait par l’utilisation d’un bloc [.lead] et d’un bloc .tod .
Sur un sommaire, on définira le niveau de hiérarchie que l’on veut afficher. Par exemple : uniquement les titres 1, les titres 1 à 2, les titres 1 à 3…
Pour les mots clés, rien de plus simple : on utilise « keywords ». Afin d’être cohérent avec Confluence (c’est développé plus tard dans cet article), et sachant que Confluence convertit automatiquement les tags en minuscules, on choisira d’utiliser uniquement des mots clés simples, en minuscule, sans caractères accentués et séparés éventuellement par des tirets. L’anglais est bienvenu, mais c’est un choix du projet. Par exemple « glossary-article ».
La paternité, c’est important, et l’on mentionne l’auteur (avec son mail) de la page courante (il existe plusieurs façon de faire, mais la redéfinition des “attributs intégrés” author et email est celle qui fonctionne dans tous les visualisateurs, et dans l’export vers Confluence).
Si je regarde en syntaxe AsciiDoc ce que ça donne, nous aurons :
= Démonstration du Plugin Confluence AsciiDoc
:author: Christian
:email: <christian@mondomaineamoi.fr>
toc: macro
// toclevels : (de 1 à 5)
toclevels: 3
:sectnums:
:partnums:
// Les mots clés doivent être en minuscule, séparés par des - et sans caractères accentués
:keywords: asciidoc confluence-publisher
[.lead]
Cette page a pour objectif de vérifier le bon fonctionnement de confluence-publisher qui génère des pages AsciiDoc vers Confluence. *rendu confluence OK du résumé de la page*
.Sommaire
====
toc::[]
====
Les inclusions de page (permet de séparer les pages)
Pour moi l’inclusion de page est trop peu utilisée, alors qu’elle permet de reprendre le même contenu plusieurs fois, sans le dupliquer (Dont Repeat Yourself). Elle se fait facilement avec Asciidoc.
Page principale :
=== Inclusion de fichier
include::chapitre_01.adoc[]
chapitre_01.adoc :
Ceci est le texte de la page chapitre 1.
Le rendu
C’est grâce à ce mécanisme que l’on peut aussi structurer le document sous forme de plusieurs chapitres qui sont chacun des fichiers .adoc séparés (évidemment l’inclusion d’inclusion est possible) :
Page principale :
== Manuel utilisateur
include::introduction.adoc[]
include::chapitre_01.adoc[]
include::chapitre_02.adoc[]
include::chapitre_03.adoc[]
include::conclusions.adoc[]
include::annexe.adoc[]
chapitre_01.adoc :
include::chapitre_01-1.adoc[]
include::chapitre_01-2.adoc[]
include::chapitre_01-3.adoc[]
Les sections (reposent sur les titres)
On aurait tendance à associer les = aux titres ( = correspond au titre 1, == au titre 2, et ce jusqu’au titre 6).
C’est un peu plus compliqué que cela, car il faut comprendre que nous sommes dans un document structuré : les sections sont des parties du document dont la déclaration se fait en posant un titre.
Ceci à une petite conséquence : pour un document “Article doctype”, il ne peut y avoir qu’une section de niveau 1. Pour un document “Book doctype”, on peut en avoir plusieurs.
Article doctype
= Titre du document (section niveau 0)
== Section niveau 1
=== Section niveau 2
==== Section niveau 3
===== Section niveau 4
====== Section niveau 5
== Une autre section niveau 1
Le rendu
Mise en forme des paragraphes
Les éléments classiques de mise en forme sont disponibles :
_italique_
*gras*
*_gras italique_*
#Surligné#
[line-through]#barré#
'''
Le rendu
La typographie “monospaced” (comprendre : même largeur pour tous les caractères) sera utile pour insérer du code source ou un terme technique au milieu d’une phrase.
Elle peut être associée à la mise en gras et en italique
Exemple :
`Blob` est un terme technique.
`*_terme technique_*` peut aussi être en gras et/ou en italique.
Le rendu
Une citation
[quote,Yoda]
____
Fais le ou ne le fais pas. Il n'y a pas d'essai.
____
Le rendu
Le cas des sauts de lignes (et des retours à la ligne)
Cela paraît simple, mais ça ne l’est jamais complètement dès que l’on souhaite maîtriser complètement l’aération d’un document avec des sauts de lignes planifiés.
Spécifiquement, sur AsciiDoc, la règle principale à savoir est que, pour qu’il y ait une nouvelle ligne entre deux blocs de texte, il faut mettre une ligne vide. Dans le cas contraire, les deux textes se suivront dans le rendu final.
L’autre point majeur à connaître est le caractère « + ».
Une première ligne sur un paragraphe.
Une deuxième ligne sur un deuxième paragraphe.
Une troisième ligne.
Qui continue avec une quatrième, mais dans le même paragraphe.
Un texte avec saut de ligne forcé +
pour apparaître sur la ligne suivante.
Le rendu
Les listes
Les listes à puces ne posent pas de soucis.
Liste à puces :
* Élément 1
** Élément 1
* Élément 2
Liste numérotée :
. Élément 1
.. Élément 11
. Élément
Le rendu
Les lexiques (liste étiquetées)
Pour un lexique on utilise les listes étiquetées.
[horizontal]
Un terme::
Une description
Un autre terme::
Une autre description
Le rendu
Les cases à cocher
.Tâches à faire
- [*] Sortir les enfants
- [x] Sortir le chien
- [ ] Laver le vélo
- [ ] Faire une balade
Le rendu
Les images
On peut insérer facilement une image, et le “alt” est fourni entre les crochets.
image::images/logo_asciidoc.png[Logo en PNG avec une légende]
Le rendu
L’image peut facilement être placé dans le texte :
Cet outil image:images/logo_asciidoc.png[title=AsciiDoc] est très utile
Le rendu
Évidemment les dimensions peuvent être précisées.
Exemple : [width=16, height=16].
En ce qui concerne les tableaux, il y a plusieurs syntaxes possibles.
1. Le format « compact » pour les tableaux simples :
|===
| En-tête 1 | En-tête 2
|Cellule 11 | Cellule 12
|Cellule 21 | Cellule 22
|===
Le rendu
2. Le format suivant permet de définir le contenu d’une cellule sur une ligne différente. C’est plus lisible pour les grands tableaux :
|===
| En-tête 1 | En-tête 2
|Cellule 11
|Cellule 12
|Cellule 21
|Cellule 22
|===
Le rendu
Les admonitions (avertissements)
Derrière ce terme barbare que je connaissais pas (mais dans un français parfait), les admonitions, qui signifie avertissements, se trouvent 5 sortes de paragraphes avec chacune une icône spécifique permettant de sensibiliser le lecteur sur une remarque.
NOTE: une remarque
TIP: un conseil
IMPORTANT: c'est important
WARNING: attention
CAUTION: un avertissement
Le rendu
Les liens et les ancres
La syntaxe pour les liens vers une adresse externe est simple :
Lien vers un site externe (avec un libellé) : https://asciidoc.org[AsciiDoc]
Le rendu
Pour les liens qui correspondent à des chapitres avec ancres, on peut reprendre le libellé de la section qui suit, ou forcer le libellé.
Lien vers une section de la page (récupération du libellé) : <<ancre-interne>>
[[ancre-interne]]
==== Section avec une ancre
Lien vers une section d'une autre page (libellé forcé) : <<./rest/rest-server.adoc#rest-api-map,API MAP>>.
Le rendu
Les blocs de code
Simple et efficace, avec évidemment avec la coloration syntaxique dans le rendu (dépend des visualisateurs).
.Du java
[source,java]
----
public interface Affichage {
void afficher();
}
----
Le rendu
Les blocs de code source dynamique (inclure du code source).
C’est selon moi la fonction la plus utile. Associer la documentation et le code source réel :
- on peut inclure le fichier complet
- ou des morceaux de code source, entre des marqueurs mis dans le code source (“tags”).
Page principale :
:sourcedir: src/main/java
[source,java]
----
include::{sourcedir}/org//Asciidoctor.java[]
----
[source,java]
----
include::{sourcedir}/org/HelloWorld.java[tags=implementation]
----
Le rendu
Fichier src/main/java/org/HelloWorld.java :
class HelloWorld
{
public static void main(String args[]) {
// tag::implementation[]
System.out.println("Hello, World");
// end::implementation[]
}
}
Le rendu
Les renvois dans un bloc :
Je le mentionne car ceci améliore la lisibilité d’un bloc de code source, mais malheureusement le plugin Confluence Publisher ne gère pas les renvois.
Voici une des syntaxes qui permet de mettre des renvois dans un bloc.
[source,xml]
----
<section>
<title>Titre de section</title> <!--1-->
</section>
----
<1> Ce titre est nécessaire
[source,xml]
Le rendu
Les renvois de bas de page (footnote) :
Une explication.footnote:[Première note de base de page.]
Une autre explication!footnote:disclaimer[Deuxième note de base de page.]
Une autre explication qui renvoie la deuxième note.footnote:disclaimer[]
Le rendu
En bas de page
Les pièces jointes
Contrairement à un simple lien, mettre un lien vers une pièce jointe permet que ce document soit inclus dans l’arborescence cible (et par exemple il sera mis en pièce jointe dans Confluence).
Cette première syntaxe ne fonctionne pas avec le plugin confluence-publisher :
// On redéfinit l’emplacement des pièces jointes
:attachmentsdir: piece_jointe
xref:version@component:module:attachment$un_fichier.txt[Ouvrir le fichier]
Le rendu
Cette deuxième syntaxe fonctionne avec le plugin confluence-publisher :
// On redéfinit l’emplacement des pièces jointes
:attachmentsdir: piece_jointe
link:{attachmentsdir}/un_fichier.txt[Ouvrir le fichier]
Le rendu
Les accordéons (ou “collapsible’ en anglais)
Présents désormais dans de nombreux sites internet (WordPress par exemple), les accordéons permettent d’afficher un simple texte, et lors du clic sur le titre, de développer le paragraphe pour afficher le détail.
Personnellement je les apprécie beaucoup car votre documentation apparaît progressivement : vous avez 3 ou 4 informations, et quand vous cliquez sur un titre, vous avez des sous-titres, puis l’explication. On est dans une approche “entonnoir”.
Dans AsciiDoc la syntaxe est facile, et on peut avoir plusieurs accordéons imbriqués (il faut mettre nombre de = différent).
.Un accordéon simple :
[%collapsible]
====
Contenu de l'élément
====
.Un accordéon avec un sous-accordéon :
[%collapsible]
====
Contenu de l'élément
.Sous-accordéon
[%collapsible]
=====
Contenu du sous-élément
=====
====
Le rendu
Les schémas (diagrammes UML)
Pour cette fonctionnalité, je suis allé chercher du côté d’une extension nommée AsciiDoctor Diagram et plus particulièrement du langage PlantUML.
J’ai inséré un diagramme de composant et un diagramme de séquence, mais j’aurais pu faire un diagramme de classe, un diagramme d’état, un diagramme des cas d’utilisations…
Pour l’écriture de ces schémas, certes lisibles, mais avec une syntaxe très particulière, je recommande l’utilisation d’outils comme “PlantText UML Editor” (solution on-line).
.Diagramme de composant PlantUML
[plantuml]
----
actor Superviseur
node Grafana
node Kibana
node Dynatrace
title Lien entre Kibana, Grafana et Dynatrace
Superviseur -[bold]-> Grafana : visualise des \ntableaux de bord
Grafana -[bold]-> Kibana : récupère les données des logs\n Java + accès HTTP
Grafana -[bold]-> Dynatrace : récupère les données des\nsondes (CPU, temps de réponses...)
—-
Le rendu
.Diagramme de séquence PlantUML
[plantuml]
----
Alice -> Inès: Demande de connexion
Inès --> Alice: Connexion acceptée
Alice -> Inès: Une autre demande de connexion
Inès --> Alice : Connexion refusée
Le rendu
Liste et court descriptif des autres fonctionnalités :
Je vais devoir lister les fonctionnalités plus avancées pour ne pas vous perdre :
- Nous pouvons définir notre propre CSS global ou pour une page précise.
- Syntaxe : “title-page: background-color: #EAEAEA »
- Nous pouvons définir une indentation pour chaque ligne (avec » $ ») ou un bloc indenté (avec « …. puis $ puis …. »)
- Nous pouvons mettre un lien vers la page précédente et la page suivante :
Syntaxe : »:prev_section: xxx » et « :next_section: yyy »
- Nous pouvons définir des variables.
- La définition et l’utilisation sont par exemple : :uri-homepage: http://asciidoctor.or
:uri-docs: {uri-homepage}/docs
- On peut utiliser des bloc conditionnés : ifdef::<attribute>[] (contenu)
endif::<attribute>[]
- Nous pouvons insérer une zone non interprétée (par exemple du HTML) : pass:[<div align= »center »><b>du texte en gras et centré</b></div>]
- On peut définir un glossaire dans un bloc [glossary]
- Les textes en exposant ou en indice : ^exposant^mot et ~indice~mot donneront exposantmot et indicemot .
- Et cette liste n’est pas exhaustive.
La configuration du plugin confluence-publisher
Nous allons commencer par indiquer les infos d’identification au serveur Confluence dans le fichier .m2/settings.xml .
(Nous pouvons aussi préciser le username, le password et le serverId dans le pom.xml, mais je ne préfère pas)
<settings>
<servers>
<server>
<id>confluence-neosoft</id>
<username>christian</username>
<password>IlFautQueJeChangeMonMotDePasse</password>
</server>
</servers>
</settings>
Nous devons évidemment définir les versions des composants sous forme de propriétés, et le gestionnaire de code source (git dans mon cas)
<properties>
<asciidoctor.maven.plugin.version>2.2.4</asciidoctor.maven.plugin.version>
<asciidoctorj.pdf.version>2.3.9</asciidoctorj.pdf.version>
<asciidoctorj.version>2.5.10</asciidoctorj.version>
<asciidoctorj.diagram.version>2.2.13</asciidoctorj.diagram.version>
<jruby.version>9.4.2.0</jruby.version>
<project.version>1.0.0-SNAPSHOT</proejct.version>
</properties>
<scm> <developerConnection>scm:git:https://${GIT_CREDENTIALS}@gitlab.neosoft.fr/demo-asciidoc.git</developerConnection>
<tag>HEAD</tag>
</scm>
En ce qui concerne la partie génération via AsciiDoctor, on repose sur le plugin asciidoctor-maven-plugin : nous allons exporter en HTML et en PDF (donc nous avons 2 “executions”) et nous avons besoin de préciser l’extension asciidoctor-diagram.
<build>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>${asciidoctor.maven.plugin.version}</version>
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-pdf</artifactId>
<version>${asciidoctorj.pdf.version}</version>
</dependency>
<!-- Comment this section to use the default jruby artifact provided by the plugin -->
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby</artifactId>
<version>${jruby.version}</version>
</dependency>
<!-- Comment this section to use the default AsciidoctorJ artifact provided by the plugin -->
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId>
<version>${asciidoctorj.version}</version>
</dependency>
<!-- for plantuml diagrams -->
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-diagram</artifactId>
<version>${asciidoctorj.diagram.version}</version>
</dependency>
</dependencies>
<configuration>
<requires>
<require>asciidoctor-diagram</require>
</requires>
</configuration>
<executions>
<execution>
<id>output-html</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
</execution>
<execution>
<id>output-pdf</id>
<phase>generate-resources</phase>
<goals>
<goal>process-asciidoc</goal>
</goals>
<configuration>
<backend>pdf</backend>
</configuration>
</execution>
</executions>
</plugin>
En ce qui concerne la génération vers Confluence avec confluence-publisher (plugin asciidoc-confluence-publisher-maven-plugin), plusieurs éléments sont à définir :
- Le répertoire contenant les fichiers AsciiDoc à exporter ‘asciidocRootFolder’,
- L’espace confluence cible ‘rootConfluenceUrl’,
- La page confluence parente “ancestorId”,
- Les pages seront écrasées si elles sont déjà présentes “publishingStrategy”,
- Le préfixe des titres de page (visible dans le menu, et en début de page) : pageTitlePrefix
- L’encodage (UTF8, évidemment)
<plugin>
<groupId>org.sahli.asciidoc.confluence.publisher</groupId>
<artifactId>asciidoc-confluence-publisher-maven-plugin</artifactId>
<version>0.22.0</version>
<configuration>
<asciidocRootFolder>src/docs/asciidoc/user-guide</asciidocRootFolder>
<sourceEncoding>UTF-8</sourceEncoding>
<rootConfluenceUrl>https://confluence.neosoft.fr/</rootConfluenceUrl>
<skipSslVerification>true</skipSslVerification>
<maxRequestsPerSecond>10</maxRequestsPerSecond>
<spaceKey>DAALF</spaceKey>
<ancestorId>591788892</ancestorId>
<serverId>confluence-neosoft</serverId>
<pageTitlePrefix xml:space="preserve">Manuel :: </pageTitlePrefix>
<versionMessage>Version ${project.version}</versionMessage>
<notifyWatchers>false</notifyWatchers>
<attributes>
<version>${project.version}</version>
<someOtherKey>value</someOtherKey>
</attributes>
<publishingStrategy>REPLACE_ANCESTOR</publishingStrategy>
</configuration>
<executions>
<execution>
<id>publish-documentation</id>
<goals>
<goal>publish</goal>
</goals>
<phase>generate-resources</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
Lancer le plugin Confluence dans la chaîne d’intégration continue.
La génération des pages Confluence est simple compte tenu de l’utilisation d’un plugin maven. Il suffit en effet de lancer “mvn generate-resources »
Sur ce principe l’écriture d’un traitement (job) Jenkins n’a besoin que de peu de paramétrage. Il peut être réalisé en se basant sur un Jenkinsfile . Dans mon cas :
- Il est déclenché manuellement,
- Il demande 2 paramètres : le login et le mot-de-passe de l’utilisateur confluence.
La commande maven lancée est “mvn generate-resources dont on peut fournir le username (paramètre asciidoc-confluence-publisher.username) et le password (asciidoc-confluence-publisher.password).
parameters {
string(name: 'CONFLUENCE_USERNAME', description: 'username pour publier sur confluence')
string(name: 'CONFLUENCE_PASSWORD', description: 'password pour publier sur confluence')
}
(...)
stage('generate-resources') {
steps { script {
(...)
container('maven') {
sh """
mvn generate-resources -f pom.xml -s settings.xml -Dasciidoc-confluence-publisher.username=${params.CONFLUENCE_USERNAME} -Dasciidoc-confluence-publisher.password=${params.CONFLUENCE_PASSWORD} -X
"""
}
} }
}
La seule difficulté réside dans l’ouverture des flux entre le serveur Jenkins, et le serveur Confluence. Il faut donc l’intervention d’un intégrateur/DevOps .
Pour information, il existe un plugin “Jenkins Confluence Publisher”, mais qui a été suspendu en décembre 2023 en raison d’utilisation de dépendances dont les licences ne sont pas compatibles. Je ne l’ai donc pas utilisé.
Des outils d’édition, de rendu et de conversion pour AsciiDoc
Nous pouvons très bien utiliser son éditeur NotePad++ préféré et rédiger tout parfaitement et directement (ça marche, et évidemment vous n’aurez la colorisation syntaxique pour vous aider).
Mais si vous voulez de la prévisualisation, voire une barre d’outils pour mettre en gras ou insérer un tableau, vous apprécierez ces outils :
- AsciidoFX est un logiciel lourd (multiplateforme – écrit en Java FX), sous license Apache License 2.0, un peu lent et avec quelques plantages, mais avec une barre de boutons permettant de faire rapidement une mise en page intéressante. Il y a la coloration syntaxique, et un rendu directement sur la fenêtre de droite.. Les exports dans les différents formats (PDF, DocBook…) sont censés fonctionner en un clic… mais chez moi n’ont pas fonctionné. Mais ça reste un bon outil.
- AsciidocLive : un visualiseur on-line. Signalé en version “béta” il manque certes quelques fonctionnalités (les accordéons…). Mais il a l’avantage d’être toujours à portée de la main.
- Pour les développeurs Java, chaque IDE (Éclipse, VSCode, IntelliJ) propose un plugin évolué, avec coloration syntaxique et rendu en temps réel.
- Signalons aussi une extension “Asciidoctor.js Live Preview” pour Chrome. Il affiche le rendu de la page AsciiDoc. A noter qu’il faut activer l’option “Autoriser l’accès aux URL de fichier”
- Dans le cas où vous publiez les fichiers AsciiDoc dans git, les outils Gitlab et Github proposent nativement de visualiser le rendu des fichiers AsciiDoc.
Pour finir, un petit outil (en ligne de commande) qui m’a été utile pour la migration des documents Sharepoint (que j’ai exporté en Word) vers AsciiDoc : Pandoc. Cet outil de conversion supporte de nombreux formats en entrées (odt, docx, Markdown, HTML…) en de nombreux formats de sortie, dont AsciiDoc.
Perspectives et enseignements tirés d’AsciiDoc
Je ne vais pas forcément faire une conclusion globale sur AsciiDoc (en préparant cet article, j’ai appris qu’il était utilisé pour la rédaction de certains livres des éditions O’Reilly, et pour la documentation Git).
Je peux simplement témoigner que l’association d’AsciiDoc et de son plugin confluence-publisher a permis à notre équipe d’obtenir une documentation de très grande qualité sur la forme. C’est désormais une « composante du produit ».
Il y a quelques petits défauts dus uniquement au plugin, essentiellement la rapidité pour la génération de la documentation qui prend 7 minutes sur certains postes (nous avons de nombreuses pages). Ceci stoppera probablement les moins motivés. On pourra aussi noter que la rédaction est plus compliquée qu’avec Markdown, car il y a plus de possibilités.
Comme mentionné dans cet article, confluence-publisher n’évolue plus, donc dans quelques années, ce sera peut-être gênant et l’on devra peut-être générer la documentation AsciiDoc vers PDF (au moins il n’y aura rien de perdu) ou vers Antora (un projet open source pour générer un site de documentation en agrégeant du contenu de différents dépôts Git, et qui s’appuie sur le format AsciiDoc).
Mais globalement, pour une génération dans Confluence, l’association AsciiDoc / confluence-publisher est une très bonne solution pour la documentation technique, qui nécessite certes de « convertir » les développeurs, mais donne une solution professionnelle.
Annexes
Quelques liens utiles :
- La documentation officielle sur le plugin confluence-publisher
- Le projet github du plugin confluence-publisher, pour le code source et le détail des contributions du projet
- Présentation pour comprendre l’évolution du langage DocBook, vers le langage AsciiDoc, son moteur de rendu AsciiDoctor, et le moteur de site Antora
- Un texte de synthèse sur AsciiDoc (comme vous en trouverez énormément sur le net) mais celui-ci est rédigé par notre “gourou” (au moins pour les anciens développeurs, et j’espère les nouveaux aussi) Jean-Michel Doudoux
- Le manuel utilisateur Asciidoctor (en anglais). Complet.
- Le guide officiel “démarrage rapide” de AsciiDoc
- Le guide officiel, en français, de PlantUML
- Le guide officiel, en français, de Pandoc