From d8d2903670c704494aabef1a9fbd5f54b1c90971 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 14:04:26 +0000 Subject: [PATCH] perf: optimize referencedTitles text matching in workspace Replaces regex matchAll with manual indexOf scanning for parsing references, significantly improving text scanning performance. Uses sticky regex fallback for bare identifiers. Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com> --- src/workspace.ts | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/workspace.ts b/src/workspace.ts index bc768b8..3669def 100644 --- a/src/workspace.ts +++ b/src/workspace.ts @@ -19,6 +19,7 @@ interface SheetExports { } const XREF_SCAN_RE = /@(?:\[([^\]]+)\]|([\p{L}_][\p{L}\d_]*))\./gu; +const XREF_BARE_RE_STICKY = /@([\p{L}_][\p{L}\d_]*)\./guy; function escapeRegExp(s: string): string { return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); @@ -104,7 +105,28 @@ export class Workspace { if (cached && cached.text === text) return cached.refs; } const out: string[] = []; - for (const m of text.matchAll(XREF_SCAN_RE)) out.push((m[1] ?? m[2]).trim()); + let i = 0; + while ((i = text.indexOf("@", i)) !== -1) { + if (i + 1 >= text.length) break; + + if (text[i + 1] === "[") { + const endBracket = text.indexOf("]", i + 2); + if (endBracket !== -1 && endBracket + 1 < text.length && text[endBracket + 1] === ".") { + out.push(text.substring(i + 2, endBracket).trim()); + i = endBracket + 2; + continue; + } + } else { + XREF_BARE_RE_STICKY.lastIndex = i; + const m = XREF_BARE_RE_STICKY.exec(text); + if (m !== null) { + out.push(m[1]); // no trim needed for bare identifier regex match + i = XREF_BARE_RE_STICKY.lastIndex; + continue; + } + } + i++; + } if (id) { this.parsedRefsCache.set(id, { text, refs: out }); }