{"id":13714930,"url":"https://github.com/vsch/flexmark-java","last_synced_at":"2025-05-13T15:07:28.298Z","repository":{"id":39654065,"uuid":"50244301","full_name":"vsch/flexmark-java","owner":"vsch","description":"CommonMark/Markdown Java parser with source level AST. CommonMark 0.28, emulation of: pegdown, kramdown, markdown.pl, MultiMarkdown. With HTML to MD, MD to PDF, MD to DOCX  conversion modules.","archived":false,"fork":false,"pushed_at":"2025-04-16T19:07:12.000Z","size":155879,"stargazers_count":2402,"open_issues_count":159,"forks_count":277,"subscribers_count":58,"default_branch":"master","last_synced_at":"2025-05-06T14:48:49.502Z","etag":null,"topics":["commonmark","html-to-markdown","java","markdown","markdown-conversion","markdown-flavors","markdown-parser","markdown-processor","markdown-to-html","markdown-to-pdf","pegdown"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vsch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-01-23T15:29:29.000Z","updated_at":"2025-05-04T15:29:11.000Z","dependencies_parsed_at":"2024-01-09T15:01:39.301Z","dependency_job_id":"26e5babe-c2ea-4d87-86b4-d8ffb69efed2","html_url":"https://github.com/vsch/flexmark-java","commit_stats":null,"previous_names":[],"tags_count":412,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vsch%2Fflexmark-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vsch%2Fflexmark-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vsch%2Fflexmark-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vsch%2Fflexmark-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vsch","download_url":"https://codeload.github.com/vsch/flexmark-java/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253969226,"owners_count":21992262,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["commonmark","html-to-markdown","java","markdown","markdown-conversion","markdown-flavors","markdown-parser","markdown-processor","markdown-to-html","markdown-to-pdf","pegdown"],"created_at":"2024-08-03T00:00:52.086Z","updated_at":"2025-05-13T15:07:28.266Z","avatar_url":"https://github.com/vsch.png","language":"Java","readme":"![Flexmark Icon Logo](assets/images/flexmark-icon-logo.png) flexmark-java\n=========================================================================\n\n**flexmark-java** is a Java implementation of **[CommonMark (spec 0.28)]** parser using the\nblocks first, inlines after Markdown parsing architecture.\n\nIts strengths are speed, flexibility, Markdown source element based AST with details of the\nsource position down to individual characters of lexemes that make up the element and\nextensibility.\n\nThe API allows granular control of the parsing process and is optimized for parsing with a large\nnumber of installed extensions. The parser and extensions come with plenty of options for parser\nbehavior and HTML rendering variations. The end goal is to have the parser and renderer be able\nto mimic other parsers with great degree of accuracy. This is now partially complete with the\nimplementation of [Markdown Processor Emulation](#markdown-processor-emulation)\n\nMotivation for this project was the need to replace [pegdown] parser in my [Markdown Navigator]\nplugin for JetBrains IDEs. [pegdown] has a great feature set but its speed in general is less\nthan ideal and for pathological input either hangs or practically hangs during parsing.\n\n:warning: **Version 0.60.0** has breaking changes due to re-organization, renaming, clean up and\noptimization of implementation classes. Changes are detailed in\n[Version-0.60.0-Changes](../../wiki/Version-0.60.0-Changes).\n\n### latest [![Maven Central status](https://img.shields.io/maven-central/v/com.vladsch.flexmark/flexmark.svg)](https://search.maven.org/search?q=g:com.vladsch.flexmark)\u003c!-- @IGNORE PREVIOUS: link --\u003e [![Javadocs](https://www.javadoc.io/badge/com.vladsch.flexmark/flexmark.svg)](https://www.javadoc.io/doc/com.vladsch.flexmark/flexmark)\n\n### Requirements\n\n* For Versions 0.62.2 or below, Java 8 or above, Java 9+ compatible. For Versions 0.64.0 or\n  above, Java 11 or above.\n* The project is on Maven: `com.vladsch.flexmark`\n* The core has no dependencies other than `org.jetbrains:annotations:24.0.1`. For extensions, see\n  extension description below.\n\n  The API is still evolving to accommodate new extensions and functionality.\n\n### Quick Start\n\nFor Maven, add `flexmark-all` as a dependency which includes core and all modules to the\nfollowing sample:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.vladsch.flexmark\u003c/groupId\u003e\n    \u003cartifactId\u003eflexmark-all\u003c/artifactId\u003e\n    \u003cversion\u003e0.64.8\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nSource:\n[BasicSample.java](flexmark-java-samples/src/com/vladsch/flexmark/java/samples/BasicSample.java)\n\n```java\npackage com.vladsch.flexmark.samples;\n\nimport com.vladsch.flexmark.util.ast.Node;\nimport com.vladsch.flexmark.html.HtmlRenderer;\nimport com.vladsch.flexmark.parser.Parser;\nimport com.vladsch.flexmark.util.data.MutableDataSet;\n\npublic class BasicSample {\n    public static void main(String[] args) {\n        MutableDataSet options = new MutableDataSet();\n\n        // uncomment to set optional extensions\n        //options.set(Parser.EXTENSIONS, Arrays.asList(TablesExtension.create(), StrikethroughExtension.create()));\n\n        // uncomment to convert soft-breaks to hard breaks\n        //options.set(HtmlRenderer.SOFT_BREAK, \"\u003cbr /\u003e\\n\");\n\n        Parser parser = Parser.builder(options).build();\n        HtmlRenderer renderer = HtmlRenderer.builder(options).build();\n\n        // You can re-use parser and renderer instances\n        Node document = parser.parse(\"This is *Sparta*\");\n        String html = renderer.render(document);  // \"\u003cp\u003eThis is \u003cem\u003eSparta\u003c/em\u003e\u003c/p\u003e\\n\"\n        System.out.println(html);\n    }\n}\n```\n\n#### Building via Gradle\n\n```shell\nimplementation 'com.vladsch.flexmark:flexmark-all:0.64.8'\n```\n\n#### Building with Android Studio\n\nAdditional settings due to duplicate files:\n\n```groovy\npackagingOptions {\n    exclude 'META-INF/LICENSE-LGPL-2.1.txt'\n    exclude 'META-INF/LICENSE-LGPL-3.txt'\n    exclude 'META-INF/LICENSE-W3C-TEST'\n    exclude 'META-INF/DEPENDENCIES'\n}\n```\n\nMore information can be found in the documentation:  \n[Wiki Home](../../wiki) \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Usage Examples](../../wiki/Usage)\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Extension Details](../../wiki/Extensions)\n\u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;[Writing Extensions](../../wiki/Writing-Extensions)\n\n### Pegdown Migration Helper\n\n`PegdownOptionsAdapter` class converts pegdown `Extensions.*` flags to flexmark options and\nextensions list. Pegdown `Extensions.java` is included for convenience and new options not found\nin pegdown 1.6.0. These are located in `flexmark-profile-pegdown` module but you can grab the\nsource from this repo: [PegdownOptionsAdapter.java], [Extensions.java] and make your own\nversion, modified to your project's needs.\n\nYou can pass your extension flags to static `PegdownOptionsAdapter.flexmarkOptions(int)` or you\ncan instantiate `PegdownOptionsAdapter` and use convenience methods to set, add and remove\nextension flags. `PegdownOptionsAdapter.getFlexmarkOptions()` will return a fresh copy of\n`DataHolder` every time with the options reflecting pegdown extension flags.\n\n```java\nimport com.vladsch.flexmark.html.HtmlRenderer;\nimport com.vladsch.flexmark.parser.Parser;\nimport com.vladsch.flexmark.profile.pegdown.Extensions;\nimport com.vladsch.flexmark.profile.pegdown.PegdownOptionsAdapter;\nimport com.vladsch.flexmark.util.data.DataHolder;\n\npublic class PegdownOptions {\n     final private static DataHolder OPTIONS = PegdownOptionsAdapter.flexmarkOptions(\n            Extensions.ALL\n    );\n\n    static final Parser PARSER = Parser.builder(OPTIONS).build();\n    static final HtmlRenderer RENDERER = HtmlRenderer.builder(OPTIONS).build();\n\n    // use the PARSER to parse and RENDERER to render with pegdown compatibility\n}\n```\n\nDefault flexmark-java pegdown emulation uses less strict HTML block parsing which interrupts an\nHTML block on a blank line. Pegdown only interrupts an HTML block on a blank line if all tags in\nthe HTML block are closed.\n\nTo get closer to original pegdown HTML block parsing behavior use the method which takes a\n`boolean strictHtml` argument:\n\n```java\nimport com.vladsch.flexmark.html.HtmlRenderer;\nimport com.vladsch.flexmark.parser.Parser;\nimport com.vladsch.flexmark.profile.pegdown.Extensions;\nimport com.vladsch.flexmark.profile.pegdown.PegdownOptionsAdapter;\nimport com.vladsch.flexmark.util.data.DataHolder;\n\npublic class PegdownOptions {\n     final private static DataHolder OPTIONS = PegdownOptionsAdapter.flexmarkOptions(true,\n            Extensions.ALL\n    );\n\n    static final Parser PARSER = Parser.builder(OPTIONS).build();\n    static final HtmlRenderer RENDERER = HtmlRenderer.builder(OPTIONS).build();\n\n    // use the PARSER to parse and RENDERER to render with pegdown compatibility\n}\n```\n\nA sample with a [custom link resolver] is also available, which includes link resolver for\nchanging URLs or attributes of links and a custom node renderer if you need to override the\ngenerated link HTML.\n\n:information_source: [flexmark-java] has many more extensions and configuration options than\n[pegdown] in addition to extensions available in pegdown 1.6.0.\n[Available Extensions via PegdownOptionsAdapter](../../wiki/Pegdown-Migration#available-extensions-via-pegdownoptionsadapter)\n\n### Latest Additions and Changes\n\n* Major reorganization and code cleanup of implementation in version 0.60.0, see\n  [Version-0.60.0-Changes](../../wiki/Version-0.60.0-Changes) thanks to great work by\n  [Alex Karezin](mailto:javadiagrams@gmail.com) you can get an overview of module dependencies\n  with ability to drill down to packages and classes.\n* [Merge API](../../wiki/Markdown-Merge-API) to merge multiple markdown documents into a single\n  document.\n* Docx Renderer Extension:\n  [Limited Attributes Node Handling](../../wiki/Docx-Renderer-Extension#limited-attributes-node-handling)\n* Extensible HTML to Markdown Converter module:\n  [flexmark-html2md-converter](flexmark-html2md-converter). Sample:\n  [HtmlToMarkdownCustomizedSample.java]\n* Java9+ module compatibility\n* Compound Enumerated References\n  [Enumerated References Extension](../../wiki/Enumerated-References-Extension) for creating\n  legal numbering for elements and headings.\n* [Macros Extension](../../wiki/Macros-Extension) to allow arbitrary markdown content to be\n  inserted as block or inline elements, allowing block elements to be used where only inline\n  elements are allowed by syntax.\n* [GitLab Flavoured Markdown](../../wiki/Extensions#gitlab-flavoured-markdown) for parsing and\n  rendering GitLab markdown extensions.\n* OSGi module courtesy Dan Klco (GitHub [@klcodanr](https://github.com/klcodanr))\n* [Media Tags](../../wiki/Extensions#media-tags) Media link transformer extension courtesy\n  Cornelia Schultz (GitHub [@CorneliaXaos](https://github.com/CorneliaXaos)) transforms links\n  using custom prefixes to Audio, Embed, Picture, and Video HTML5 tags.\n* [Translation Helper API](../../wiki/Translation-Helper-API) to make translating markdown\n  documents easier.\n* [Admonition](../../wiki/Extensions#admonition) To create block-styled side content. For\n  complete documentation please see the [Admonition Extension, Material for MkDocs]\n  documentation.\n* [Enumerated Reference](../../wiki/Extensions#enumerated-reference) to create enumerated\n  references for figures, tables and other markdown elements.\n* [Attributes](../../wiki/Extensions#attributes) to parse attributes of the form `{name\n  name=value name='value' name=\"value\" #id .class-name}` attributes.\n* [YouTube Embedded Link Transformer](../../wiki/Extensions#youtube-embedded-link-transformer)\n  thanks to Vyacheslav N. Boyko (GitHub @bvn13) transforms simple links to youtube videos to\n  embedded video iframe HTML.\n* [Docx Converter](../../wiki/Extensions#docx-converter) using the [docx4j] library. How to use:\n  [DocxConverter Sample], how to customize:\n  [Customizing Docx Rendering](../../wiki/Customizing-Docx-Rendering)\n\n  Development of this module was sponsored by\n  [Johner Institut GmbH](https://www.johner-institut.de).\n* Update library to be [CommonMark (spec 0.28)] compliant and add\n  `ParserEmulationProfile.COMMONMARK_0_27` and `ParserEmulationProfile.COMMONMARK_0_28` to allow\n  selecting a specific spec version options.\n* Custom node rendering API with ability to invoke standard rendering for an overridden node,\n  allowing custom node renders that only handle special cases and let the rest be rendered as\n  usual. [custom link resolver]\n* [Gfm-Issues](../../wiki/Extensions#gfm-issues) and\n  [Gfm-Users](../../wiki/Extensions#gfm-users) extensions for parsing and rendering `#123` and\n  `@user-name` respectively.\n* Deep HTML block parsing option for better handling of raw text tags that come after other tags\n  and for [pegdown] HTML block parsing compatibility.\n* `flexmark-all` module that includes: core, all extensions, formatter, JIRA and YouTrack\n  converters, pegdown profile module and HTML to Markdown conversion.\n* [PDF Output Module](../../wiki/Extensions#pdf-output-module)\n  [PDF output](../../wiki/Usage#pdf-output) using [Open HTML To PDF]\n* [Typographic](../../wiki/Extensions#typographic) implemented\n* [XWiki Macro Extension](../../wiki/Extensions#xwiki-macro-extension)\n* [Jekyll Tags](../../wiki/Extensions#jekyll-tags)\n* [Html To Markdown](../../wiki/Extensions#html-to-markdown)\n* [Maven Markdown Page Generator Plugin](https://github.com/vsch/markdown-page-generator-plugin)\n* [Markdown Formatter](../../wiki/Markdown-Formatter) module to output AST as markdown with\n  formatting options.\n* [Tables](../../wiki/Extensions#tables) for [Markdown Formatter](../../wiki/Markdown-Formatter)\n  with column width and alignment of markdown tables:\n\n  \u003ctable\u003e\n      \u003cthead\u003e \u003ctr\u003e\u003cth\u003eInput\u003c/th\u003e \u003cth\u003eOutput\u003c/th\u003e \u003c/tr\u003e \u003c/thead\u003e\n      \u003ctr\u003e\u003ctd\u003e\n      \u003cpre\u003e\u003ccode class=\"language-markdown\"\u003eday|time|spent\n  :---|:---:|--:\n  nov. 2. tue|10:00|4h 40m\n  nov. 3. thu|11:00|4h\n  nov. 7. mon|10:20|4h 20m\n  total:|| 13h\u003c/code\u003e\u003c/pre\u003e\n      \u003c/td\u003e\u003ctd\u003e\n      \u003cpre\u003e\u003ccode class=\"language-markdown\"\u003e| day         | time  |   spent |\n  |:------------|:-----:|--------:|\n  | nov. 2. tue | 10:00 |  4h 40m |\n  | nov. 3. thu | 11:00 |      4h |\n  | nov. 7. mon | 10:20 |  4h 20m |\n  | total:             ||     13h |\u003c/code\u003e\u003c/pre\u003e\n      \u003c/td\u003e\u003c/tr\u003e\n  \u003c/table\u003e\n\n### Releases, Bug Fixes, Enhancements and Support\n\nI use flexmark-java as the parser for [Markdown Navigator] plugin for JetBrains IDEs. I tend to\nuse the latest, unreleased version to fix bugs or get improvements. So if you find a bug that is\na show stopper for your project or see a bug in [github issues page] marked `fixed for next\nrelease` that is affecting your project then please let me know and I may be able to promptly\nmake a new release to address your issue. Otherwise, I will let bug fixes and enhancements\naccumulate thinking no one is affected by what is already fixed.\n\n#### Extension points in the API are many and numerous\n\nThere are many extension options in the API with their intended use. A good soft-start is the\n[`flexmark-java-samples`](flexmark-java-samples) module which has simple samples for asked for\nextensions. The next best place is the source of an existing extension that has similar syntax\nto what you want to add.\n\nIf your extension lines up with the right API, the task is usually very short and sweet. If your\nextension uses the API in an unintended fashion or does not follow expected housekeeping\nprotocols, you may find it an uphill battle with a rat's nest of if/else condition handling and\nfixing one bug only leading to creating another one.\n\nGenerally, if it takes more than a few dozen lines to add a simple extension, then either you\nare going about it wrong or the API is missing an extension point. If you look at all the\nimplemented extensions you will see that most are a few lines of code other than boiler plate\ndictated by the API. That is the goal for this library: provide an extensible core that makes\nwriting extensions a breeze.\n\nThe larger extensions are `flexmark-ext-tables` and `flexmark-ext-spec-example`, the meat of\nboth is around 200 lines of code. You can use them as a guide post for size estimating your\nextension.\n\nMy own experience adding extensions shows that sometimes a new type of extension is best\naddressed with an API enhancement to make its implementation seamless, or by fixing a bug that\nwas not visible before the extension stressed the API in just the right way. Your intended\nextension may just be the one requiring such an approach.\n\n#### Don't hesitate to open an issue if you can't find the answer\n\nThe takeaway is: if you want to implement an extension or a feature please don't hesitate to\nopen an issue and I will give you pointers on the best way to go about it. It may save you a lot\nof time by letting me improve the API to address your extension's needs before you put a lot of\nfruitless effort into it.\n\nI do ask that you realize that I am chief cook and bottle washer on this project, without an\niota of Vulcan Mind Melding skills. I do ask that you describe what you want to implement\nbecause I can't read your mind. Please do some reconnaissance background work around the source\ncode and documentation because I cannot transfer what I know to you, without your willing\neffort.\n\n#### Consulting is available\n\nIf you have a commercial application and don't want to write the extension(s) yourself or want\nto reduce the time and effort of implementing extensions and integrating flexmark-java, feel\nfree to contact me. I am available on a consulting/contracting basis.\n\n### Markdown Processor Emulation\n\nDespite its name, commonmark is neither a superset nor a subset of other markdown flavors.\nRather, it proposes a standard, unambiguous syntax specification for the original, \"core\"\nMarkdown, thus effectively introducing yet another flavor. While flexmark is by default\ncommonmark compliant, its parser can be tweaked in various ways. The sets of tweaks required to\nemulate the most commonly used markdown parsers around are available in flexmark as\n`ParserEmulationProfiles`.\n\nAs the name `ParserEmulationProfile` implies, it's only the parser that is adjusted to the\nspecific markdown flavor. Applying the profile does not add features beyond those available in\ncommonmark. If you want to use flexmark to fully emulate another markdown processor's behavior,\nyou have to adjust the parser and configure the flexmark extensions that provide the additional\nfeatures available in the parser that you want to emulate.\n\nA rewrite of the list parser to better control emulation of other markdown processors as per\n[Markdown Processors Emulation](MarkdownProcessorsEmulation.md) is complete. Addition of\nprocessor presets to emulate specific markdown processing behaviour of these parsers is on a\nshort to do list.\n\nSome emulation families do a better better job of emulating their target than others. Most of\nthe effort was directed at emulating how these processors parse standard Markdown and list\nrelated parsing specifically. For processors that extend original Markdown, you will need to add\nthose extensions that are already implemented in flexmark-java to the Parser/Renderer builder\noptions.\n\nExtensions will be modified to include their own presets for specific processor emulation, if\nthat processor has an equivalent extension implemented.\n\nIf you find a discrepancy please open an issue so it can be addressed.\n\nMajor processor families are implemented and some family members also:\n\n* [ ] [Jekyll]\n* [CommonMark] for latest implemented spec, currently [CommonMark (spec 0.28)]\n  * [ ] [League/CommonMark]\n  * [CommonMark (spec 0.27)] for specific version compatibility\n  * [CommonMark (spec 0.28)] for specific version compatibility\n  * [GitHub] Comments\n* [Markdown.pl][Markdown]\n  * [ ] [Php Markdown Extra]\n  * [GitHub] Docs (old GitHub markdown parser)\n* [Kramdown]\n* FixedIndent\n  * [MultiMarkdown]\n  * [Pegdown]\n\n:information_source: profiles to encapsulate configuration details for variants within the\nfamily were added in 0.11.0:\n\n* CommonMark (default for family): `ParserEmulationProfile.COMMONMARK`\n* FixedIndent (default for family): `ParserEmulationProfile.FIXED_INDENT`\n* GitHub Comments (just CommonMark): `ParserEmulationProfile.COMMONMARK`\n* Old GitHub Docs: `ParserEmulationProfile.GITHUB_DOC`\n* Kramdown (default for family): `ParserEmulationProfile.KRAMDOWN`\n* Markdown.pl (default for family): `ParserEmulationProfile.MARKDOWN`\n* MultiMarkdown: `ParserEmulationProfile.MULTI_MARKDOWN`\n* Pegdown, with pegdown extensions use `PegdownOptionsAdapter` in `flexmark-profile-pegdown`\n* Pegdown, without pegdown extensions `ParserEmulationProfile.PEGDOWN`\n* Pegdown HTML block parsing rules, without pegdown extensions\n  `ParserEmulationProfile.PEGDOWN_STRICT`\n\n### History and Motivation\n\n**flexmark-java** is a fork of [commonmark-java] project, modified to generate an AST which\nreflects all the elements in the original source, full source position tracking for all elements\nin the AST and easier JetBrains Open API PsiTree generation.\n\nThe API was changed to allow more granular control of the parsing process and optimized for\nparsing with a large number of installed extensions. The parser and extensions come with many\ntweaking options for parser behavior and HTML rendering variations. The end goal is to have the\nparser and renderer be able to mimic other parsers with great degree of accuracy.\n\nMotivation for this was the need to replace [pegdown] parser in [Markdown Navigator] plugin.\n[pegdown] has a great feature set but its speed in general is less than ideal and for\npathological input either hangs or practically hangs during parsing.\n\n[commonmark-java] has an excellent parsing architecture that is easy to understand and extend.\nThe goal was to ensure that adding source position tracking in the AST would not change the ease\nof parsing and generating the AST more than absolutely necessary.\n\nReasons for choosing [commonmark-java] as the parser are: speed, ease of understanding, ease of\nextending and speed. Now that I have reworked the core and added a few extensions I am extremely\nsatisfied with my choice.\n\nAnother goal was to improve the ability of extensions to modify parser behavior so that any\ndialect of markdown could be implemented through the extension mechanism. An extensible options\nAPI was added to allow setting of all options in one place. Parser, renderer and extensions use\nthese options for configuration, including disabling some core block parsers.\n\nThis is a work in progress with many API changes. No attempt is made to keep backward API\ncompatibility to the original project and until the feature set is mostly complete, not even to\nearlier versions of this project.\n\n### Feature Comparison\n\n| Feature                                                                          | flexmark-java                                                    | commonmark-java                                                   | pegdown                                                              |\n|:---------------------------------------------------------------------------------|:-----------------------------------------------------------------|:------------------------------------------------------------------|:---------------------------------------------------------------------|\n| Relative parse time (less is better)                                             | :heavy_check_mark: 1x [(1)](#1)                                  | :heavy_check_mark: 0.6x to 0.7x [(2)](#2)                         | :x: 25x average, 20,000x to ∞ for pathological input [(3)](#3)       |\n| All source elements in the AST                                                   | :heavy_check_mark:                                               | :x:                                                               | :heavy_check_mark:                                                   |\n| AST elements with source position                                                | :heavy_check_mark:                                               | :heavy_check_mark:                                                | :heavy_check_mark: with some errors and idiosyncrasies               |\n| AST can be easily manipulated                                                    | :heavy_check_mark: AST post processing is an extension mechanism | :heavy_check_mark: AST post processing is an extension mechanism  | :x: not an option. No node's parent information, children as List\u003c\u003e. |\n| AST elements have detailed source position for all parts                         | :heavy_check_mark:                                               | :x:                                                               | :x: only node start/end                                              |\n| Can disable core parsing features                                                | :heavy_check_mark:                                               | :x:                                                               | :x:                                                                  |\n| Core parser implemented via the extension API                                    | :heavy_check_mark:                                               | :x: `instanceOf` tests for specific block parser and node classes | :x: core exposes few extension points                                |\n| Easy to understand and modify parser implementation                              | :heavy_check_mark:                                               | :heavy_check_mark:                                                | :x: one PEG parser with complex interactions [(3)](#3)               |\n| Parsing of block elements is independent from each other                         | :heavy_check_mark:                                               | :heavy_check_mark:                                                | :x: everything in one PEG grammar                                    |\n| Uniform configuration across: parser, renderer and all extensions                | :heavy_check_mark:                                               | :x: none beyond extension list                                    | :x: `int` bit flags for core, none for extensions                    |\n| Parsing performance optimized for use with extensions                            | :heavy_check_mark:                                               | :x: parsing performance for core, extensions do what they can     | :x: performance is not a feature                                     |\n| Feature rich with many configuration options and extensions out of the box       | :heavy_check_mark:                                               | :x: limited extensions, no options                                | :heavy_check_mark:                                                   |\n| Dependency definitions for processors to guarantee the right order of processing | :heavy_check_mark:                                               | :x: order specified by extension list ordering, error prone       | :x: not applicable, core defines where extension processing is added |\n\n\u003c!--\n|  | :x: | :x: | :x: |\n|  | :x: | :x: | :x: |\n|  | :x: | :x: | :x: |\n|  | :x: | :x: | :x: |\n|  | :x: | :x: | :x: |\n|--|:----|:----|:----|\n|  | :x: | :x: | :x: |\n--\u003e\n\n###### (1)\n\nflexmark-java pathological input of 100,000 `[` parses in 68ms, 100,000 `]` in 57ms, 100,000\nnested `[` `]` parse in 55ms\n\n###### (2)\n\ncommonmark-java pathological input of 100,000 `[` parses in 30ms, 100,000 `]` in 30ms, 100,000\nnested `[` `]` parse in 43ms\n\n###### (3)\n\npegdown pathological input of 17 `[` parses in 650ms, 18 `[` in 1300ms\n\nProgress\n--------\n\n* Parser options, items marked as a task item are to be implemented the rest are complete:\n  * Typographic\n    * Quotes\n    * Smarts\n  * GitHub Extensions\n    * Fenced code blocks\n    * Anchor links for headers with auto id generation\n    * Table Spans option to be implemented for tables extension\n    * Wiki Links with GitHub and Creole syntax\n    * Emoji Shortcuts with use GitHub emoji URL option\n  * GitHub Syntax\n    * Strikethrough\n    * Task Lists\n    * No Atx Header Space\n    * No Header indents\n    * Hard Wraps (achieved with SOFT_BREAK option changed to `\"\u003cbr /\u003e\"`)\n    * Relaxed HR Rules Option\n    * Wiki links\n  * Publishing\n    * Abbreviations\n    * Footnotes\n    * Definitions\n    * Table of Contents\n  * Suppress\n    * inline HTML: all, non-comments, comments\n    * HTML blocks: all, non-comments, comments\n  * Processor Extensions\n    * Jekyll front matter\n    * Jekyll tag elements, with support for `{% include file %}`,\n      [Include Markdown and HTML File Content]\n    * GitBook link URL encoding. Not applicable\n    * HTML comment nodes: Block and Inline\n    * Multi-line Image URLs\n    * Spec Example Element\n  * Commonmark Syntax suppression\n    * Manual loose lists\n    * Numbered lists always start with 1.\n    * Fixed list item indent, items must be indented by at least 4 spaces\n    * Relaxed list start option, allow lists to start when not preceded by a blank line.\n\nI am very pleased with the decision to switch to [commonmark-java] based parser for my own\nprojects. Even though I had to do major surgery on its innards to get full source position\ntracking and AST that matches source elements, it is a pleasure to work with and is now a\npleasure to extend. If you don't need source level element AST or the rest of what flexmark-java\nadded and [CommonMark] is your target markdown parser then I encourage you to use\n[commonmark-java] as it is an excellent choice for your needs and its performance does not\nsuffer for the overhead of features that you will not use.\n\nBenchmarks\n----------\n\nLatest, Jan 28, 2017 flexmark-java 0.13.1, intellij-markdown from CE EAP 2017, commonmark-java\n0.8.0:\n\n| File             | commonmark-java | flexmark-java | intellij-markdown |   pegdown |\n|:-----------------|----------------:|--------------:|------------------:|----------:|\n| README-SLOW      |         0.420ms |       0.812ms |           2.027ms |  15.483ms |\n| VERSION          |         0.743ms |       1.425ms |           4.057ms |  42.936ms |\n| commonMarkSpec   |        31.025ms |      44.465ms |         600.654ms | 575.131ms |\n| markdown_example |         8.490ms |      10.502ms |         223.593ms | 983.640ms |\n| spec             |         4.719ms |       6.249ms |          35.883ms | 307.176ms |\n| table            |         0.229ms |       0.623ms |           0.800ms |   3.642ms |\n| table-format     |         1.385ms |       2.881ms |           4.150ms |  23.592ms |\n| wrap             |         3.804ms |       4.589ms |          16.609ms |  86.383ms |\n\nRatios of above:\n\n| File             | commonmark-java | flexmark-java | intellij-markdown |   pegdown |\n|:-----------------|----------------:|--------------:|------------------:|----------:|\n| README-SLOW      |            1.00 |          1.93 |              4.83 |     36.88 |\n| VERSION          |            1.00 |          1.92 |              5.46 |     57.78 |\n| commonMarkSpec   |            1.00 |          1.43 |             19.36 |     18.54 |\n| markdown_example |            1.00 |          1.24 |             26.34 |    115.86 |\n| spec             |            1.00 |          1.32 |              7.60 |     65.09 |\n| table            |            1.00 |          2.72 |              3.49 |     15.90 |\n| table-format     |            1.00 |          2.08 |              3.00 |     17.03 |\n| wrap             |            1.00 |          1.21 |              4.37 |     22.71 |\n| **overall**      |        **1.00** |      **1.41** |         **17.47** | **40.11** |\n\n| File             | commonmark-java | flexmark-java | intellij-markdown |   pegdown |\n|:-----------------|----------------:|--------------:|------------------:|----------:|\n| README-SLOW      |            0.52 |          1.00 |              2.50 |     19.07 |\n| VERSION          |            0.52 |          1.00 |              2.85 |     30.12 |\n| commonMarkSpec   |            0.70 |          1.00 |             13.51 |     12.93 |\n| markdown_example |            0.81 |          1.00 |             21.29 |     93.66 |\n| spec             |            0.76 |          1.00 |              5.74 |     49.15 |\n| table            |            0.37 |          1.00 |              1.28 |      5.85 |\n| table-format     |            0.48 |          1.00 |              1.44 |      8.19 |\n| wrap             |            0.83 |          1.00 |              3.62 |     18.83 |\n| **overall**      |        **0.71** |      **1.00** |         **12.41** | **28.48** |\n\n---\n\nBecause these two files represent the pathological input for pegdown, I no longer run them as\npart of the benchmark to prevent skewing of the results. The results are here for posterity.\n\n| File          | commonmark-java | flexmark-java | intellij-markdown |    pegdown |\n|:--------------|----------------:|--------------:|------------------:|-----------:|\n| hang-pegdown  |         0.082ms |       0.326ms |           0.342ms |  659.138ms |\n| hang-pegdown2 |         0.048ms |       0.235ms |           0.198ms | 1312.944ms |\n\nRatios of above:\n\n| File          | commonmark-java | flexmark-java | intellij-markdown |      pegdown |\n|:--------------|----------------:|--------------:|------------------:|-------------:|\n| hang-pegdown  |            1.00 |          3.98 |              4.17 |      8048.38 |\n| hang-pegdown2 |            1.00 |          4.86 |              4.10 |     27207.32 |\n| **overall**   |        **1.00** |      **4.30** |          **4.15** | **15151.91** |\n\n| File          | commonmark-java | flexmark-java | intellij-markdown |     pegdown |\n|:--------------|----------------:|--------------:|------------------:|------------:|\n| hang-pegdown  |            0.25 |          1.00 |              1.05 |     2024.27 |\n| hang-pegdown2 |            0.21 |          1.00 |              0.84 |     5594.73 |\n| **overall**   |        **0.23** |      **1.00** |          **0.96** | **3519.73** |\n\n* [VERSION.md] is the version log file I use for Markdown Navigator\n* [commonMarkSpec.md] is a 33k line file used in [intellij-markdown] test suite for performance\n  evaluation.\n* [spec.txt] commonmark spec markdown file in the [commonmark-java] project\n* [hang-pegdown.md] is a file containing a single line of 17 characters `[[[[[[[[[[[[[[[[[`\n  which causes pegdown to go into a hyper-exponential parse time.\n* [hang-pegdown2.md] a file containing a single line of 18 characters `[[[[[[[[[[[[[[[[[[` which\n  causes pegdown to go into a hyper-exponential parse time.\n* [wrap.md] is a file I was using to test wrap on typing performance only to discover that it\n  has nothing to do with the wrap on typing code when 0.1 seconds is taken by pegdown to parse\n  the file. In the plugin the parsing may happen more than once: syntax highlighter pass, psi\n  tree building pass, external annotator.\n* markdown_example.md a file with 10,000+ lines containing 500kB+ of text.\n\nContributing\n------------\n\nPull requests, issues and comments welcome :smile:. For pull requests:\n\n* Add tests for new features and bug fixes, preferably in the\n  [ast_spec.md](flexmark-core-test/src/test/resources/ast_spec.md) format\n* Follow the existing style to make merging easier, as much as possible: 4 space indent,\n  trailing spaces trimmed.\n\n* * *\n\nLicense\n-------\n\nCopyright (c) 2015-2016 Atlassian and others.\n\nCopyright (c) 2016-2023, Vladimir Schneider,\n\nBSD (2-clause) licensed, see [LICENSE.txt] file.\n\n[Admonition Extension, Material for MkDocs]: https://squidfunk.github.io/mkdocs-material/reference/admonitions/\n[CommonMark]: https://commonmark.org\n[CommonMark (spec 0.27)]: https://spec.commonmark.org/0.27\n[CommonMark (spec 0.28)]: https://spec.commonmark.org/0.28\n[DocxConverter Sample]: flexmark-java-samples/src/com/vladsch/flexmark/java/samples/DocxConverterCommonMark.java\n[Extensions.java]: flexmark-profile-pegdown/src/main/java/com/vladsch/flexmark/profile/pegdown/Extensions.java\n[GitHub]: https://github.com/vsch/laravel-translation-manager\n[GitHub Issues page]: ../../issues\n[HtmlToMarkdownCustomizedSample.java]: flexmark-java-samples/src/com/vladsch/flexmark/java/samples/HtmlToMarkdownCustomizedSample.java\n[Include Markdown and HTML File Content]: ../../wiki/Usage#include-markdown-and-html-file-content\n[Jekyll]: https://jekyllrb.com\n[Kramdown]: https://kramdown.gettalong.org\n[LICENSE.txt]: LICENSE.txt\n[League/CommonMark]: https://github.com/thephpleague/commonmark\n[Markdown]: https://daringfireball.net/projects/markdown/\n[Markdown Navigator]: https://github.com/vsch/idea-multimarkdown\n[MultiMarkdown]: https://fletcherpenney.net/multimarkdown\n[Open HTML To PDF]: https://github.com/danfickle/openhtmltopdf\n[PHP Markdown Extra]: https://michelf.ca/projects/php-markdown/extra/#abbr\n[PegdownOptionsAdapter.java]: flexmark-profile-pegdown/src/main/java/com/vladsch/flexmark/profile/pegdown/PegdownOptionsAdapter.java\n[VERSION.md]: https://github.com/vsch/idea-multimarkdown/blob/master/test-data/performance/VERSION.md\n[commonmark-java]: https://github.com/atlassian/commonmark-java\n[commonMarkSpec.md]: https://github.com/vsch/idea-multimarkdown/blob/master/test-data/performance/commonMarkSpec.md\n[custom link resolver]: flexmark-java-samples/src/com/vladsch/flexmark/java/samples/PegdownCustomLinkResolverOptions.java\n[docx4j]: https://www.docx4java.org/trac/docx4j\n[flexmark-java]: https://github.com/vsch/flexmark-java\n[hang-pegdown.md]: https://github.com/vsch/idea-multimarkdown/blob/master/test-data/performance/hang-pegdown.md\n[hang-pegdown2.md]: https://github.com/vsch/idea-multimarkdown/blob/master/test-data/performance/hang-pegdown2.md\n[intellij-markdown]: https://github.com/valich/intellij-markdown\n[pegdown]: https://github.com/sirthias/pegdown\n[spec.txt]: https://github.com/vsch/idea-multimarkdown/blob/master/test-data/performance/spec.md\n[wrap.md]: https://github.com/vsch/idea-multimarkdown/blob/master/test-data/performance/wrap.md\n\n","funding_links":[],"categories":["Libraries","Java"],"sub_categories":["Java"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvsch%2Fflexmark-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvsch%2Fflexmark-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvsch%2Fflexmark-java/lists"}