Files
cinny/src/app/utils/findAndReplace.ts
T

32 lines
1.2 KiB
TypeScript
Raw Normal View History

2023-10-30 16:58:47 +11:00
export type ReplaceCallback<R> = (
match: RegExpExecArray | RegExpMatchArray,
pushIndex: number,
2023-10-30 16:58:47 +11:00
) => R;
export type ConvertPartCallback<R> = (text: string, pushIndex: number) => R;
export const findAndReplace = <ReplaceReturnType, ConvertReturnType>(
text: string,
regex: RegExp,
replace: ReplaceCallback<ReplaceReturnType>,
convertPart: ConvertPartCallback<ConvertReturnType>,
2023-10-30 16:58:47 +11:00
): Array<ReplaceReturnType | ConvertReturnType> => {
const result: Array<ReplaceReturnType | ConvertReturnType> = [];
let lastEnd = 0;
let match: RegExpExecArray | RegExpMatchArray | null = regex.exec(text);
while (match !== null && typeof match.index === 'number') {
result.push(convertPart(text.slice(lastEnd, match.index), result.length));
result.push(replace(match, result.length));
lastEnd = match.index + match[0].length;
// A non-global regex always returns the same first match from exec() (its
// lastIndex never advances), so re-running it would loop forever. Treat a
// non-global regex as a single match and stop after processing it.
match = regex.global ? regex.exec(text) : null;
2023-10-30 16:58:47 +11:00
}
result.push(convertPart(text.slice(lastEnd), result.length));
return result;
};