* Creates an extended regular expression object for matching text with a pattern. Differs from a * native regular expression in that additional syntax and flags are supported. The returned object * is in fact a native `RegExp` and works with all native methods. * * @class XRegExp * @constructor
(pattern, flags)
| 548 | * XRegExp(/regex/); |
| 549 | */ |
| 550 | function XRegExp(pattern, flags) { |
| 551 | if (XRegExp.isRegExp(pattern)) { |
| 552 | if (flags !== undefined) { |
| 553 | throw new TypeError('Cannot supply flags when copying a RegExp'); |
| 554 | } |
| 555 | return copyRegex(pattern); |
| 556 | } |
| 557 | |
| 558 | // Copy the argument behavior of `RegExp` |
| 559 | pattern = pattern === undefined ? '' : String(pattern); |
| 560 | flags = flags === undefined ? '' : String(flags); |
| 561 | |
| 562 | if (XRegExp.isInstalled('astral') && !flags.includes('A')) { |
| 563 | // This causes an error to be thrown if the Unicode Base addon is not available |
| 564 | flags += 'A'; |
| 565 | } |
| 566 | |
| 567 | if (!patternCache[pattern]) { |
| 568 | patternCache[pattern] = {}; |
| 569 | } |
| 570 | |
| 571 | if (!patternCache[pattern][flags]) { |
| 572 | const context = { |
| 573 | hasNamedCapture: false, |
| 574 | captureNames: [] |
| 575 | }; |
| 576 | let scope = defaultScope; |
| 577 | let output = ''; |
| 578 | let pos = 0; |
| 579 | let result; |
| 580 | |
| 581 | // Check for flag-related errors, and strip/apply flags in a leading mode modifier |
| 582 | const applied = prepareFlags(pattern, flags); |
| 583 | let appliedPattern = applied.pattern; |
| 584 | const appliedFlags = applied.flags; |
| 585 | |
| 586 | // Use XRegExp's tokens to translate the pattern to a native regex pattern. |
| 587 | // `appliedPattern.length` may change on each iteration if tokens use `reparse` |
| 588 | while (pos < appliedPattern.length) { |
| 589 | do { |
| 590 | // Check for custom tokens at the current position |
| 591 | result = runTokens(appliedPattern, appliedFlags, pos, scope, context); |
| 592 | // If the matched token used the `reparse` option, splice its output into the |
| 593 | // pattern before running tokens again at the same position |
| 594 | if (result && result.reparse) { |
| 595 | appliedPattern = appliedPattern.slice(0, pos) + |
| 596 | result.output + |
| 597 | appliedPattern.slice(pos + result.matchLength); |
| 598 | } |
| 599 | } while (result && result.reparse); |
| 600 | |
| 601 | if (result) { |
| 602 | output += result.output; |
| 603 | pos += (result.matchLength || 1); |
| 604 | } else { |
| 605 | // Get the native token at the current position |
| 606 | const [token] = XRegExp.exec(appliedPattern, nativeTokens[scope], pos, 'sticky'); |
| 607 | output += token; |
no test coverage detected
searching dependent graphs…