fix: param block detection with nested parens + cursor alignment

The paren depth counter started at 0 and immediately matched before
any '(' was counted, causing param blocks to be detected as ending
on line 0. Added foundOpen flag to require at least one '(' before
checking for balanced depth.

For cursor alignment: switch both textarea and overlay to whitespace-pre
with wrap=off, use explicit 21px line-height (14px * 1.5), and strip
all default pre element margins/padding/borders.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-03-14 19:34:45 -04:00
parent 099a4a2b4e
commit e5899d81c4
2 changed files with 6 additions and 4 deletions

View File

@@ -37,7 +37,7 @@ export function ScriptBodyEditor({ value, onChange, disabled }: Props) {
<div className="relative rounded-xl border border-border overflow-hidden">
{/* Highlighted overlay (read-only visual layer) — scroll synced to textarea */}
<div ref={overlayRef} className="absolute inset-0 pointer-events-none overflow-hidden p-4">
<PowerShellHighlighter script={value || ' '} className="font-label text-sm leading-[1.5] whitespace-pre-wrap break-words m-0" />
<PowerShellHighlighter script={value || ' '} className="font-label text-sm leading-[21px] whitespace-pre m-0 p-0 border-0" />
</div>
{/* Editable textarea (transparent text, visible caret) */}
@@ -48,8 +48,9 @@ export function ScriptBodyEditor({ value, onChange, disabled }: Props) {
onScroll={handleScroll}
onKeyDown={handleTab}
disabled={disabled}
wrap="off"
spellCheck={false}
className="relative z-10 w-full min-h-[300px] resize-y font-label text-sm leading-[1.5] bg-transparent text-transparent caret-foreground p-4 whitespace-pre-wrap break-words focus:outline-none focus:ring-1 focus:ring-[rgba(6,182,212,0.2)] disabled:cursor-not-allowed disabled:opacity-50"
className="relative z-10 w-full min-h-[300px] resize-y font-label text-sm leading-[21px] bg-transparent text-transparent caret-foreground p-4 whitespace-pre overflow-auto focus:outline-none focus:ring-1 focus:ring-[rgba(6,182,212,0.2)] disabled:cursor-not-allowed disabled:opacity-50"
placeholder="# Enter your PowerShell script here…&#10;# Use {{ param_name }} for parameter placeholders"
/>
</div>

View File

@@ -155,11 +155,12 @@ function findScriptLevelParamBlock(script: string): { start: number; end: number
if (functionBraceDepth === 0 && /^param\s*\(/i.test(trimmed) && paramStart === -1) {
paramStart = i
let foundOpen = false
for (let j = i; j < lines.length; j++) {
for (const ch of lines[j]) {
if (ch === '(') parenDepth++
if (ch === '(') { parenDepth++; foundOpen = true }
if (ch === ')') parenDepth--
if (parenDepth === 0 && paramStart !== -1) {
if (foundOpen && parenDepth === 0) {
return { start: paramStart, end: j }
}
}