UNPKG

very-small-parser

Version:

A very small Markdown, HTML, and CSS parser.

161 lines (160 loc) 6.08 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.toHast = void 0; const toHast_1 = require("../inline/toHast"); const toTextChildrenInline = ({ children }) => { const res = []; if (!children) return res; const length = children.length; for (let i = 0; i < length; i++) res.push((0, toHast_1.toHast)(children[i])); return res; }; const toHastChildren = ({ children }) => { const arr = []; if (!children) return arr; const length = children.length; for (let i = 0; i < length; i++) arr.push((0, exports.toHast)(children[i])); return arr; }; const toHastChildrenSkipSingleParagraph = (node) => { const { children } = node; if (children?.length === 1 && children[0].type === 'paragraph') return toTextChildrenInline(children[0]); return toHastChildren(node); }; 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, block, properties, children = toHastChildren(block)) => el(tagName, properties, children); const text = (value) => ({ type: 'text', value }); const toHast = (node) => { if (Array.isArray(node)) return { type: 'root', children: toHastChildren({ children: node }) }; const block = node; switch (block.type) { case 'paragraph': return element('p', block, void 0, toTextChildrenInline(block)); case 'code': { const lang = block.lang || 'text'; const attr = { class: 'language-' + lang, 'data-lang': lang, 'data-meta': block.meta || '', }; return element('pre', block, attr, [element('code', block, { ...attr }, [text(block.value)])]); } case 'heading': return element('h' + block.depth, block, void 0, toTextChildrenInline(block)); case 'blockquote': { let attr = void 0; if (block.spoiler) attr = { 'data-spoiler': 'true' }; return element('blockquote', block, attr, toHastChildren(block)); } case 'list': { const children = block.children; const length = children.length; const items = []; for (let i = 0; i < length; i++) { const item = children[i]; const itemAttr = {}; const checked = item.checked; if (typeof checked === 'boolean') itemAttr['data-checked'] = checked + ''; items.push(element('li', item, itemAttr, toHastChildrenSkipSingleParagraph(item))); } const attr = {}; let tag = 'ul'; if (block.ordered) { tag = 'ol'; attr.start = (block.start ?? 1) + ''; } const list = element(tag, block, attr, items); return list; } case 'thematicBreak': return el('hr'); case 'table': { const { align, children } = block; const rowLength = children.length; const columnLength = align.length; const headerRow = children[0]; const headerRowCells = []; const header = el('thead', void 0, [el('tr', void 0, headerRowCells)]); if (headerRow) { const headerCells = headerRow.children; for (let j = 0; j < columnLength; j++) { const alignment = align[j]; const cellAttr = alignment ? { align: alignment } : void 0; headerRowCells.push(el('th', cellAttr, toTextChildrenInline(headerCells[j]))); } } const bodyRows = []; const body = el('tbody', void 0, bodyRows); for (let i = 1; i < rowLength; i++) { const row = children[i]; const rowChildren = row.children; const tds = []; for (let j = 0; j < columnLength; j++) { const cell = rowChildren[j]; const alignment = align[j]; const cellAttr = alignment ? { align: alignment } : void 0; tds.push(el('td', cellAttr, toTextChildrenInline(cell))); } bodyRows.push(el('tr', void 0, tds)); } const attr = { 'data-align': JSON.stringify(align), }; return el('table', attr, [header, body]); } case 'definition': { const { label, url, title, identifier: id } = block; const attr = { 'data-node': 'definition', 'data-label': label, 'data-id': id, 'data-title': title || '', 'data-url': url, }; return el('div', attr, [ el('a', { name: id, id }, [text(block.label)]), text(': '), el('a', { href: url, title: title || url }, [text(title || url)]), ]); } case 'footnoteDefinition': { const id = block.identifier; const attr = { 'data-node': 'footnoteDefinition', 'data-label': block.label, 'data-id': id, }; return el('div', attr, [el('a', { name: id, id }, [text(block.label)]), ...toHastChildren(block)]); } case 'math': { const attr = { 'data-math': 'true', }; return element('pre', block, attr, [element('code', block, { ...attr }, [text(block.value)])]); } case 'element': return block; case '': return element('br', block); } return { ...node, type: 'root', children: toHastChildren(block) }; }; exports.toHast = toHast;