UNPKG

react-lowlight

Version:

Super-thin React wrapper for lowlight (Syntax highlighting using VDOM)

90 lines (74 loc) 2.11 kB
const lineNumberify = (ast, lineNumber = 1) => { return ast.reduce(function (result, node) { if (node.type === 'text') { if (node.value.indexOf('\n') === -1) { node.lineNumber = lineNumber result.nodes.push(node) return result } const lines = node.value.split('\n') for (let i = 0; i < lines.length; i++) { result.nodes.push({ type: 'text', value: i === lines.length - 1 ? lines[i] : lines[i] + '\n', lineNumber: i === 0 ? lineNumber : ++lineNumber }) } result.lineNumber = lineNumber return result } if (node.children) { node.lineNumber = lineNumber const processed = lineNumberify(node.children, lineNumber) node.children = processed.nodes result.lineNumber = processed.lineNumber result.nodes.push(node) return result } result.nodes.push(node) return result }, { nodes: [], lineNumber }) } const wrapLines = function wrapLines (ast, markers, options) { let i = 0 const wrapped = markers.reduce(function (nodes, marker) { const line = marker.line const children = [] for (; i < ast.length; i++) { if (ast[i].lineNumber < line) { nodes.push(ast[i]) continue } if (ast[i].lineNumber === line) { children.push(ast[i]) continue } if (ast[i].lineNumber > line) { break } } nodes.push({ type: 'element', tagName: 'div', properties: { className: [marker.className || (options.prefix + 'marker')] }, children, lineNumber: line }) return nodes }, []) for (; i < ast.length; i++) { wrapped.push(ast[i]) } return wrapped } const addMarkers = (ast, options) => { const markers = options.markers.map((marker) => { return marker.line ? marker : { line: marker } }).sort((nodeA, nodeB) => { return nodeA.line - nodeB.line }) const numbered = lineNumberify(ast).nodes const wrapped = wrapLines(numbered, markers, options) return wrapped } export default addMarkers