commonmark.js
commonmark.js copied to clipboard
Consider a JSONRenderer
I'd love to see a "JSONRenderer" which would be equivalent to the HTML renderer's output, except in a form like this:
{
tagName: "h1",
children: "whatever",
attributes: {}
}
Effectively, what I'm hoping for is something that would match (or be similar to) the vdom type currently being implemented in Jupyter frontends.
Example input:
## Try CommonMark
You can try CommonMark here. This dingus is powered by
[commonmark.js](https://github.com/jgm/commonmark.js), the
JavaScript reference implementation.
1. item one
2. item two
- sublist
- sublist
Example output (click to expand me):
{
"attributes": {
"attributes": {},
"children": [
{
"attributes": {},
"children": "Try CommonMark",
"tagName": "h2"
},
{
"attributes": {},
"children": [
"You can try CommonMark here. This dingus is powered by",
{
"attributes": { "href": "https://github.com/jgm/commonmark.js" },
"children": "commonmark.js",
"tagName": "a"
},
", the\nJavaScript reference implementation."
],
"tagName": "p"
},
{
"attributes": {},
"children": [
{ "attributes": {}, "children": "item one", "tagName": "li" },
{ "attributes": {}, "children": "item two", "tagName": "li" },
{
"attributes": {},
"children": [
{
"attributes": {},
"children": "sublist",
"tagName": "li"
},
{ "attributes": {}, "children": "sublist", "tagName": "li" }
],
"tagName": "ul"
}
],
"tagName": "ol"
}
]
},
"children": [
{
"attributes": {},
"children": "Try CommonMark",
"tagName": "h2"
},
{
"attributes": {},
"children": [
"You can try CommonMark here. This dingus is powered by",
{
"attributes": { "href": "https://github.com/jgm/commonmark.js" },
"children": "commonmark.js",
"tagName": "a"
},
", the\nJavaScript reference implementation."
],
"tagName": "p"
},
{
"attributes": {},
"children": [
{ "attributes": {}, "children": "item one", "tagName": "li" },
{ "attributes": {}, "children": "item two", "tagName": "li" },
{
"attributes": {},
"children": [
{ "attributes": {}, "children": "sublist", "tagName": "li" },
{ "attributes": {}, "children": "sublist", "tagName": "li" }
],
"tagName": "ul"
}
],
"tagName": "ol"
}
],
"tagName": "div"
}
Hello @rgbkrk
I have achieved something like this using an HTML parser on the HtmlRenderer output:
(using https://github.com/fb55/htmlparser2)
import htmlparser from 'htmlparser2'
import commonmark from 'commonmark'
const simplified = (domObject) => {
if (domObject.type === 'text') return domObject.data.trim()
return {
tagName: domObject.name,
children: domObject.children.map(domChild => simplified(domChild)).filter(child => child),
attributes: domObject.attribs,
}
}
export const markdownToJSON = (markdown) => {
const reader = new commonmark.Parser()
const parsed = reader.parse(markdown)
const writer = new commonmark.HtmlRenderer()
const html = writer.render(parsed)
const dom = htmlparser.parseDOM(html)
return dom.map(domObject => simplified(domObject)).filter(element => element)
}
which for your input produces
[
{
"tag": "h2",
"attributes": {},
"children": [
"Try CommonMark"
]
},
{
"tag": "p",
"attributes": {},
"children": [
"You can try CommonMark here. This dingus is powered by",
{
"attributes": {
"href": "https:\/\/github.com\/jgm\/commonmark.js"
},
"tag": "a",
"children": [
"commonmark.js"
]
},
", the\nJavaScript reference implementation."
]
},
{
"tag": "ol",
"attributes": {},
"children": [
{
"tag": "li",
"attributes": {},
"children": [
"item one"
]
},
{
"tag": "li",
"attributes": {},
"children": [
"item two",
{
"tag": "ul",
"attributes": {},
"children": [
{
"tag": "li",
"attributes": {},
"children": [
"sublist"
]
},
{
"tag": "li",
"attributes": {},
"children": [
"sublist"
]
}
]
}
]
}
]
}
]