Skip to content

Commit e65bb1d

Browse files
aalemayhuclaude
andcommitted
refactor(docs): replace callout regex with line-based scanner
Sonar S5852 flagged /^:::(note|tip|warning)\s*\n([\s\S]*?)\n:::/gm as super-linear-runtime-by-backtracking. The lazy quantifier with a clear terminator isn't actually catastrophic, and markdown bodies are build-time-bundled (no user input), so this isn't reachable as DoS. But removing the regex entirely is cheaper than arguing. The replacement walks lines, finds open/close markers, and emits the same <aside> output. No quantifiers, obviously linear. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 52be369 commit e65bb1d

1 file changed

Lines changed: 40 additions & 6 deletions

File tree

web/src/pages/DocsPage/DocContent.tsx

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,19 +65,53 @@ function DocsAnchor({ href, children, ...rest }: AnchorProps) {
6565
);
6666
}
6767

68-
const CALLOUT_PATTERN = /^:::(note|tip|warning)\s*\n([\s\S]*?)\n:::/gm;
6968
const CALLOUT_VARIANT_CLASS: Record<CalloutVariant, string> = {
7069
note: 'callout-note',
7170
tip: 'callout-tip',
7271
warning: 'callout-warning',
7372
};
7473

74+
function parseCalloutOpen(line: string): CalloutVariant | null {
75+
if (!line.startsWith(':::')) return null;
76+
const rest = line.slice(3).trim();
77+
return Object.hasOwn(CALLOUT_VARIANT_CLASS, rest)
78+
? (rest as CalloutVariant)
79+
: null;
80+
}
81+
82+
function isCalloutClose(line: string): boolean {
83+
return line.trim() === ':::';
84+
}
85+
7586
function transformCallouts(body: string): string {
76-
return body.replace(
77-
CALLOUT_PATTERN,
78-
(_match, variant: string, inner: string) =>
79-
`<aside class="callout ${CALLOUT_VARIANT_CLASS[variant as CalloutVariant]}">\n\n${inner.trim()}\n\n</aside>`,
80-
);
87+
const lines = body.split('\n');
88+
const out: string[] = [];
89+
let i = 0;
90+
while (i < lines.length) {
91+
const variant = parseCalloutOpen(lines[i]);
92+
if (variant == null) {
93+
out.push(lines[i]);
94+
i++;
95+
continue;
96+
}
97+
let close = i + 1;
98+
while (close < lines.length && !isCalloutClose(lines[close])) close++;
99+
if (close >= lines.length) {
100+
out.push(lines[i]);
101+
i++;
102+
continue;
103+
}
104+
const inner = lines.slice(i + 1, close).join('\n').trim();
105+
out.push(
106+
`<aside class="callout ${CALLOUT_VARIANT_CLASS[variant]}">`,
107+
'',
108+
inner,
109+
'',
110+
'</aside>',
111+
);
112+
i = close + 1;
113+
}
114+
return out.join('\n');
81115
}
82116

83117
const markdownComponents: Components = {

0 commit comments

Comments
 (0)