mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-30 10:36:35 +02:00
77 lines
1.9 KiB
TypeScript
77 lines
1.9 KiB
TypeScript
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;
|
|
|