* Applies a transformation function only to the non-code regions of markdown content. * Skips both fenced code blocks (``` / ~~~ delimited) and inline code spans (backtick * delimited) so that the transformation is not applied to code content. * * Falls back to applying fn to the entire string i
(s, fn)
| 543 | * @returns {string} The content with the transformation applied only outside code regions |
| 544 | */ |
| 545 | function applyToNonCodeRegions(s, fn) { |
| 546 | if (!s || typeof s !== "string") { |
| 547 | return s || ""; |
| 548 | } |
| 549 | |
| 550 | try { |
| 551 | const codeRanges = getFencedCodeRanges(s); |
| 552 | |
| 553 | if (codeRanges.length === 0) { |
| 554 | // No fenced code blocks – still protect inline code spans |
| 555 | return applyFnOutsideInlineCode(s, fn); |
| 556 | } |
| 557 | |
| 558 | const parts = []; |
| 559 | let pos = 0; |
| 560 | |
| 561 | for (const [start, end] of codeRanges) { |
| 562 | if (pos < start) { |
| 563 | // Non-code text before this code block: protect inline code spans |
| 564 | parts.push(applyFnOutsideInlineCode(s.slice(pos, start), fn)); |
| 565 | } |
| 566 | // Fenced code block: preserve verbatim |
| 567 | parts.push(s.slice(start, end)); |
| 568 | pos = end; |
| 569 | } |
| 570 | |
| 571 | // Non-code text after the last code block |
| 572 | if (pos < s.length) { |
| 573 | parts.push(applyFnOutsideInlineCode(s.slice(pos), fn)); |
| 574 | } |
| 575 | |
| 576 | return parts.join(""); |
| 577 | } catch (_e) { |
| 578 | // Fallback: apply fn to the entire string (conservative – redacts more, never less) |
| 579 | return fn(s); |
| 580 | } |
| 581 | } |
| 582 | |
| 583 | /** |
| 584 | * Removes XML comments from content |
no test coverage detected