1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-18 09:35:20 +02:00
joplin/packages/editor/CodeMirror/utils/formatting/findInlineMatch.ts

77 lines
1.9 KiB
TypeScript
Raw Normal View History

import { Text as DocumentText, SelectionRange } from '@codemirror/state';
import { RegionSpec } from './RegionSpec';
export enum MatchSide {
Start,
End,
}
// Returns the length of a match for this in the given selection,
// -1 if no match is found.
const findInlineMatch = (
doc: DocumentText, spec: RegionSpec, sel: SelectionRange, side: MatchSide,
): number => {
const [regex, template] = (() => {
if (side === MatchSide.Start) {
return [spec.matcher.start, spec.template.start];
} else {
return [spec.matcher.end, spec.template.end];
}
})();
const [startIndex, endIndex] = (() => {
if (!sel.empty) {
return [sel.from, sel.to];
}
const bufferSize = template.length;
if (side === MatchSide.Start) {
return [sel.from - bufferSize, sel.to];
} else {
return [sel.from, sel.to + bufferSize];
}
})();
const searchText = doc.sliceString(startIndex, endIndex);
// Returns true if [idx] is in the right place (the match is at
// the end of the string or the beginning based on startIndex/endIndex).
const indexSatisfies = (idx: number, len: number): boolean => {
idx += startIndex;
if (side === MatchSide.Start) {
return idx === startIndex;
} else {
return idx + len === endIndex;
}
};
if (!regex.global) {
throw new Error('Regular expressions used by RegionSpec must have the global flag! This flag is required to find multiple matches.');
}
// Search from the beginning.
regex.lastIndex = 0;
let foundMatch: RegExpMatchArray|null = null;
let match: RegExpMatchArray|null;
while ((match = regex.exec(searchText)) !== null) {
if (indexSatisfies(match.index ?? -1, match[0].length)) {
foundMatch = match;
break;
}
}
if (foundMatch) {
const matchLength = foundMatch[0].length;
const matchIndex = foundMatch.index;
// If the match isn't in the right place,
if (indexSatisfies(matchIndex, matchLength)) {
return matchLength;
}
}
return -1;
};
export default findInlineMatch;