UNPKG

react-markdown

Version:
95 lines (79 loc) 2.23 kB
"use strict"; /** * Naive, simple plugin to match inline nodes without attributes * This allows say <strong>foo</strong>, but not <strong class="very">foo</strong> * For proper HTML support, you'll want a different plugin **/ var visit = require('unist-util-visit'); var type = 'virtualHtml'; var selfClosingRe = /^<(area|base|br|col|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)\s*\/?>$/i; var simpleTagRe = /^<(\/?)([a-z]+)\s*>$/; module.exports = function (tree) { var open; var currentParent; visit(tree, 'html', function (node, index, parent) { if (currentParent !== parent) { open = []; currentParent = parent; } var selfClosing = getSelfClosing(node); if (selfClosing) { parent.children.splice(index, 1, { type: type, tag: selfClosing, position: node.position }); return true; } var current = getSimpleTag(node, parent); if (!current) { return true; } var matching = findAndPull(open, current.tag); if (matching) { parent.children.splice(index, 0, virtual(current, matching, parent)); } else if (!current.opening) { open.push(current); } return true; }, true // Iterate in reverse ); return tree; }; function findAndPull(open, matchingTag) { var i = open.length; while (i--) { if (open[i].tag === matchingTag) { return open.splice(i, 1)[0]; } } return false; } function getSimpleTag(node, parent) { var match = node.value.match(simpleTagRe); return match ? { tag: match[2], opening: !match[1], node: node } : false; } function getSelfClosing(node) { var match = node.value.match(selfClosingRe); return match ? match[1] : false; } function virtual(fromNode, toNode, parent) { var fromIndex = parent.children.indexOf(fromNode.node); var toIndex = parent.children.indexOf(toNode.node); var extracted = parent.children.splice(fromIndex, toIndex - fromIndex + 1); var children = extracted.slice(1, -1); return { type: type, children: children, tag: fromNode.tag, position: { start: fromNode.node.position.start, end: toNode.node.position.end, indent: [] } }; }