Bibliothèque Java pour analyser et restituer le texte Markdown selon la spécification CommonMark (et certaines extensions).
Fournit des classes pour analyser les entrées dans un arbre de syntaxe abstraite (AST), visiter et manipuler des nœuds et effectuer le rendu au format HTML ou vers Markdown. Il a commencé comme un portage de commonmark.js, mais a depuis évolué vers une bibliothèque extensible avec les fonctionnalités suivantes :
Petit (le noyau n'a pas de dépendances, extensions dans des artefacts séparés)
Rapide (10 à 20 fois plus rapide que pegdown qui était autrefois une bibliothèque Markdown populaire, voir les benchmarks dans le dépôt)
Flexible (manipuler l'AST après l'analyse, personnaliser le rendu HTML)
Extensible (tableaux, barrés, liaison automatique et plus, voir ci-dessous)
La bibliothèque est prise en charge sur Java 11 et versions ultérieures. Cela fonctionne également sur Android, mais dans la mesure du possible, veuillez signaler les problèmes. Pour Android, le niveau minimum de l'API est 19, consultez le répertoire commonmark-android-test.
Coordonnées de la bibliothèque principale (voir tout sur Maven Central) :
<dépendance> <groupId>org.commonmark</groupId> <artifactId>marque commune</artifactId> <version>0.24.0</version> </dépendance>
Les noms de modules à utiliser dans Java 9 sont org.commonmark
, org.commonmark.ext.autolink
, etc., correspondant aux noms de packages.
Notez que pour les versions 0.x de cette bibliothèque, l'API n'est pas encore considérée comme stable et peut être interrompue entre les versions mineures. Après la version 1.0, le versioning sémantique sera suivi. Un package contenant beta
signifie qu'il n'est pas encore soumis aux garanties stables de l'API ; mais pour une utilisation normale, il ne devrait pas être nécessaire de l'utiliser.
Consultez le fichier spec.txt si vous vous demandez quelle version de la spécification est actuellement implémentée. Consultez également le dingus CommonMark pour vous familiariser avec la syntaxe ou essayer des cas extrêmes. Si vous clonez le référentiel, vous pouvez également utiliser la classe DingusApp
pour essayer des choses de manière interactive.
importer org.commonmark.node.*;importer org.commonmark.parser.Parser;importer org.commonmark.renderer.html.HtmlRenderer;Parser parser = Parser.builder().build();Node document = parser.parse(" Il s'agit de *Markdown*");HtmlRenderer renderer = HtmlRenderer.builder().build();renderer.render(document); // "<p>C'est <em>Markdown</em></p>n"
Cela utilise l'analyseur et le moteur de rendu avec les options par défaut. Les deux constructeurs disposent de méthodes pour configurer leur comportement :
escapeHtml(true)
sur HtmlRenderer
échappera aux balises et aux blocs HTML bruts.
sanitizeUrls(true)
sur HtmlRenderer
supprimera les URL potentiellement dangereuses des balises <a>
et <img>
Pour toutes les options disponibles, consultez les méthodes sur les constructeurs.
Notez que cette bibliothèque n'essaie pas de nettoyer le HTML résultant en ce qui concerne les balises autorisées, etc. C'est la responsabilité de l'appelant, et si vous exposez le HTML résultant, vous souhaiterez probablement exécuter un désinfectant après cela. .
import org.commonmark.node.*;import org.commonmark.renderer.markdown.MarkdownRenderer;MarkdownRenderer renderer = MarkdownRenderer.builder().build();Node document = new Document();Heading heading = new Heading();heading .setLevel(2);heading.appendChild(new Text("Mon titre"));document.appendChild(titre);renderer.render(document); // "## Mon titren"
Pour le rendu en texte brut avec un balisage minimal, il existe également TextContentRenderer
.
Une fois le texte source analysé, le résultat est un arbre de nœuds. Cet arbre peut être modifié avant le rendu, ou simplement inspecté sans rendu :
Node node = parser.parse("Exemplen=======nnUn peu plus de texte");WordCountVisitor visiteur = new WordCountVisitor();node.accept(visitor);visitor.wordCount; // 4class WordCountVisitor étend AbstractVisitor { int wordCount = 0; @Override public void visit(Text text) { // Ceci est appelé pour tous les nœuds Text. Remplacez les autres méthodes de visite pour d’autres types de nœuds. // Comptez les mots (ce n'est qu'un exemple, ne le faites pas de cette façon pour diverses raisons). wordCount += text.getLiteral().split("\W+").length; // Descendre en enfants (pourrait être omis dans ce cas car les nœuds Text n'ont pas d'enfants). visiterEnfants(texte); } }
Si vous souhaitez savoir où un Node
analysé est apparu dans le texte source d'entrée, vous pouvez demander à l'analyseur de renvoyer les positions source comme ceci :
var parser = Parser.builder().includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES).build();
Analysez ensuite les nœuds et inspectez les positions sources :
var source = "foonnbar *baz*";var doc = parser.parse(source);var accent = doc.getLastChild().getLastChild();var s = accent.getSourceSpans().get(0) ;s.getLineIndex(); // 2 (troisième ligne)s.getColumnIndex(); // 4 (cinquième colonne)s.getInputIndex(); // 9 (index de chaîne 9)s.getLength(); // 5source.substring(s.getInputIndex(), s.getInputIndex() + s.getLength()); // "*baz*"
Si vous n'êtes intéressé que par les blocs et non par les lignes, utilisez IncludeSourceSpans.BLOCKS
.
Parfois, vous souhaiterez peut-être personnaliser la façon dont le HTML est rendu. Si tout ce que vous souhaitez faire est d’ajouter ou de modifier des attributs sur certains éléments, il existe un moyen simple de le faire.
Dans cet exemple, nous enregistrons une fabrique pour un AttributeProvider
sur le moteur de rendu afin de définir un attribut class="border"
sur les éléments img
.
Analyseur parser = Parser.builder().build();HtmlRenderer renderer = HtmlRenderer.builder() .attributeProviderFactory(new AttributeProviderFactory() { public AttributeProvider create(AttributeProviderContext context) { return new ImageAttributeProvider(); } }) .build();Node document = parser.parse("![text](/url.png)");renderer.render(document);// "<p><img src="/url.png " alt="text" class="border" /></p>n"class ImageAttributeProvider implémente AttributeProvider { @Override public void setAttributes(Node node, String tagName, Map<String, String> attributs) { if (node instanceof Image) {attributs.put("class", "border"); } } }
Si vous souhaitez faire plus que simplement modifier les attributs, il existe également un moyen de prendre un contrôle total sur la façon dont le HTML est rendu.
Dans cet exemple, nous modifions le rendu des blocs de code indentés pour les envelopper uniquement dans pre
au lieu de pre
et code
:
Analyseur parser = Parser.builder().build();HtmlRenderer renderer = HtmlRenderer.builder() .nodeRendererFactory(new HtmlNodeRendererFactory() { public NodeRenderer create(HtmlNodeRendererContext context) { return new IndentedCodeBlockNodeRenderer(context); } }) .build();Node document = parser.parse("Exemple :nn code");renderer.render(document);// "<p>Exemple :</p>n<pre>coden </pre>n"class IndentedCodeBlockNodeRenderer implémente NodeRenderer { private final HtmlWriter html; IndentedCodeBlockNodeRenderer (contexte HtmlNodeRendererContext) { this.html = context.getWriter(); } @Override public Set<Class<? extends Node>> getNodeTypes() { // Renvoie les types de nœuds pour lesquels nous souhaitons utiliser ce moteur de rendu. return Set.of(IndentedCodeBlock.class); } @Override public void render(Node node) { // Nous ne gérons qu'un seul type selon getNodeTypes, nous pouvons donc simplement le convertir ici. IndentedCodeBlock codeBlock = (IndentedCodeBlock) nœud ; html.line(); html.tag("pré"); html.text(codeBlock.getLiteral()); html.tag("/pre"); html.line(); } }
Si vous souhaitez stocker des données supplémentaires dans le document ou avoir des éléments personnalisés dans le HTML résultant, vous pouvez créer votre propre sous-classe de CustomNode
et ajouter des instances en tant que nœuds enfants aux nœuds existants.
Pour définir le rendu HTML de ces derniers, vous pouvez utiliser un NodeRenderer
comme expliqué ci-dessus.
Il existe plusieurs façons d'étendre l'analyse ou même de remplacer l'analyse intégrée, toutes via des méthodes sur Parser.Builder
(voir Blocs et inlines dans la spécification pour un aperçu des blocs/inlines) :
L'analyse de types de blocs spécifiques (par exemple, les titres, les blocs de code, etc.) peut être activée/désactivée avec enabledBlockTypes
L'analyse des blocs peut être étendue/remplacée avec customBlockParserFactory
L'analyse du contenu en ligne peut être étendue/remplacée avec customInlineContentParserFactory
L'analyse des délimiteurs dans le contenu en ligne peut être étendue avec customDelimiterProcessor
Le traitement des liens peut être personnalisé avec linkProcessor
et linkMarker
L' Parser
et HtmlRenderer
sont tous deux conçus pour que vous puissiez les configurer une fois à l'aide des générateurs, puis les utiliser plusieurs fois/à partir de plusieurs threads. Cela se fait en séparant l'état d'analyse/rendu de la configuration.
Cela dit, il peut bien sûr y avoir des bugs. Si vous en trouvez un, veuillez signaler un problème.
Les Javadocs sont disponibles en ligne sur javadoc.io.
Les extensions doivent étendre l'analyseur, ou le moteur de rendu HTML, ou les deux. Pour utiliser une extension, les objets constructeur peuvent être configurés avec une liste d'extensions. Étant donné que les extensions sont facultatives, elles résident dans des artefacts distincts, des dépendances supplémentaires doivent donc également être ajoutées.
Voyons comment activer les tables de GitHub Flavored Markdown. Tout d’abord, ajoutez une dépendance supplémentaire (voir Maven Central pour les autres) :
<dépendance> <groupId>org.commonmark</groupId> <artifactId>commonmark-ext-gfm-tables</artifactId> <version>0.24.0</version> </dépendance>
Ensuite, configurez l'extension sur les builders :
importer org.commonmark.ext.gfm.tables.TablesExtension;List<Extension> extensions = List.of(TablesExtension.create());Parser parser = Parser.builder() .extensions(extensions) .build();HtmlRenderer moteur de rendu = HtmlRenderer.builder() .extensions(extensions) .construire();
Pour configurer une autre extension dans l'exemple ci-dessus, ajoutez-la simplement à la liste.
Les extensions suivantes sont développées avec cette bibliothèque, chacune dans son propre artefact.
Transforme les liens simples tels que les URL et les adresses e-mail en liens (basés sur autolink-java).
Utilisez la classe AutolinkExtension
de l'artefact commonmark-ext-autolink
.
Permet de barrer le texte en le plaçant entre ~~
. Par exemple, dans hey ~~you~~
, you
serez rendu sous forme de texte barré.
Utilisez la classe StrikethroughExtension
dans l'artefact commonmark-ext-gfm-strikethrough
.
Active les tables utilisant des tubes comme dans GitHub Flavored Markdown.
Utilisez la classe TablesExtension
dans l'artefact commonmark-ext-gfm-tables
.
Active les notes de bas de page comme dans GitHub ou Pandoc :
Main text[^1] [^1]: Additional text in a footnote
Les notes de bas de page en ligne telles que ^[inline footnote]
sont également prises en charge lorsqu'elles sont activées via FootnotesExtension.Builder#inlineFootnotes
.
Utilisez la classe FootnotesExtension
dans l'artefact commonmark-ext-footnotes
.
Permet d'ajouter des attributs "id" générés automatiquement aux balises de titre. Le « id » est basé sur le texte du titre.
# Heading
sera rendu comme :
<h1 id="heading">Heading</h1>
Utilisez la classe HeadingAnchorExtension
dans l'artefact commonmark-ext-heading-anchor
.
Si vous souhaitez plutôt un rendu personnalisé du titre, vous pouvez utiliser la classe IdGenerator
directement avec un HtmlNodeRendererFactory
(voir l'exemple ci-dessus).
Permet de souligner le texte en le plaçant entre ++
. Par exemple, dans hey ++you++
, you
serez rendu sous forme de texte souligné. Utilise la balise <ins>.
Utilisez la classe InsExtension
dans l'artefact commonmark-ext-ins
.
Ajoute la prise en charge des métadonnées via un bloc préliminaire YAML. Cette extension ne prend en charge qu'un sous-ensemble de la syntaxe YAML. Voici un exemple de ce qui est pris en charge :
--- key: value list: - value 1 - value 2 literal: | this is literal value. literal values 2 --- document start here
Utilisez la classe YamlFrontMatterExtension
dans l'artefact commonmark-ext-yaml-front-matter
. Pour récupérer les métadonnées, utilisez YamlFrontMatterVisitor
.
Ajoute la prise en charge de la spécification des attributs (en particulier la hauteur et la largeur) pour les images.
Les éléments d'attribut sont donnés sous forme de paires key=value
entre accolades { }
après le nœud d'image auquel ils s'appliquent, par exemple :
![text](/url.png){width=640 height=480}
sera rendu comme suit :
<img src="/url.png" alt="text" width="640" height="480" />
Utilisez la classe ImageAttributesExtension
dans l'artefact commonmark-ext-image-attributes
.
Remarque : étant donné que cette extension utilise des accolades {
}
comme délimiteurs (dans StylesDelimiterProcessor
), cela signifie que les autres processeurs de délimiteurs ne peuvent pas utiliser d'accolades pour délimiter.
Ajoute la prise en charge des tâches en tant qu'éléments de liste.
Une tâche peut être représentée comme un élément de liste où le premier caractère autre qu'un espace est un crochet gauche [
, puis un seul caractère espace ou la lettre x
en minuscule ou en majuscule, puis un crochet droit ]
suivi d'au moins un espace avant tout autre. contenu.
Par exemple:
- [ ] task #1 - [x] task #2
sera rendu comme suit :
<ul> <li><input type="checkbox" disabled=""> task #1</li> <li><input type="checkbox" disabled="" checked=""> task #2</li> </ul>
Utilisez la classe TaskListItemsExtension
dans l'artefact commonmark-ext-task-list-items
.
Vous pouvez également trouver d’autres extensions dans la nature :
commonmark-ext-notifications : cette extension permet de créer facilement des paragraphes de notifications/avertissements comme INFO
, SUCCESS
, WARNING
ou ERROR
Certains utilisateurs de cette bibliothèque (n'hésitez pas à créer un PR si vous souhaitez être ajouté) :
Atlassian (où la bibliothèque a été initialement développée)
Java (OpenJDK) (lien)
Révision du code Gerrit/Gitiles (lien)
Programmation en direct moulable par un commis pour Clojure
Znaï
Markwon : bibliothèque Android pour le rendu des démarques en tant que Spannables natifs du système
flexmark-java : Fork qui a ajouté la prise en charge de beaucoup plus de syntaxe et de flexibilité
Voir le fichier CONTRIBUTING.md.
Copyright (c) 2015, Robin Stocker
Licence BSD (2 clauses), voir le fichier LICENSE.txt.