UNPKG

rst2html

Version:

Convert reStructured Text to HTML

152 lines (122 loc) 5.49 kB
import restructured from 'restructured'; const rst2html = (rstSource, indent = 2) => { const parsedRST = restructured.parse(rstSource); return render_any(parsedRST, 0, 2) }; const render_any = (element, level = 0, indent = 2) => { switch (element.type) { case 'document': return render_document(element, level, indent); case 'section': return render_section(element, level, indent); case 'transition': return render_transition(element, level, indent); case 'paragraph': return render_paragraph(element, level, indent); case 'bullet_list': return render_bullet_list(element, level, indent); case 'enumerated_list': return render_enumerated_list(element, level, indent); case 'definition_list': return render_definition_list(element, level, indent); case 'list_item': return render_list_item(element, level, indent); case 'line': return render_line(element, level, indent); case 'line_block': return render_line_block(element, level, indent); case 'literal_block': return render_literal_block(element, level, indent); case 'block_quote': return render_block_quote(element, level, indent); case 'text': return render_text(element, level, indent); case 'emphasis': return render_emphasis(element, level, indent); case 'strong': return render_strong(element, level, indent); case 'literal': return render_literal(element, level, indent); default: return render_unknown(element, level, indent) } } const render_unknown = (element, level = 0, indent = 2) => { if ( element.children ) { return render_block_element('div', `rst-unknown rst-${element.type}`, element, level, indent) } else { return render_leaf_element('div', `rst-unknown rst-${element.type}`, element, level, indent) } } const render_document = (element, level = 0, indent = 2) => { return render_block_element('div', 'rst-document', element, level, indent) } const render_section = (element, level = 0, indent = 2) => { const indentString = ' '.repeat(level * indent); const title = render_title(element.depth, element.children[0], level + 1, indent); const children = element.children.slice(1).map(e => render_any(e, level + 1, indent)).join('\n') return `${indentString}<div class="rst-section">\n${title}${children}${indentString}</div>\n`; } const render_title = (depth, element, level = 0, indent = 2) => { const titleTag = `h${depth}`; const titleClassName = `rst-title-${depth}`; return render_block_element(titleTag, titleClassName, element, level, indent) } const render_transition = (element, level = 0, indent = 2) => { // TODO: implement transitions return render_unknown(element, level, indent) } const render_paragraph = (element, level = 0, indent = 2) => { return render_block_element('p', 'rst-paragraph', element, level, indent) } const render_bullet_list = (element, level = 0, indent = 2) => { return render_block_element('ul', 'rst-bullet-list', element, level, indent) } const render_enumerated_list = (element, level = 0, indent = 2) => { return render_block_element('ol', 'rst-enumerated-list', element, level, indent) } const render_definition_list = (element, level = 0, indent = 2) => { // TODO: implement definition lists return render_unknown(element, level, indent) } const render_list_item = (element, level = 0, indent = 2) => { return render_block_element('li', 'rst-list-item', element, level, indent) } const render_line = (element, level = 0, indent = 2) => { return render_block_element('div', 'rst-line', element, level, indent) } const render_line_block = (element, level = 0, indent = 2) => { return render_block_element('div', 'rst-line-block', element, level, indent) } const render_literal_block = (element, level = 0, indent = 2) => { return render_block_element('pre', 'rst-literal-block', element, level, indent) } const render_block_quote = (element, level = 0, indent = 2) => { return render_block_element('blockquote', 'rst-block-quote', element, level, indent) } const render_text = (element, level = 0, indent = 2) => { return render_leaf_element('span', 'rst-text', element, level, indent) } const render_emphasis = (element, level = 0, indent = 2) => { return render_inline_element('em', 'rst-emphasis', element, level, indent) } const render_strong = (element, level = 0, indent = 2) => { return render_inline_element('strong', 'rst-strong', element, level, indent) } const render_literal = (element, level = 0, indent = 2) => { return render_inline_element('tt', 'rst-literal', element, level, indent) } const render_leaf_element = (tag, className, element, level = 0, indent = 2) => { const indentString = ' '.repeat(level * indent); return `<${tag} class="${className}">${element.value.replace(/\n$/, "")}</${tag}>`; } const render_inline_element = (tag, className, element, level = 0, indent = 2) => { const children = element.children.map(e => render_any(e, level+1, indent)).join('') return `<${tag} class="${className}">${children}</${tag}>`; } const render_block_element = (tag, className, element, level = 0, indent = 2) => { const indentString = ' '.repeat(level * indent); const children = element.children.map(e => render_any(e, level+1, indent)).join('') return `${indentString}<${tag} class="${className}">\n${children}\n${indentString}</${tag}>\n`; } module.exports = rst2html;