Le Markdown et la gestion des échappements

Le cas des codes inline sur ZdS

Salut à tous,

une question est passée il n’y a pas longtemps sur Discord et portait sur l’échappement des caractères au sein des blocs de code dans ZMarkdown ; je tente ici d’apporter une réponse au problème, en expliquant pourquoi la solution initialement voulue n’est pas viable. Plutôt qu’une courte réponse sur le canal, il m’a semblé intéressant d’informer la communauté dans son ensemble de cette possibilité offerte par le Markdown et de développer un peu sur le choix technique effectué.

Une histoire de syntaxe

Le Markdown est un langage de balisage léger, dont les premières implémentations remontent à 2004 ; il s’agit du langage utilisé pour la rédaction sur Zeste de Savoir. Quand je parle d’implémentation, je parle ici de code, puisque le langage n’a jamais été standardisé, ce qui a très vite posé des problèmes dans les implémentations, qui divergeaient dans leurs façon de traiter la syntaxe.

Un standard de facto a plus ou moins émergé de Markdown.pl, mais l’implémentation a toujours été buguée, et les différents parseurs ont commencé à mettre en place chacun de leurs côté des règles concernant :

  • la précédence des opérateurs (le titre l’emporte sur le gras, par exemple) ;
  • les nouvelles fonctionnalités.

En 2012, CommonMark tente d’unifier ces syntaxes et d’en établir une spécification universelle. Cette spécification prendra peu au début, mais va connaître son essor en 2017 grâce à Github Flavored Markdown, une nouvelle spécification, basée sur CommonMark, et n’en changeant qu’une très petite partie. Fait standard pour la rédaction sur Github, le format prends très vite, et la grande majorité des parseurs sont basés sur cette syntaxe aujourd’hui.

Les choix techniques initiaux

