-
Notifications
You must be signed in to change notification settings - Fork 5
/
util.js
81 lines (68 loc) · 2.21 KB
/
util.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
const assert = require('node:assert');
const {fuzzysearchSlice} = require('./fuzzysearch/fuzzysearch.js');
// Why is doing everything in JS so difficult?! Maybe I should write python...
exports.regexEscape = (string) => {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
};
exports.regexEscapeReplacement = (string) => {
return string.replace(/\$/g, '$$$$');
};
exports.countSubstring = (string, substring) => {
const matches = string.match(new RegExp(exports.regexEscape(substring), 'g'));
return (matches || []).length;
};
exports.replaceOnce = (string, src, dst) => {
return string.replace(
new RegExp(exports.regexEscape(src)),
exports.regexEscapeReplacement(dst));
};
exports.expandHTMLs = (basenode, direction, condition) => {
let result = basenode.outerHTML;
let addresult;
if (direction === 'next') {
addresult = (html) => {
result += html;
};
} else if (direction === 'previous') {
addresult = (html) => {
result = html + result;
};
} else {
assert(false);
}
const endNode = basenode[`${direction}ElementSibling`];
if (endNode && condition(endNode)) {
let nextNode = basenode;
while (nextNode !== endNode) {
nextNode = nextNode[`${direction}Sibling`];
if (nextNode.outerHTML !== undefined) {
addresult(nextNode.outerHTML);
} else {
const wrap = basenode.ownerDocument.createElement('div');
wrap.appendChild(nextNode.cloneNode(true));
addresult(wrap.innerHTML);
}
}
}
return result;
};
exports.makeRegexForLine = (string) => {
// eslint-disable-next-line max-len
return `(?:(?:(?<=\n)|^)[ \t]*)?${exports.regexEscape(string)}([ \t]*(?:\n|\r\n))?`;
};
exports.findWithFixup = async (haystack, needle, state) => {
if (exports.countSubstring(haystack, needle) === 1) {
// Simple case
return needle;
} else if (state.data && needle === state.data[0] &&
exports.countSubstring(haystack, state.data[1]) === 1) {
// Use cached fixup
return state.data[1];
} else {
// Fuzzy search this
const fixup = await fuzzysearchSlice(haystack, needle);
assert(exports.countSubstring(haystack, fixup) === 1);
state.data = [needle, fixup];
return fixup;
}
};