commonmark.js icon indicating copy to clipboard operation
commonmark.js copied to clipboard

Consider a JSONRenderer

Open rgbkrk opened this issue 6 years ago • 1 comments

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"
}

rgbkrk avatar Nov 01 '17 20:11 rgbkrk

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"
                ]
              }
            ]
          }
        ]
      }
    ]
  }
]

christianchown avatar Nov 03 '17 18:11 christianchown