From 2e5b3352a3ab82e4d6fa249f3c74fb8a1f8fad04 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Thu, 1 May 2025 16:49:02 -0300 Subject: data, replacer: withContentNodes, splitContentNodesAround --- src/replacer.js | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) (limited to 'src/replacer.js') diff --git a/src/replacer.js b/src/replacer.js index 8abbbd6b..8574bf0c 100644 --- a/src/replacer.js +++ b/src/replacer.js @@ -871,3 +871,79 @@ export function parseInput(input) { ].join('\n')); } } + +export function* splitContentNodesAround(nodes, splitter) { + if (splitter instanceof RegExp) { + const regex = splitter; + + splitter = function*(text) { + for (const match of text.matchAll(regex)) { + yield { + index: match.index, + length: match[0].length, + }; + } + }; + } + + if (typeof splitter === 'string') { + throw new TypeError(`Expected generator or regular expression`); + } + + function* splitTextNode(node) { + let textNode = { + i: node.i, + iEnd: null, + type: 'text', + data: '', + }; + + let parseFrom = 0; + for (const match of splitter(node.data)) { + const {index, length} = match; + + textNode.data += node.data.slice(parseFrom, index); + + if (textNode.data) { + textNode.iEnd = textNode.i + textNode.data.length; + yield textNode; + } + + yield { + i: node.i + index, + iEnd: node.i + index + length, + type: 'separator', + data: { + text: node.data.slice(index, index + length), + match, + }, + }; + + textNode = { + i: node.i + index + length, + iEnd: null, + type: 'text', + data: '', + }; + + parseFrom = index + length; + } + + if (parseFrom !== node.data.length) { + textNode.data += node.data.slice(parseFrom); + textNode.iEnd = node.iEnd; + } + + if (textNode.data) { + yield textNode; + } + } + + for (const node of nodes) { + if (node.type === 'text') { + yield* splitTextNode(node); + } else { + yield node; + } + } +} -- cgit 1.3.0-6-gf8a5