( content: string, sedInfo: SedEditInfo, )
| 242 | * Returns the new content after applying the substitution |
| 243 | */ |
| 244 | export function applySedSubstitution( |
| 245 | content: string, |
| 246 | sedInfo: SedEditInfo, |
| 247 | ): string { |
| 248 | // Convert sed pattern to JavaScript regex |
| 249 | let regexFlags = '' |
| 250 | |
| 251 | // Handle global flag |
| 252 | if (sedInfo.flags.includes('g')) { |
| 253 | regexFlags += 'g' |
| 254 | } |
| 255 | |
| 256 | // Handle case-insensitive flag (i or I in sed) |
| 257 | if (sedInfo.flags.includes('i') || sedInfo.flags.includes('I')) { |
| 258 | regexFlags += 'i' |
| 259 | } |
| 260 | |
| 261 | // Handle multiline flag (m or M in sed) |
| 262 | if (sedInfo.flags.includes('m') || sedInfo.flags.includes('M')) { |
| 263 | regexFlags += 'm' |
| 264 | } |
| 265 | |
| 266 | // Convert sed pattern to JavaScript regex pattern |
| 267 | let jsPattern = sedInfo.pattern |
| 268 | // Unescape \/ to / |
| 269 | .replace(/\\\//g, '/') |
| 270 | |
| 271 | // In BRE mode (no -E flag), metacharacters have opposite escaping: |
| 272 | // BRE: \+ means "one or more", + is literal |
| 273 | // ERE/JS: + means "one or more", \+ is literal |
| 274 | // We need to convert BRE escaping to ERE for JavaScript regex |
| 275 | if (!sedInfo.extendedRegex) { |
| 276 | jsPattern = jsPattern |
| 277 | // Step 1: Protect literal backslashes (\\) first - in both BRE and ERE, \\ is literal backslash |
| 278 | .replace(/\\\\/g, BACKSLASH_PLACEHOLDER) |
| 279 | // Step 2: Replace escaped metacharacters with placeholders (these should become unescaped in JS) |
| 280 | .replace(/\\\+/g, PLUS_PLACEHOLDER) |
| 281 | .replace(/\\\?/g, QUESTION_PLACEHOLDER) |
| 282 | .replace(/\\\|/g, PIPE_PLACEHOLDER) |
| 283 | .replace(/\\\(/g, LPAREN_PLACEHOLDER) |
| 284 | .replace(/\\\)/g, RPAREN_PLACEHOLDER) |
| 285 | // Step 3: Escape unescaped metacharacters (these are literal in BRE) |
| 286 | .replace(/\+/g, '\\+') |
| 287 | .replace(/\?/g, '\\?') |
| 288 | .replace(/\|/g, '\\|') |
| 289 | .replace(/\(/g, '\\(') |
| 290 | .replace(/\)/g, '\\)') |
| 291 | // Step 4: Replace placeholders with their JS equivalents |
| 292 | .replace(BACKSLASH_PLACEHOLDER_RE, '\\\\') |
| 293 | .replace(PLUS_PLACEHOLDER_RE, '+') |
| 294 | .replace(QUESTION_PLACEHOLDER_RE, '?') |
| 295 | .replace(PIPE_PLACEHOLDER_RE, '|') |
| 296 | .replace(LPAREN_PLACEHOLDER_RE, '(') |
| 297 | .replace(RPAREN_PLACEHOLDER_RE, ')') |
| 298 | } |
| 299 | |
| 300 | // Unescape sed-specific escapes in replacement |
| 301 | // Convert \n to newline, & to $& (match), etc. |
no test coverage detected