UNPKG

very-small-parser

Version:

A very small Markdown, HTML, and CSS parser.

101 lines (100 loc) 3.61 kB
const toHastChildren = ({ children }) => { const arr = []; if (!children) return arr; const length = children.length; for (let i = 0; i < length; i++) arr.push(toHast(children[i])); return arr; }; const text = (value) => ({ type: 'text', value }); const el = (tagName, properties, children) => { const node = { type: 'element', tagName, }; if (properties) node.properties = properties; if (children) node.children = children; return node; }; const element = (tagName, inline, properties, children = toHastChildren(inline)) => el(tagName, properties, children); const elementWithText = (tagName, inline, text, properties) => element(tagName, inline, properties, [{ type: 'text', value: text }]); const anchor = (identifier, children, properties = {}) => { properties.href = '#' + identifier; const node = { type: 'element', tagName: 'a', properties, children, }; return node; }; export const toHast = (node) => { const inline = node; switch (inline.type) { case 'text': return inline; case 'inlineCode': return elementWithText('code', inline, inline.value); case 'strong': return element('strong', inline); case 'emphasis': return element('em', inline); case 'delete': return element('del', inline); case 'spoiler': return element('spoiler', inline, { style: 'background:black;color:black' }); case 'inlineMath': return elementWithText('code', inline, inline.value || '', { class: 'language-math', 'data-lang': 'math' }); case 'footnoteReference': return el('sup', { 'data-node': 'footnote' }, [anchor(inline.identifier, [text(inline.label)])]); case 'linkReference': return anchor(inline.identifier, toHastChildren(inline)); case 'imageReference': { const { identifier, alt } = inline; return anchor(identifier, [text(alt || identifier)], { 'data-ref': 'img' }); } case 'link': { const { title, url } = inline; const attr = { href: url }; if (title) attr.title = title; return element('a', inline, attr); } case 'image': { const { title, url, alt } = inline; const attr = { src: url }; if (title) attr.title = title; if (alt) attr.alt = alt; return element('img', inline, attr); } case 'inlineLink': return elementWithText('a', inline, inline.value, { href: inline.value }); case 'sup': return element('sup', inline); case 'sub': return element('sub', inline); case 'mark': return element('mark', inline); case 'handle': return elementWithText('cite', inline, inline.prefix + inline.value); case 'underline': return element('u', inline); case 'break': return element('br', inline); case 'icon': return elementWithText('acronym', inline, ':' + inline.emoji + ':', { title: inline.emoji + ' icon', 'data-icon': inline.emoji, }); case 'element': return inline; case 'whitespace': return { type: 'text', value: ' '.repeat(inline.length) }; } return { ...node, type: 'root', children: toHastChildren(inline) }; };