MCPcopy Create free account
hub / github.com/Rich-Harris/magic-string / _replaceRegexp

Method _replaceRegexp

src/MagicString.ts:1450–1522  ·  view source on GitHub ↗

@internal

(searchValue: RegExp, replacement: string | ReplacementFunction)

Source from the content-addressed store, hash-verified

1448
1449 /** @internal */
1450 _replaceRegexp(searchValue: RegExp, replacement: string | ReplacementFunction): this {
1451 function getReplacement(match: RegExpMatchArray, str: string): string {
1452 if (typeof replacement === 'string') {
1453 return expandReplacement(
1454 replacement,
1455 match[0],
1456 match.index,
1457 str,
1458 match.slice(1),
1459 match.groups,
1460 )
1461 }
1462 else {
1463 // `String.prototype.replace` only passes the named-capture-groups object
1464 // when the pattern actually has named groups - passing an `undefined`
1465 // there unconditionally shifts the last argument a replacer sees
1466 return match.groups === undefined
1467 ? replacement(match[0], ...match.slice(1), match.index, str)
1468 : replacement(match[0], ...match.slice(1), match.index, str, match.groups)
1469 }
1470 }
1471 // Returns true once a surviving match has been handled, so a non-global
1472 // search can stop at the first match still present in the output.
1473 const replaceMatch = (match: RegExpMatchArray): boolean => {
1474 /* v8 ignore next 2 -- `match.index` is always defined for matches from `matchAll` */
1475 if (match.index == null)
1476 return false
1477
1478 if (this._hasRemovedContent(match.index, match.index + match[0].length))
1479 return false
1480
1481 const replacement = getReplacement(match, this.original)
1482 if (replacement === match[0])
1483 return true
1484
1485 if (match[0].length === 0) {
1486 // a zero-length match spans no characters, so there is no range to
1487 // overwrite - the replacement is an insertion at the matched position,
1488 // which is what `String.prototype.replace` does for an empty match
1489 this.appendRight(match.index, replacement)
1490 }
1491 else {
1492 this.overwrite(match.index, match.index + match[0].length, replacement)
1493 }
1494 return true
1495 }
1496
1497 if (searchValue.global) {
1498 // `String.prototype.replace` starts a global regexp from the beginning of
1499 // the string, so reset `lastIndex` - a regexp that has already been used
1500 // would otherwise resume from wherever it stopped and skip earlier matches.
1501 // `matchAll` also steps over a zero-length match, where `exec` in a loop
1502 // would keep rematching it at an unmoving `lastIndex` and never terminate.
1503 searchValue.lastIndex = 0
1504 for (const match of this.original.matchAll(searchValue)) {
1505 replaceMatch(match)
1506 }
1507 }

Callers 2

replaceMethod · 0.95
replaceAllMethod · 0.95

Calls 1

matchAllMethod · 0.80

Tested by

no test coverage detected