diff options
author | (quasar) nebula <qznebula@protonmail.com> | 2025-05-01 16:49:02 -0300 |
---|---|---|
committer | (quasar) nebula <qznebula@protonmail.com> | 2025-05-06 12:29:06 -0300 |
commit | 2e5b3352a3ab82e4d6fa249f3c74fb8a1f8fad04 (patch) | |
tree | cde0493e1771c160a1531416b2172810a480ff5a /src/replacer.js | |
parent | 301f1466b9d0e2e04d5bed6b948cae6683d61224 (diff) |
data, replacer: withContentNodes, splitContentNodesAround
Diffstat (limited to 'src/replacer.js')
-rw-r--r-- | src/replacer.js | 76 |
1 files changed, 76 insertions, 0 deletions
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; + } + } +} |