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

Method _replaceRegexp

src/MagicString.ts:1317–1375  ·  view source on GitHub ↗

@internal

(searchValue: RegExp, replacement: string | ReplacementFunction)

Source from the content-addressed store, hash-verified

1315
1316 /** @internal */
1317 _replaceRegexp(searchValue: RegExp, replacement: string | ReplacementFunction): this {
1318 function getReplacement(match: RegExpMatchArray, str: string): string {
1319 if (typeof replacement === 'string') {
1320 return expandReplacement(
1321 replacement,
1322 match[0],
1323 match.index,
1324 str,
1325 match.slice(1),
1326 match.groups,
1327 )
1328 }
1329 else {
1330 // `String.prototype.replace` only passes the named-capture-groups object
1331 // when the pattern actually has named groups - passing an `undefined`
1332 // there unconditionally shifts the last argument a replacer sees
1333 return match.groups === undefined
1334 ? replacement(match[0], ...match.slice(1), match.index, str)
1335 : replacement(match[0], ...match.slice(1), match.index, str, match.groups)
1336 }
1337 }
1338 const replaceMatch = (match: RegExpMatchArray): void => {
1339 if (match.index == null)
1340 return
1341
1342 const replacement = getReplacement(match, this.original)
1343 if (replacement === match[0])
1344 return
1345
1346 if (match[0].length === 0) {
1347 // a zero-length match spans no characters, so there is no range to
1348 // overwrite - the replacement is an insertion at the matched position,
1349 // which is what `String.prototype.replace` does for an empty match
1350 this.appendRight(match.index, replacement)
1351 }
1352 else {
1353 this.overwrite(match.index, match.index + match[0].length, replacement)
1354 }
1355 }
1356
1357 if (searchValue.global) {
1358 // `String.prototype.replace` starts a global regexp from the beginning of
1359 // the string, so reset `lastIndex` - a regexp that has already been used
1360 // would otherwise resume from wherever it stopped and skip earlier matches.
1361 // `matchAll` also steps over a zero-length match, where `exec` in a loop
1362 // would keep rematching it at an unmoving `lastIndex` and never terminate.
1363 searchValue.lastIndex = 0
1364 for (const match of this.original.matchAll(searchValue)) {
1365 replaceMatch(match)
1366 }
1367 }
1368 else {
1369 const match = this.original.match(searchValue)
1370 if (match) {
1371 replaceMatch(match)
1372 }
1373 }
1374 return this

Callers 2

replaceMethod · 0.95
replaceAllMethod · 0.95

Calls 1

matchAllMethod · 0.80

Tested by

no test coverage detected