How to render HTML to Markdown?

Using Commonmark java how to render html to markdown? I tried this example, but it is not rendering.

@Slf4j
class MarkdownTest {
    @Test
    void markdownTest() {
        String markdown = toMarkdown("<b> Hello World!</b>");
        log.info("markdown ==> {}", markdown);
    }

    String toMarkdown(String html) {
        Node htmlDocument = Parser.builder().build().parse(html);
        return MarkdownRenderer.builder().build().render(htmlDocument);
    }
}

Output:

markdown ==> <b> Hello World!</b>

1 Like

commonmark-java doesn’t include an HTML parser. The only thing the parser accepts is Markdown.

To achieve what you want to do, you would first need to use an HTML parser (e.g. jsoup), then convert the parsed elements to a tree of Node objects in commonmark-java, then render it using the MarkdownRenderer.

Shouldn’t Pandoc do this? pandoc -f html -t commonmark most likely.

If it has to stay on the JVM: commonmark-java won’t, as robinst says, but flexmark-java ships an html2md converter module that goes HTML to Markdown directly. Probably less work than hand-rolling a jsoup to Node mapping.

For what it’s worth I take a third route: I import HTML into Carve and export Markdown from there. The point isn’t that it produces better Markdown, it’s that the intermediate can hold structure Markdown has no syntax for, so Markdown becomes one output among several rather than the only representation I keep.

Concretely, this HTML:

<dl>
  <dt>Portability</dt>
  <dd>How much survives a format change.</dd>
</dl>
<table>
  <caption>Results</caption>
  <thead><tr><th>Engine</th><th colspan="2">Timing</th></tr></thead>
  <tbody><tr><td>carve-js</td><td>12ms</td><td>ok</td></tr></tbody>
</table>

imports to this:

:: Portability
: How much survives a format change.

| Engine | Timing | < |
|---|---|---|
| carve-js | 12ms | ok |
^ Results

which fully roundtrips back to HTML if needed.

And the Markdown export then reduces whatever Markdown cannot express:

**Portability**
: How much survives a format change.

| Engine | Timing |  |
| --- | --- | --- |
| carve-js | 12ms | ok |

Results

The definition list, the table caption and the colspan all survive the first hop. The second hop flattens the caption to a paragraph, drops the column span, and falls back to raw HTML for things like abbr, sup and mark. That is Markdown’s limitation rather than the converter’s, which is exactly why I keep the intermediate.

So: if Markdown is the final target, Pandoc is the simpler answer. If it is one target among several, an intermediate that can outlive the conversion is worth having.