diff --git a/src/renderer/src/components/browser-pane/browser-annotation-output.test.ts b/src/renderer/src/components/browser-pane/browser-annotation-output.test.ts index 71c530a69f9..25a84d74dad 100644 --- a/src/renderer/src/components/browser-pane/browser-annotation-output.test.ts +++ b/src/renderer/src/components/browser-pane/browser-annotation-output.test.ts @@ -110,6 +110,26 @@ describe('formatBrowserAnnotationsAsMarkdown', () => { expect(markdown).toContain('**Classes:** `` primary `generated` ``') }) + it('formats page snippets with many backtick runs', () => { + const annotation = makeAnnotation() + const manyBacktickRuns = Array.from({ length: 130_000 }, () => '`').join(' ') + + expect(() => + formatBrowserAnnotationsAsMarkdown([ + makeAnnotation({ + payload: { + ...annotation.payload, + target: { + ...annotation.payload.target, + selector: `button[data-label="${manyBacktickRuns}"]`, + htmlSnippet: `` + } + } + }) + ]) + ).not.toThrow() + }) + it('collapses page-controlled newlines before putting text in headings and lists', () => { const annotation = makeAnnotation() const markdown = formatBrowserAnnotationsAsMarkdown([ diff --git a/src/renderer/src/components/browser-pane/browser-annotation-output.ts b/src/renderer/src/components/browser-pane/browser-annotation-output.ts index d81bd3c5560..594251fa712 100644 --- a/src/renderer/src/components/browser-pane/browser-annotation-output.ts +++ b/src/renderer/src/components/browser-pane/browser-annotation-output.ts @@ -66,14 +66,24 @@ function formatStyles(styles: BrowserGrabComputedStyles): string[] { return lines } +// Why: annotation snippets come from page DOM; avoid spreading every backtick +// run into Math.max when generated HTML contains many fence characters. +function maxBacktickRunLength(content: string, floor: number): number { + let maxRun = floor + for (const match of content.matchAll(/`+/g)) { + maxRun = Math.max(maxRun, match[0].length) + } + return maxRun +} + function fence(language: string, content: string): string[] { - const maxRun = Math.max(3, ...Array.from(content.matchAll(/`+/g), (match) => match[0].length)) + const maxRun = maxBacktickRunLength(content, 3) const marker = '`'.repeat(maxRun + 1) return [`${marker}${language}`, content, marker] } function inlineCode(content: string): string { - const maxRun = Math.max(0, ...Array.from(content.matchAll(/`+/g), (match) => match[0].length)) + const maxRun = maxBacktickRunLength(content, 0) const marker = '`'.repeat(maxRun + 1) const padding = content.startsWith('`') || content.endsWith('`') ? ' ' : '' return `${marker}${padding}${content}${padding}${marker}`