* Converts unescaped capturing groups `(...)` and named capturing groups * `(? ...)` into non-capturing groups `(?:...)`. `String.prototype.split()` * interleaves captured text (named or otherwise) into the result array, which * would surface delimiter text as spurious chunks. Lookarounds (`
(pattern: string)
| 25 | * `(?<=`, `(?<!`) and other `(?...)` constructs are left untouched. |
| 26 | */ |
| 27 | function toNonCapturing(pattern: string): string { |
| 28 | let result = '' |
| 29 | let inClass = false |
| 30 | for (let i = 0; i < pattern.length; i++) { |
| 31 | const c = pattern[i] |
| 32 | if (c === '\\' && i + 1 < pattern.length) { |
| 33 | result += c + pattern[i + 1] |
| 34 | i++ |
| 35 | continue |
| 36 | } |
| 37 | if (c === '[') inClass = true |
| 38 | else if (c === ']') inClass = false |
| 39 | if (!inClass && c === '(') { |
| 40 | if (pattern[i + 1] !== '?') { |
| 41 | result += '(?:' |
| 42 | continue |
| 43 | } |
| 44 | const namedMatch = pattern.slice(i).match(NAMED_GROUP_PREFIX) |
| 45 | if (namedMatch) { |
| 46 | result += '(?:' |
| 47 | i += namedMatch[0].length - 1 |
| 48 | continue |
| 49 | } |
| 50 | } |
| 51 | result += c |
| 52 | } |
| 53 | return result |
| 54 | } |
| 55 | |
| 56 | export class RegexChunker { |
| 57 | private readonly chunkSize: number |