用於根據 CommonMark 規範(和一些擴充)解析和渲染 Markdown 文字的 Java 函式庫。
提供用於解析抽象語法樹 (AST) 的輸入、存取和操作節點以及渲染為 HTML 或返回為 Markdown 的類別。它最初是 commonmark.js 的一個端口,但後來發展成為一個具有以下功能的可擴展庫:
小(核心沒有依賴項,擴展在單獨的工件中)
快速(比過去流行的 Markdown 庫 pegdown 快 10-20 倍,請參閱 repo 中的基準測試)
靈活(解析後操作AST,自訂HTML渲染)
可擴充(表格、刪除線、自動連結等,見下文)
Java 11 及更高版本支援該程式庫。它也適用於 Android,但這是在盡最大努力的基礎上,請回報問題。對於 Android,最低 API 等級為 19,請參閱 commonmark-android-test 目錄。
核心庫的座標(在 Maven Central 上查看所有內容):
<依賴關係> <groupId>org.commonmark</groupId> <artifactId>通用標記</artifactId> <版本>0.24.0</版本> </依賴>
Java 9 中使用的模組名稱是org.commonmark
、 org.commonmark.ext.autolink
等,對應於套件名稱。
請注意,對於此程式庫的 0.x 版本,該 API 尚未被視為穩定,並且可能會在次要版本之間中斷。 1.0之後,將遵循語義版本控制。包含beta
的套件意味著它還不受穩定的 API 保證;但對於正常使用來說,沒有必要使用。
如果您想知道目前實作了哪個版本的規範,請參閱 spec.txt 檔案。另請參閱 CommonMark dingus 以熟悉語法或嘗試邊緣情況。如果您克隆儲存庫,您也可以使用DingusApp
類別以互動方式進行嘗試。
導入org.commonmark.node.*;導入org.commonmark.parser.Parser;導入org.commonmark.renderer.html.HtmlRenderer;解析器解析器= Parser.builder().build();節點文件= parser.parse ("這是*Markdown*");HtmlRenderer renderer = HtmlRenderer.builder().build();renderer.render(document); //“<p>這是<em>Markdown</em></p>n”
這使用帶有預設選項的解析器和渲染器。兩個建構器都有配置其行為的方法:
HtmlRenderer
上的escapeHtml(true)
將轉義原始 HTML 標籤和區塊。
HtmlRenderer
上的sanitizeUrls(true)
將從<a>
和<img>
標記中移除潛在不安全的 URL
對於所有可用選項,請參閱建構器上的方法。
請注意,該庫不會嘗試清理生成的 HTML(關於允許使用哪些標籤等)。
導入org.commonmark.node.*;導入org.commonmark.renderer.markdown.MarkdownRenderer;MarkdownRenderer 渲染器= MarkdownRenderer.builder().build();節點文件= new Document();Heading 標題= new Heading(); heading .setLevel(2);heading.appendChild(new Text("我的標題"));document.appendChild(標題);renderer.render(document); // "## 我的標題n"
為了以最少的標記渲染為純文本,還有TextContentRenderer
。
解析原始文字後,結果是一棵節點樹。該樹可以在渲染之前修改,或者只是在不渲染的情況下進行檢查:
Node node = parser.parse("範例n========nn更多文字");WordCountVisitor guest = new WordCountVisitor();node.accept(visitor);visitor.wordCount; // 4class WordCountVisitor 擴充 AbstractVisitor { int wordCount = 0; @Override public void Visit(Text text) { // 為所有 Text 節點呼叫此方法。覆蓋其他節點類型的其他存取方法。 // 計算單字數(這只是一個例子,由於各種原因實際上不要這樣做)。 wordCount += text.getLiteral().split("\W+").length; // 下降到子節點(在這種情況下可以省略,因為文字節點沒有子節點)。 訪問兒童(文本); } }
如果您想知道已解析的Node
出現在輸入來源文字中的位置,您可以請求解析器返回來源位置,如下所示:
var parser = Parser.builder().includeSourceSpans(IncludeSourceSpans.BLOCKS_AND_INLINES).build();
然後解析節點並檢查來源位置:
var source = "foonnbar *baz*";var doc = parser.parse(source);var 強調 = doc.getLastChild().getLastChild();var s = 強調.getSourceSpans().get(0) ;s.getLineIndex(); // 2(第三行)s.getColumnIndex(); // 4(第五列)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 (節點實例影像) { attribute.put("class", "border"); } } }
如果您想要做的不僅僅是更改屬性,還有一種方法可以完全控制 HTML 的呈現方式。
在此範例中,我們將更改縮排程式碼區塊的呈現,以僅將它們包裝在pre
而不是pre
和code
中:
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 處理一種類型,所以我們可以在這裡強制轉換它。 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</版本> </依賴>
然後,在建構器上配置擴充:
導入 org.commonmark.ext.gfm.tables.TablesExtension;List<Extension> 擴充功能 = List.of(TablesExtension.create());解析器解析器 = Parser.builder() .副檔名(副檔名) .build();HtmlRenderer 渲染器 = HtmlRenderer.builder() .副檔名(副檔名) 。
要配置上例中的另一個擴展,只需將其添加到清單中即可。
以下擴充功能是使用此程式庫開發的,每個擴充功能都有自己的工件。
將 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
透過FootnotesExtension.Builder#inlineFootnotes
啟用時,也支援像^[inline footnote]
這樣的內聯註腳。
在工件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 Front Matter 區塊新增對元資料的支援。此擴充僅支援 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
中),這意味著其他分隔符號處理器不能使用大括號進行分隔。
新增對任務作為清單項目的支援。
任務可以表示為一個列表項,其中第一個非空白字符是左括號[
,然後是單個空白字符或小寫或大寫的字母x
,然後是右括號]
後跟至少一個空白字符,然後是任何其他空白字元內容。
例如:
- [ ] 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 程式碼審查/Gtiles(連結)
Clojure 的 Clerk 可塑即時編程
茲奈
Markwon:用於將 Markdown 渲染為系統原生 Spannables 的 Android 函式庫
flexmark-java:添加了對更多語法和靈活性的支持的分叉
請參閱 CONTRIBUTING.md 檔案。
版權所有 (c) 2015,羅賓‧斯托克
BSD(2-clause)許可,請參閱 LICENSE.txt 檔案。