94 lines
2.3 KiB
JavaScript
94 lines
2.3 KiB
JavaScript
const MAX = 4294967295;
|
|
class JavaScriptScanner {
|
|
constructor(patterns, options = {}) {
|
|
this.patterns = patterns;
|
|
this.options = options;
|
|
const {
|
|
forgiving = false,
|
|
cache,
|
|
regexConstructor
|
|
} = options;
|
|
if (!regexConstructor) {
|
|
throw new Error("Option `regexConstructor` is not provided");
|
|
}
|
|
this.regexps = patterns.map((p) => {
|
|
if (typeof p !== "string") {
|
|
return p;
|
|
}
|
|
const cached = cache?.get(p);
|
|
if (cached) {
|
|
if (cached instanceof RegExp) {
|
|
return cached;
|
|
}
|
|
if (forgiving)
|
|
return null;
|
|
throw cached;
|
|
}
|
|
try {
|
|
const regex = regexConstructor(p);
|
|
cache?.set(p, regex);
|
|
return regex;
|
|
} catch (e) {
|
|
cache?.set(p, e);
|
|
if (forgiving)
|
|
return null;
|
|
throw e;
|
|
}
|
|
});
|
|
}
|
|
regexps;
|
|
findNextMatchSync(string, startPosition, _options) {
|
|
const str = typeof string === "string" ? string : string.content;
|
|
const pending = [];
|
|
function toResult(index, match, offset = 0) {
|
|
return {
|
|
index,
|
|
captureIndices: match.indices.map((indice) => {
|
|
if (indice == null) {
|
|
return {
|
|
start: MAX,
|
|
end: MAX,
|
|
length: 0
|
|
};
|
|
}
|
|
return {
|
|
start: indice[0] + offset,
|
|
end: indice[1] + offset,
|
|
length: indice[1] - indice[0]
|
|
};
|
|
})
|
|
};
|
|
}
|
|
for (let i = 0; i < this.regexps.length; i++) {
|
|
const regexp = this.regexps[i];
|
|
if (!regexp)
|
|
continue;
|
|
try {
|
|
regexp.lastIndex = startPosition;
|
|
const match = regexp.exec(str);
|
|
if (!match)
|
|
continue;
|
|
if (match.index === startPosition) {
|
|
return toResult(i, match, 0);
|
|
}
|
|
pending.push([i, match, 0]);
|
|
} catch (e) {
|
|
if (this.options.forgiving)
|
|
continue;
|
|
throw e;
|
|
}
|
|
}
|
|
if (pending.length) {
|
|
const minIndex = Math.min(...pending.map((m) => m[1].index));
|
|
for (const [i, match, offset] of pending) {
|
|
if (match.index === minIndex) {
|
|
return toResult(i, match, offset);
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export { JavaScriptScanner as J };
|