String.prototype.replaceAll

by AntowaKartowa

TypeScript

interface ReplacerFunc {
  (substrMatch: string, submatches: string[], offset: number, string: string): string
}

interface StrReplaceAll {
  (pattern: string | RegExp, replacer: string | ReplacerFunc): string;
}

export const strReplaceAll: StrReplaceAll = function (pattern, replacer) {
  if (typeof pattern === 'string') pattern = new RegExp(pattern, 'g');
  // const resultArr = [...string];
  // const matchArr = [...string.matchAll(pattern)];
  const resultArr = [...this as string];
  const matchArr = [...(this as string).matchAll(pattern)];
  let i = matchArr.length;

  while (i--) {
    const match = matchArr[i];
    const currentMatches = [];
    let currentReplacer = replacer;

    for (let j = 0; j < match.length; j++) {
      if (typeof currentReplacer === 'function') {
        if (j > 0) currentMatches.push(match[j]);

        continue;
      }

      if (!currentReplacer.includes(`$${j}`)) continue;

      currentReplacer = (currentReplacer as string).replace(`$${j}`, match[j]);
    }

    if (typeof currentReplacer === 'string') {
      resultArr.splice(match.index, match[0].length, currentReplacer);
    } else {
      resultArr.splice(match.index, match[0].length, currentReplacer(match[0], currentMatches, match.index, this));
    }
  }

  return resultArr.join('');
};


// const firstReplace = strReplaceAll(string, /([A-Z])+/g, ' $1');
// const secondReplace = strReplaceAll(firstReplace, /_([a-z]+)/g, ' ($1)');
// const thirdReplace = strReplaceAll(secondReplace, /^\w?/g, str => str.toUpperCase());

// console.log(string);
// console.log(firstReplace);
// console.log(secondReplace);
// console.log(thirdReplace);

if (!String.prototype?.replaceAll) {
  Object.defineProperty(
    String.prototype,
    'replaceAll',
    {
      enumerable: false,
      configurable: false,
      writable: false,
      value: strReplaceAll,
    },
  );
}

console.log('premiumLinkLabel_gdpr');
console.log('premiumLinkLabel_gdpr'.replaceAll(/([A-Z])+/g, '...