UNPKG

@augment-vir/common

Version:

A collection of augments, helpers types, functions, and classes for any JavaScript environment.

48 lines (47 loc) 2.46 kB
import { addRegExpFlags, setRegExpCaseSensitivity } from '@augment-vir/core'; /** * Finds all indexes of a `searchFor` string or RegExp in `searchIn`. Ths is similar to * [`''.indexOf`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf) * except that it finds _all_ indexes of. * * @category String * @category Package : @augment-vir/common * @package [`@augment-vir/common`](https://www.npmjs.com/package/@augment-vir/common) */ export function findSubstringIndexes({ searchIn, searchFor, caseSensitive, includeLength, }) { const searchRegExp = addRegExpFlags(setRegExpCaseSensitivity(searchFor, { caseSensitive }), 'g'); const indexes = []; const indexesAndLengths = []; searchIn.replace(searchRegExp, (...matchResults) => { /** * Grabbing the second to last entry in the array (rather than the second) takes capture * groups into account. */ const matchIndex = matchResults[matchResults.length - 2]; // this is used as a type safety catch and cannot actually be triggered on purpose /* node:coverage ignore next 5 */ if (typeof matchIndex !== 'number') { throw new TypeError(`Match index "${matchIndex}" is not a number. Searching for "${searchFor}" in "${searchIn}".`); } const regExpMatch = matchResults[0]; // this is used as a type safety catch and cannot actually be triggered on purpose /* node:coverage ignore next 5 */ if (typeof regExpMatch !== 'string') { throw new TypeError(`regExpMatch should've been a string but was ${typeof regExpMatch}!`); } indexesAndLengths.push({ index: matchIndex, length: regExpMatch.length }); indexes.push(matchIndex); const originalMatch = matchResults[0]; // this is used as a type safety catch and cannot actually be triggered on purpose /* node:coverage ignore next 5 */ if (typeof originalMatch !== 'string') { throw new TypeError(`Original match when searching for "${searchFor}" in "${searchIn}" at index ${matchIndex} is not a string.`); } /** * Don't actually change any text. What we do here doesn't matter because we're not * using the output of the .replace method, we're just producing side effects. */ return originalMatch; }); return (includeLength ? indexesAndLengths : indexes); }