commonmark-java

repository·main·Indexed 25 days ago

https://github.com/commonmark/commonmark-java

A fast, extensible Java library for parsing Markdown text into an Abstract Syntax Tree (AST) and rendering it to HTML, Markdown, or plain text. It follows the CommonMark specification and supports various extensions including GFM tables, task lists, and alerts. The library provides tools for AST traversal via visitors, custom HTML rendering through NodeRenderer and AttributeProvider, and support for Android environments.

Tokens
3.8K
Snippets
14
Records
17
Agent score
83%

What's inside commonmark-java

  1. Use GFM Alerts extension in commonmark-java

    main

    To enable support for GitHub Flavored Markdown (GFM) alerts, create an AlertsExtension and register it with both the Parser and the HtmlRenderer. This allows you to use the > [!TYPE] syntax in your markdown.

    var extension = AlertsExtension.create();
    var parser = Parser.builder().extensions(List.of(extension)).build();
    var renderer = HtmlRenderer.builder().extensions(List.of(extension)).build();
  2. Enable extensions in Parser and Renderer

    main

    Extensions are provided in separate artifacts. To use them, add the extension dependency and pass a list of Extension objects to both the Parser.Builder and HtmlRenderer.Builder.

    <!-- Example: Adding GFM Tables -->
    <dependency>
        <groupId>org.commonmark</groupId>
        <artifactId>commonmark-ext-gfm-tables</artifactId>
        <version>0.29.0</version>
    </dependency>
    import org.commonmark.ext.gfm.tables.TablesExtension;
    
    List<Extension> extensions = List.of(TablesExtension.create());
    Parser parser = Parser.builder()
            .extensions(extensions)
            .build();
    HtmlRenderer renderer = HtmlRenderer.builder()
            .extensions(extensions)
            .build();
  3. Install commonmark core via Maven

    main

    To use the core CommonMark library in your Java project, add the following dependency to your pom.xml. Note that for 0.x releases, the API is not considered stable and may break between minor releases.

    <dependency>
        <groupId>org.commonmark</groupId>
        <artifactId>commonmark</artifactId>
        <version>0.29.0</version>
    </dependency>
  4. Set up commonmark-android-test environment

    main

    To run lint checks for Android support in commonmark-java, ensure your environment meets the following requirements and configuration steps:

    Requirements

    • Java: Version 11 or above
    • Android SDK: Version 30 installed (x86 is recommended)

    Configuration Steps

    1. Download the Android SDK.
    2. Ensure SDK Platform 30 is installed.
    3. Add the following directories to your PATH environment variable:
      • path_to_android_sdk/platform-tools
      • path_to_android_sdk/tools
    4. Create a local.properties file in the commonmark-android-test directory and define the SDK path:
    sdk.dir=/path_to_android_sdk
  5. Add or change HTML element attributes

    main

    Use an AttributeProvider to inject custom attributes (like CSS classes) into specific HTML elements during rendering.

    Parser 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 implements AttributeProvider {
        @Override
        public void setAttributes(Node node, String tagName, Map<String, String> attributes) {
            if (node instanceof Image) {
                attributes.put("class", "border");
            }
        }
    }
  6. Parse and render Markdown to HTML

    main

    Use Parser to convert Markdown text into an Abstract Syntax Tree (AST) and HtmlRenderer to convert that AST into HTML. Both use a builder pattern for configuration.

    import org.commonmark.node.*;
    import org.commonmark.parser.Parser;
    import org.commonmark.renderer.html.HtmlRenderer;
    
    var parser = Parser.builder().build();
    var document = parser.parse("This is *Markdown*");
    var renderer = HtmlRenderer.builder().build();
    renderer.render(document);  // "<p>This is <em>Markdown</em></p>\n"
  7. Render AST to Markdown

    main

    You can render an existing AST back into Markdown text using MarkdownRenderer.

    import org.commonmark.node.*;
    import org.commonmark.renderer.markdown.MarkdownRenderer;
    
    // Build document
    var heading = new Heading();
    heading.setLevel(2);
    heading.appendChild(new Text("My heading"));
    var document = new Document();
    document.appendChild(heading);
    
    // Render to Markdown
    var renderer = MarkdownRenderer.builder().build();
    renderer.render(document);  // "## My heading\n"
  8. Customize HTML rendering with NodeRenderer

    main

    For complete control over how specific nodes are rendered, implement the NodeRenderer interface and register it via nodeRendererFactory on the HtmlRenderer.Builder.

    Parser 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("Example:\n\n    code");
    renderer.render(document);
    // "<p>Example:</p>\n<pre>code\n</pre>\n"
    
    class IndentedCodeBlockNodeRenderer implements NodeRenderer {
        private final HtmlWriter html;
    
        IndentedCodeBlockNodeRenderer(HtmlNodeRendererContext context) {
            this.html = context.getWriter();
        }
    
        @Override
        public Set<Class<? extends Node>> getNodeTypes() {
            return Set.of(IndentedCodeBlock.class);
        }
    
        @Override
        public void render(Node node) {
            IndentedCodeBlock codeBlock = (IndentedCodeBlock) node;
            html.line();
            html.tag("pre");
            html.text(codeBlock.getLiteral());
            html.tag("/pre");
            html.line();
        }
    }
  9. Process nodes using a Visitor

    main

    After parsing, you can traverse the AST using a visitor by extending AbstractVisitor and overriding the visit methods for specific node types.

    Node node = parser.parse("Example\n=======\n\nSome more text");
    WordCountVisitor visitor = new WordCountVisitor();
    node.accept(visitor);
    visitor.wordCount;  // 4
    
    class WordCountVisitor extends AbstractVisitor {
        int wordCount = 0;
    
        @Override
        public void visit(Text text) {
            // Count words
            wordCount += text.getLiteral().split("\\W+").length;
    
            // Descend into children
            visitChildren(text);
        }
    }