From 5efe42583ac4dcea75e5f709c2237b1965e2d6d8 Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Sat, 14 Mar 2026 18:50:47 -0400 Subject: [PATCH] fix: dismiss stepper on script edit and improve function brace tracking Stepper now auto-dismisses when the user edits the script body during detection, preventing stale matchedLine replacements. Function-level param() block detection uses brace depth counting instead of simple equality check, correctly handling nested braces in function bodies. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../script-editor/ScriptTemplateEditor.tsx | 10 ++++++++ frontend/src/lib/scriptParameterDetector.ts | 24 +++++++++++++------ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/script-editor/ScriptTemplateEditor.tsx b/frontend/src/components/script-editor/ScriptTemplateEditor.tsx index 15154746..5020548b 100644 --- a/frontend/src/components/script-editor/ScriptTemplateEditor.tsx +++ b/frontend/src/components/script-editor/ScriptTemplateEditor.tsx @@ -67,6 +67,16 @@ export function ScriptTemplateEditor({ templateId, onBack, onSaved }: Props) { const { canShareScriptTemplate } = usePermissions() + // Dismiss stepper if user edits the script body during detection + const scriptBodyRef = form.script_body + useEffect(() => { + if (showStepper) { + setShowStepper(false) + setDetectedCandidates([]) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [scriptBodyRef]) + // Load categories + template detail (if editing) useEffect(() => { const load = async () => { diff --git a/frontend/src/lib/scriptParameterDetector.ts b/frontend/src/lib/scriptParameterDetector.ts index 5043a4fb..edca1f3f 100644 --- a/frontend/src/lib/scriptParameterDetector.ts +++ b/frontend/src/lib/scriptParameterDetector.ts @@ -127,19 +127,33 @@ function parseDefault(value: string | null, type: ScriptParameter['type']): stri */ function findScriptLevelParamBlock(script: string): { start: number; end: number } | null { const lines = script.split('\n') - let inFunction = false + let functionBraceDepth = 0 let paramStart = -1 let parenDepth = 0 for (let i = 0; i < lines.length; i++) { const trimmed = lines[i].trim() + // Track function blocks with brace depth to handle nested braces if (/^function\s+/i.test(trimmed)) { - inFunction = true + // Count braces on this line and subsequent lines + for (const ch of lines[i]) { + if (ch === '{') functionBraceDepth++ + if (ch === '}') functionBraceDepth-- + } continue } - if (!inFunction && /^param\s*\(/i.test(trimmed) && paramStart === -1) { + // Track braces while inside a function + if (functionBraceDepth > 0) { + for (const ch of lines[i]) { + if (ch === '{') functionBraceDepth++ + if (ch === '}') functionBraceDepth-- + } + continue + } + + if (functionBraceDepth === 0 && /^param\s*\(/i.test(trimmed) && paramStart === -1) { paramStart = i for (let j = i; j < lines.length; j++) { for (const ch of lines[j]) { @@ -151,10 +165,6 @@ function findScriptLevelParamBlock(script: string): { start: number; end: number } } } - - if (inFunction && trimmed === '}') { - inFunction = false - } } return null