From 9130c6ee6cacf79795f2dbc35ceada5cadd428fb Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Fri, 4 Sep 2026 14:32:37 -0700 Subject: [PATCH] perf(editor): build the closing-fence pattern once per fence, not once per line (#18629) markdownFenceRanges recompiled the closing-fence RegExp for every line inside an open code fence, though it only depends on the fence's own marker and length. A 100k-line fenced block went from 16.6ms to 5.8ms. --- .../src/components/editor/details-markdown-html.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/renderer/src/components/editor/details-markdown-html.ts b/src/renderer/src/components/editor/details-markdown-html.ts index 109005460dc..964c08f35d6 100644 --- a/src/renderer/src/components/editor/details-markdown-html.ts +++ b/src/renderer/src/components/editor/details-markdown-html.ts @@ -94,7 +94,7 @@ export function renderDetailsAttributes(attrs: Record | undefin function markdownFenceRanges(content: string): MarkdownFenceRanges { const ranges: [number, number][] = [] let offset = 0 - let openFence: { marker: '`' | '~'; length: number; start: number } | null = null + let openFence: { closingPattern: RegExp; start: number } | null = null for (const lineMatch of content.matchAll(/[^\r\n]*(?:\r\n|\n|\r|$)/g)) { const line = lineMatch[0] @@ -104,11 +104,8 @@ function markdownFenceRanges(content: string): MarkdownFenceRanges { const lineText = line.replace(/(?:\r\n|\n|\r)$/u, '') if (openFence) { - const closingFencePattern = - openFence.marker === '`' - ? new RegExp(`^ {0,3}\`{${openFence.length},}\\s*$`) - : new RegExp(`^ {0,3}~{${openFence.length},}\\s*$`) - if (closingFencePattern.test(lineText)) { + // Built once per fence: rebuilding it per line recompiled the same regex for every fenced line. + if (openFence.closingPattern.test(lineText)) { ranges.push([openFence.start, offset + line.length]) openFence = null } @@ -116,8 +113,9 @@ function markdownFenceRanges(content: string): MarkdownFenceRanges { const openingFenceMatch = lineText.match(/^ {0,3}(`{3,}|~{3,})/u) if (openingFenceMatch?.[1]) { openFence = { - marker: openingFenceMatch[1][0] as '`' | '~', - length: openingFenceMatch[1].length, + closingPattern: new RegExp( + `^ {0,3}${openingFenceMatch[1][0]}{${openingFenceMatch[1].length},}\\s*$` + ), start: offset } }