import { each, eachRight } from 'lodash'; const findMatches = (doc, searchValue) => { const allNodes = []; doc.descendants((node, pos) => { allNodes.push({ node, pos }); }); eachRight(allNodes, (node, index) => { if (node.node.type.name === 'footnote') { allNodes.splice(index + 1, node.node.childCount); } }); const results = []; const mergedTextNodes = []; let index = 0; allNodes.forEach((node, i) => { if (node.node.isText) { if (mergedTextNodes[index]) { mergedTextNodes[index] = { text: mergedTextNodes[index].text + node.node.text, pos: mergedTextNodes[index].pos, }; } else { mergedTextNodes[index] = { text: node.node.text, pos: node.pos, }; } } else { index += 1; } }); mergedTextNodes.forEach(({ text, pos }) => { const search = RegExp(searchValue, 'gui'); let m; // eslint-disable-next-line no-cond-assign while ((m = search.exec(text))) { if (m[0] === '') { break; } results.push({ from: pos + m.index, to: pos + m.index + m[0].length, }); } }); return results; }; const getMatchesByView = (views, searchValue, findAndReplacePlugin) => { let allResults = 0; eachRight(views, (singleView, viewId) => { const results = findMatches(singleView.state.doc, searchValue); allResults += results.length; findAndReplacePlugin.props.setResults(results); singleView.state.tr.setMeta('search', true); singleView.dispatch(singleView.state.tr); }); views.main.dispatch(views.main.state.tr); return allResults; }; export default { findMatches, getMatchesByView };