CommonMark 仕様 (および一部の拡張機能) に従って Markdown テキストを解析およびレンダリングするための Java ライブラリ。
抽象構文ツリー (AST) への入力を解析し、ノードにアクセスして操作し、HTML にレンダリングしたり Markdown に戻したりするためのクラスを提供します。これは commonmark.js の移植として始まりましたが、その後、次の機能を備えた拡張可能なライブラリに進化しました。
小規模 (コアには依存関係がなく、拡張機能は別のアーティファクト内にあります)
高速 (かつて人気の Markdown ライブラリだったペグダウンより 10 ~ 20 倍高速です。リポジトリのベンチマークを参照してください)
柔軟性 (解析後の AST の操作、HTML レンダリングのカスタマイズ)
拡張可能 (表、取り消し線、自動リンクなど、以下を参照)
このライブラリは Java 11 以降でサポートされています。 Android でも動作しますが、ベストエフォート型ですので、問題がある場合は報告してください。 Android の場合、最小 API レベルは 19 です。commonmark-android-test ディレクトリを参照してください。
コア ライブラリの座標 (Maven Central ですべてを参照):
<依存関係> <groupId>org.commonmark</groupId> <artifactId>commonmark</artifactId> <バージョン>0.24.0</バージョン> </依存関係>
Java 9 で使用するモジュール名は、パッケージ名に対応するorg.commonmark
、 org.commonmark.ext.autolink
などです。
このライブラリの 0.x リリースでは、API はまだ安定していないと考えられており、マイナー リリース間で機能しなくなる可能性があることに注意してください。 1.0 以降はセマンティック バージョニングが採用されます。 beta
を含むパッケージは、まだ安定した API 保証の対象になっていないことを意味します。ただし、通常の使用では使用する必要はありません。
現在実装されている仕様のバージョンが気になる場合は、spec.txt ファイルを参照してください。構文に慣れたり、エッジケースを試したりするには、CommonMark dingus もチェックしてください。リポジトリのクローンを作成すると、 DingusApp
クラスを使用して対話的に試すこともできます。
import org.commonmark.node.*;import org.commonmark.parser.Parser;import org.commonmark.renderer.html.HtmlRenderer;パーサー parser = Parser.builder().build();Node document = parser.parse("これは *Markdown*");HtmlRenderer レンダラー = HtmlRenderer.builder().build();renderer.render(ドキュメント); // "<p>これは<em>マークダウン</em></p>ですn"
これは、デフォルトのオプションでパーサーとレンダラーを使用します。どちらのビルダーにも、動作を構成するためのメソッドがあります。
HtmlRenderer
のescapeHtml(true)
は、生の HTML タグとブロックをエスケープします。
HtmlRenderer
のsanitizeUrls(true)
は、安全でない可能性のある URL を<a>
タグと<img>
タグから削除します。
利用可能なすべてのオプションについては、ビルダーのメソッドを参照してください。
このライブラリは、どのタグが許可されるかなどに関して、結果の HTML をサニタイズしようとしないことに注意してください。これは呼び出し側の責任であり、結果の HTML を公開する場合は、この後にサニタイザーを実行する必要があるでしょう。 。
import org.commonmark.node.*;import org.commonmark.renderer.markdown.MarkdownRenderer;MarkdownRenderer renderer = MarkdownRenderer.builder().build();Node document = new Document();Heading 見出し = new Heading();Heading .setLevel(2);Heading.appendChild(new Text("Myタイトル"));document.appendChild(見出し);renderer.render(ドキュメント); // "## 私のタイトルn"
最小限のマークアップでプレーン テキストにレンダリングする場合は、 TextContentRenderer
もあります。
ソース テキストが解析されると、結果はノードのツリーになります。そのツリーはレンダリング前に変更することも、レンダリングせずに検査するだけでも可能です。
ノード node = parser.parse("例n=======nnその他のテキスト");WordCountVisitor 訪問者 = new WordCountVisitor();node.accept(visitor);visitor.wordCount; // 4class WordCountVisitor extends AbstractVisitor { int wordCount = 0; @Override public void visit(Text text) { // これはすべての Text ノードに対して呼び出されます。他のノードタイプの他の訪問メソッドをオーバーライドします。 // 単語をカウントします (これは単なる例であり、さまざまな理由から実際にはこのようにしないでください)。 wordCount += text.getLiteral().split("\W+").length; // 子に降ります (Text ノードには子がないため、この場合は省略できます)。 visitChildren(テキスト); } }
解析されたNode
入力ソース テキストのどこに出現したかを知りたい場合は、次のようにパーサーにソース位置を返すように要求できます。
var parser = Parser.builder().includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES).build();
次に、ノードを解析してソースの位置を検査します。
var ソース = "foonnbar *baz*";var doc = parser.parse(source);var強調 = doc.getLastChild().getLastChild();var s =強調.getSourceSpans().get(0) ;s.getLineIndex(); // 2 (3行目)s.getColumnIndex(); // 4 (5 列目)s.getInputIndex(); // 9 (文字列インデックス 9)s.getLength(); // 5source.substring(s.getInputIndex(), s.getInputIndex() + s.getLength()); // "*バズ*"
インラインではなくブロックのみに興味がある場合は、 IncludeSourceSpans.BLOCKS
を使用します。
HTML のレンダリング方法をカスタマイズしたい場合があります。一部の要素の属性を追加または変更したいだけであれば、それを行う簡単な方法があります。
この例では、レンダラーのAttributeProvider
のファクトリを登録して、 img
要素にclass="border"
属性を設定します。
パーサー parser = Parser.builder().build();HtmlRenderer レンダラ = 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 は AttributeProvider を実装します { @Override public void setAttributes(Node ノード, String tagName, Map<String, String> 属性) { if (ノード インスタンスオブイメージ) {attributes.put("class", "border"); } } }
属性を変更するだけでなく、HTML のレンダリング方法を完全に制御する方法もあります。
この例では、インデントされたコード ブロックのレンダリングを変更して、 pre
とcode
ではなくpre
でのみラップするようにしています。
パーサー parser = Parser.builder().build();HtmlRenderer レンダラ = HtmlRenderer.builder() .nodeRendererFactory(new HtmlNodeRendererFactory() { public NodeRenderer create(HtmlNodeRendererContext context) { return new IndentedCodeBlockNodeRenderer(context); } }) .build();Node document = parser.parse("例:nn コード");renderer.render(document);// "<p>例:</p>n<pre>コードn </pre>n"クラス IndentedCodeBlockNodeRenderer は NodeRenderer { private Final HtmlWriter html を実装します。 IndentedCodeBlockNodeRenderer(HtmlNodeRendererContext context) { this.html = context.getWriter(); @Override public Set<Class<? extends Node>> getNodeTypes() { // このレンダラーを使用するノード タイプを返します。 Set.of(IndentedCodeBlock.class) を返します。 } @Override public void render(Node node) { // getNodeTypes に従って 1 つの型のみを処理するため、ここでキャストするだけです。 IndentedCodeBlock codeBlock = (IndentedCodeBlock) ノード; html.line(); html.tag("前"); html.text(codeBlock.getLiteral()); html.tag("/pre"); html.line(); } }
追加のデータをドキュメントに保存する場合、または結果の HTML にカスタム要素を含める場合は、 CustomNode
の独自のサブクラスを作成し、インスタンスを子ノードとして既存のノードに追加できます。
これらの HTML レンダリングを定義するには、上で説明したようにNodeRenderer
使用できます。
解析を拡張したり、組み込みの解析をオーバーライドしたりする方法はいくつかありますが、それらはすべてParser.Builder
のメソッドを使用します (ブロック/インラインの概要については、仕様内のブロックとインラインを参照してください)。
特定のブロック タイプ (見出し、コード ブロックなど) の解析は、 enabledBlockTypes
で有効/無効にできます。
ブロックの解析は、 customBlockParserFactory
で拡張/オーバーライドできます。
インライン コンテンツの解析は、 customInlineContentParserFactory
を使用して拡張/オーバーライドできます。
インライン コンテンツ内の区切り文字の解析は、 customDelimiterProcessor
を使用して拡張できます。
リンクの処理はlinkProcessor
とlinkMarker
でカスタマイズできます
Parser
とHtmlRenderer
どちらも、ビルダーを使用して一度構成すれば、複数回または複数のスレッドから使用できるように設計されています。これは、解析/レンダリングの状態を構成から分離することによって行われます。
そうは言っても、もちろんバグがある可能性があります。見つけた場合は、問題を報告してください。
Javadoc は、javadoc.io でオンラインで入手できます。
拡張機能では、パーサー、HTML レンダラー、あるいはその両方を拡張する必要があります。拡張機能を使用するには、拡張機能のリストを使用してビルダー オブジェクトを構成できます。拡張機能はオプションであり、別のアーティファクト内に存在するため、追加の依存関係も追加する必要があります。
GitHub Flavored Markdown からテーブルを有効にする方法を見てみましょう。まず、追加の依存関係を追加します (その他については Maven Central を参照してください)。
<依存関係> <groupId>org.commonmark</groupId> <artifactId>commonmark-ext-gfm-tables</artifactId> <バージョン>0.24.0</バージョン> </依存関係>
次に、ビルダーで拡張機能を構成します。
import org.commonmark.ext.gfm.tables.TablesExtension;List<Extension> extensions = List.of(TablesExtension.create());Parser parser = Parser.builder() .extensions(拡張子) .build();HtmlRenderer レンダラー = HtmlRenderer.builder() .extensions(拡張子) 。建てる();
上記の例で別の拡張機能を構成するには、それをリストに追加するだけです。
次の拡張機能はこのライブラリを使用して開発されており、それぞれ独自のアーティファクト内にあります。
URL や電子メール アドレスなどのプレーン リンクをリンクに変換します (autolink-java に基づいて)。
アーティファクトcommonmark-ext-autolink
のクラスAutolinkExtension
を使用します。
テキストを~~
で囲むことで取り消し線を有効にします。たとえば、 hey ~~you~~
では、取り消し線付きのテキストとしてyou
されます。
アーティファクトcommonmark-ext-gfm-strikethrough
でクラスStrikethroughExtension
を使用します。
GitHub Flavored Markdown と同様にパイプを使用してテーブルを有効にします。
アーティファクトcommonmark-ext-gfm-tables
でクラスTablesExtension
を使用します。
GitHub や Pandoc のような脚注を有効にします。
Main text[^1] [^1]: Additional text in a footnote
^[inline footnote]
のようなインライン脚注も、 FootnotesExtension.Builder#inlineFootnotes
で有効にした場合にサポートされます。
アーティファクトcommonmark-ext-footnotes
でクラスFootnotesExtension
を使用します。
自動生成された「id」属性を見出しタグに追加できるようにします。 「id」は見出しのテキストに基づいています。
# Heading
次のように表示されます。
<h1 id="heading">Heading</h1>
アーティファクトcommonmark-ext-heading-anchor
でクラスHeadingAnchorExtension
を使用します。
代わりに見出しのカスタム レンダリングが必要な場合は、 IdGenerator
クラスをHtmlNodeRendererFactory
と一緒に直接使用できます (上記の例を参照)。
テキストを++
で囲むことにより、テキストに下線を付けることができます。たとえば、 hey ++you++
では、下線付きのテキストとしてyou
されます。 <ins>タグを使用します。
アーティファクトcommonmark-ext-ins
でクラスInsExtension
を使用します。
YAML 前付ブロックを通じてメタデータのサポートを追加します。この拡張機能は、YAML 構文のサブセットのみをサポートします。サポートされているものの例を次に示します。
--- key: value list: - value 1 - value 2 literal: | this is literal value. literal values 2 --- document start here
アーティファクトcommonmark-ext-yaml-front-matter
でクラスYamlFrontMatterExtension
を使用します。メタデータを取得するには、 YamlFrontMatterVisitor
を使用します。
画像の属性 (特に高さと幅) を指定するためのサポートを追加します。
アトリビュート要素は、適用されるイメージ ノードの後に中括弧{ }
で囲まれたkey=value
ペアとして指定されます。次に例を示します。
![text](/url.png){width=640 height=480}
次のようにレンダリングされます:
<img src="/url.png" alt="text" width="640" height="480" />
アーティファクトcommonmark-ext-image-attributes
でクラスImageAttributesExtension
を使用します。
注: この拡張機能は ( StylesDelimiterProcessor
で) 区切り文字として中かっこ{
}
を使用するため、他の区切り文字プロセッサは区切りに中かっこを使用できないことを意味します。
リスト項目としてのタスクのサポートを追加します。
タスクは、最初の非空白文字が左括弧[
、次に 1 つの空白文字または小文字または大文字の文字x
、右括弧]
で、その後に少なくとも 1 つの空白文字が続き、その後に他の空白文字が続くリスト項目として表すことができます。コンテンツ。
例えば:
- [ ] task #1 - [x] task #2
次のようにレンダリングされます:
<ul> <li><input type="checkbox" disabled=""> task #1</li> <li><input type="checkbox" disabled="" checked=""> task #2</li> </ul>
アーティファクトcommonmark-ext-task-list-items
でクラスTaskListItemsExtension
を使用します。
他の拡張機能も実際に見つかります。
commonmark-ext-notifications: この拡張機能を使用すると、 INFO
、 SUCCESS
、 WARNING
、 ERROR
などの通知/警告の段落を簡単に作成できます。
このライブラリの一部のユーザー (追加をご希望の場合は、お気軽に PR を上げてください):
Atlassian (ライブラリが最初に開発された場所)
Java (OpenJDK) (リンク)
Gerrit コードレビュー/Gitiles (リンク)
Clojure 用の Clerk モールド可能なライブ プログラミング
ズナイ
Markwon: マークダウンをシステムネイティブの Spannables としてレンダリングするための Android ライブラリ
flexmark-java: より多くの構文と柔軟性のサポートを追加したフォーク
CONTRIBUTING.md ファイルを参照してください。
著作権 (c) 2015、ロビン ストッカー
BSD (2 条項) ライセンス付き。LICENSE.txt ファイルを参照してください。