Le nouveau standard en place tente de répondre aux questions suivantes :

  • quelle sont les espacement à utiliser pour le rendu ; en particulier, quelle indentation défini une sous-liste, quelle indentation démarque un bloc de code et faut-il des espaces entre les titres et leur syntaxe (#) ;
  • les sauts de lignes doivent-ils être interprétés strictement ? Si oui, dans quels cas ? Par exemple, un saut de ligne est-il requis avant une citation ?
  • Le rendu des paragraphes peut-il casser le rendu des autres syntaxes, typiquement les listes à puces ?
  • Les listes peuvent-elles contenir un ou plusieurs éléments vides ?

Comme vous pouvez le voir, ces problématique ont pour la plupart attrait à la précédence, c’est-à-dire l’ordre dans lequel doivent être traités les éléments. GFM y réponds en définissant une distinction simple entre les éléments :

  • les blocs, qui sont toujours parsés de façon prioritaire, il s’agit par exemple des citations, qui forment alors un nouveau bloc de sous-parsage, dans lequel les éléments autres pourront être rendus ;
  • les éléments en ligne (inline), qui n’ont pas de priorité, et sont donc toujours parsé ensuite, c’est ce qui fait qu’un titre dans un bloc de code ne s’affiche pas comme un titre, car le bloc de code (bloc) à la priorité sur le titre (inline) ;
  • dans les cas où l’on veut s’abstraire de cette précédence en faisant en sorte que le parseur ne prenne pas en compte certains caractères, il faut échapper le caractère, en le faisant précéder d’un antislash \ ; les caractères inline seront alors rendus dans le bloc parent.

Blocs de code, mes amours

Le problème relevé initialement par @A-312 concerne le code suivant :

`WHERE \`personnes\` LIKE %machin%`

devrait selon lui s’afficher WHERE `personnes` LIKE %machin%, alors que le rendu actuel est WHERE \personnes` LIKE %machin%`, l’échappement n’étant pas rendu. Alors, pourquoi ce comportement quand \*italique* ne rends pas l’italique ?

D’abord vu comme un problème avec le rendu de Markdown par ZMarkdown, et surtout sa couche inférieure, remark, il s’avère en fait… que ce problème n’en est pas un. Les antislashs, comme mentionné précédemment, ne se voient attribuer précédence (ou plutôt, retirent la précédence d’une syntaxe) que lors d’une ambiguïté de parsage entre bloc et inline. Il n’y en a aucune ici ; le seul caractère échappable est le début du bloc de code : \`test` rend donc `test`, puisqu’il donne la priorité au bloc de paragraphe, plutôt qu’au bloc inline de code pour le rendu du caractère.

Une solution simple

Alors, oui, c’est bien beau, cette histoire de priorité, mais comment alors peut-on rendre le code initial en inline ? La spécification mentionne pour le code inline la structure suivante :

Une chaîne d’accents graves (`) est une chaîne d’un ou plusieurs accents graves qui n’est ni précédée, ni suivie d’un accent grave.

Un bloc en ligne de code commence par une chaîne d’accents graves, et se termine par une chaîne d’accents graves de la même longueur.

GFM §6.3 (traduction libre)

En résumé, il s’agit de la plus longue chaîne possible d’accents. Un bloc de code inline n’est donc pas nécessairement commencée et terminée par un unique caractère ` ; si l’on souhaite avoir dans son code un de ces caractères, il suffit alors de choisir une chaîne de longueur supérieure à 1 ; le problème était donc résolu avant même qu’il ne se soit posé. Pour rendre la chaîne initiale, on pourra donc faire :

``WHERE `personnes` LIKE %machin%``

Notez bien les deux accents au lieu d’un seul, qui permet le bon rendu de la chaîne : WHERE `personnes` LIKE %machin%. Notez qu’il n’est pas nécessaire d’avoir n+1 accents préliminaires pour une chaîne contenant n accents qui se suivent, ainsi ``` est rendu par :

` ``` `

Qui est une chaîne d’un seul accent, en contenant trois à l’intérieur. L’espace est une autre astuce, permettant au Markdown d’éviter de confondre le code avec une chaîne de 5 accents.


La prochaine fois que vous verrez un nouveau membre poster un code non-coloré, vous saurez maintenant comment l’informer correctement à propos du problème, sans vous prendre la tête avec la syntaxe.

13 commentaires

Il y a beaucoup de choses à rajouter dans Rédigez sur ZdS.

Et même des choses à retirer. ^^" Je ferais une liste ici cette semaine.

+0 -0

Voilà une petite liste faite vite fait.

Les titres

Une autre syntaxe des titres:

Niveau 1
-------

Niveau 2
========

Les titres dit atx peuvent également être terminé par des croisillons.

# Titre de niveau 1
équivalent à 

# Titre de niveau 1 #

### Titre de niveau 3 ###

Seul compte le nombre de croisillons au début.

Il est recommandé de n’utiliser qu’une seule syntaxe afin de rester consistant dans un même document.

Enfin un petit mot sur les ancres de titres.

Généré par :

Enfin un petit mot sur les ancres de [titres](#les-titres).

Une ancre est ajoutée au titre ! ^^

Emphases

Généralement, on recommande de n’utiliser que la syntaxe avec l’étoile *. Dans tous les cas il est recommandé de n’utiliser qu’une seule syntaxe afin de rester consistant dans un même document.

Listes

Ajoutez un exemple de liste ordonnée

  1. Yeah !
  2. Putain
  3. Please O_

Parlez du fait que seul le premier nombre compte.

Les listes de tâches.

  • a task list item
  • list syntax required
  • normal formatting, @mentions, #1234 refs
  • incomplete
  • completed
- [ ] a task list item
- [ ] list syntax required
- [ ] normal **formatting**, @mentions, #1234 refs
- [ ] incomplete
- [x] completed

C’est une syntaxe que j’adore personnellement.

Liens

Parler de la transformation automatique en lien des urls. Exemple https://ache.one (automatiquement transformé en lien). C’est abordé à la fin mais il est dit que ça marche également pour les emails alors que non. zds@ache.one par exemple ne marche pas.

Et des autolinks. La même chose avec des crochets. <mailto:ache@bash.mozar>. Qui donne : ache@bash.mozar.

Les adresses emails sont automatiquement détecté. Ainsi <ache@ache.one> est lien autolink mailto valide. zestedesavoir@gmail.com

Les liens-définitions, utiles quand on a souvent un lien. Mais il y a pleins de syntaxe. Généralement toutes assez claires.

[ddg]: <ddg.gg> "DuckDuckGo"

[qwant]:
<qwant.eu> 
'Qwant
est
super'

[gg]: https://try.it.eu

J'aimme [ddg] ! Mais pas [Google][gg]. [Qwant][] ça passe

J’aime ddg !

Ligne horizontale

C’est fun là ^^

On a le droit d’utiliser 3 2 caractères. *, - ou _1.
On a le droit d’utiliser des espaces à l’intérieur mais pas de les mélanger les caractères.

-- -- -- -- -- --


 **  * ** * ** * **

Maths

On pourrait rapidement parler de KaTeX\KaTeX et LaTeX\LaTeX. Du tutoriel dédié et des commandes disponibles.

Codes

Le nombre de ~ ou ` n’est pas fixé à 3, c’est 3 minimum.

Ainsi

~~~~~~~c
int main(void) {
   return EXIT_SUCCESS;
}
~~~~~~~

Est tout à fait valide. Pratique quand on veut colorer du markdown.

D’ailleurs la syntaxe :

    :::python
    #!/usr/bin/env python3
    
    print("Hello, World!")

Ne marche plus du tout ! C’était valide pour Pandoc, certainement python-zmarkdown mais maintenant ça n’a plus lieu d’être.

Parler de la détection automatique du langage. Ajouter la liste des langages. Rapidement parler des principaux. plainshell, arduino, …

La mise en évidence des lignes de code et le début de la numérotation ne sont pas implémentée (pas encore) en zmarkdown. Une petite note serait utile.

Commentaire de code

Une sorte de légende.
C’est utilisé dans le tutoriel mais pas documenté. On peut ajouté un petit commentaire sur le code:

~~~c
int t = 23[t] + "aze"[0];
~~~
Code: Code pas beau !

Qui donne :

int t = 23[t] + "aze"[0];
Code pas beau !
Code inline

Le sujet de ce billet.

Notes de bas de page

Les inlines.

Venez on est bien[^ sur Zeste de Savoir] !

Venez on est bien2 !

Images

La syntaxe référence des images.

![ache]

[ache]: https://ache.one/res/ache.svg "Logo ache"

ache


Voilà, j’ai certainement oublié pleins de trucs ^^"
J’irais voir dans les sources si j’ai le temps.


  1. Seulement en CommonMark !
  2. sur Zeste de Savoir
+5 -0

@A-312: >_<"

Désolé,… En ce moment, je suis très très pris.
J’avais dis que je remettais en forme dans la semaine. Ce WE, je n’ai rien de prévu donc je vais m’attaquer à ça (et à pleins d’autres trucs que j’ai à faire).

Comme tu vois, j’ai cité plein de points à mentionner. Mais mon texte n’est pas rédigé et le peu qui est rédigé est bourré de fautes d’attention. Ça mérite une sacré relecture et une intégration.

Si tu veux on peut faire ça ensemble ? Si tu as le temps bien-sûr ^^

+0 -0

Merci de ne pas favoriser la syntaxe alternative pour les titres, actuellement elle n’est pas supportée par le processus d’export des contenus en pdf.

artragis

Hum ?

Titre
=====

N’est pas supporté ?

+0 -0

par le processus de génération des pdf.

en fait pour générer le pdf on a besoin du markdown à plat.

pour générer le markdown à plat, on parcourt la hiérarchie du tuto et on met les titres des parties et chapitres là où il faut.

mais ensuite il faut gérer l’effet suivant : dans la section "bidule", le texte contient des titres, ces titres commencent au niveau 1, pour faciliter la rédaction.

pour que ces titres ne soient pas considérés comme des nouvelles parties, on parcourt chaque section et on ajoute le nombre adéquat de # à chacun des titres. Et j’insiste sur le fait qu’on ajouter des # on ne supporte pas les titres soulignés.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte