From d3520a8945f7725205fa173558287b38185a4c01 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Mon, 6 Apr 2026 21:34:04 +0300 Subject: [PATCH] fix(skd-edit): modify-parameter availableValue parsing and formatting bugs Fix 3 bugs in modify-parameter: (1) first availableValue rendered as raw text when combined with other kv pairs in same batch entry, (2) presentation values with spaces truncated by \S+ regex, (3) denyIncompleteValues/use inserted without line breaks. Root cause: if/else on rest.startsWith missed availableValue when preceded by other keys. Also fix namespace-aware element lookup using LocalName/local_name instead of SelectSingleNode. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/skills/skd-edit/scripts/skd-edit.ps1 | 103 +++++++++--------- .claude/skills/skd-edit/scripts/skd-edit.py | 61 +++++++---- .../skd-edit/modify-parameter-combined.json | 22 ++++ .../modify-parameter-combined/Template.xml | 85 +++++++++++++++ .../snapshots/modify-parameter/Template.xml | 8 +- 5 files changed, 198 insertions(+), 81 deletions(-) create mode 100644 tests/skills/cases/skd-edit/modify-parameter-combined.json create mode 100644 tests/skills/cases/skd-edit/snapshots/modify-parameter-combined/Template.xml diff --git a/.claude/skills/skd-edit/scripts/skd-edit.ps1 b/.claude/skills/skd-edit/scripts/skd-edit.ps1 index 05dacc58..ba1bd8c6 100644 --- a/.claude/skills/skd-edit/scripts/skd-edit.ps1 +++ b/.claude/skills/skd-edit/scripts/skd-edit.ps1 @@ -1,4 +1,4 @@ -# skd-edit v1.5 — Atomic 1C DCS editor +# skd-edit v1.6 — Atomic 1C DCS editor # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -1707,10 +1707,50 @@ switch ($Operation) { $childIndent = Get-ChildIndent $paramEl - # Parse key=value pairs (special handling for availableValue) - if ($rest -match '^availableValue=(.+)') { - $avRest = $rest -replace '^availableValue=', '' - # Parse: "Перечисление...X presentation=текст" + # Separate availableValue=... from simple kv pairs + $simpleRest = $rest + $avPart = $null + $avIdx = $rest.IndexOf('availableValue=') + if ($avIdx -ge 0) { + $simpleRest = $rest.Substring(0, $avIdx).Trim() + $avPart = $rest.Substring($avIdx) + } + + # Process simple key=value pairs (use, denyIncompleteValues, etc.) + if ($simpleRest) { + $kvPairs = [regex]::Matches($simpleRest, '(\w+)=(\S+)') + foreach ($kv in $kvPairs) { + $key = $kv.Groups[1].Value + $value = $kv.Groups[2].Value + + $existing = $paramEl.SelectSingleNode($key) + if ($existing) { + $existing.InnerText = $value + Write-Host "[OK] Parameter `"$paramName`": $key updated to $value" + } else { + # Schema order: ...value, useRestriction, availableValue*, denyIncompleteValues, use + $refNode = $null + if ($key -eq "denyIncompleteValues") { + foreach ($child in $paramEl.ChildNodes) { + if ($child.NodeType -eq 'Element' -and $child.LocalName -eq 'use') { + $refNode = $child; break + } + } + } + $fragXml = "$childIndent<$key>$(Esc-Xml $value)" + $nodes = Import-Fragment $xmlDoc $fragXml + foreach ($node in $nodes) { + Insert-BeforeElement $paramEl $node $refNode $childIndent + } + Write-Host "[OK] Parameter `"$paramName`": $key=$value added" + } + } + } + + # Process availableValue + if ($avPart) { + $avRest = $avPart -replace '^availableValue=', '' + # Parse: "Перечисление...X presentation=текст с пробелами" $avParts = $avRest -split '\s+presentation=', 2 $avValue = $avParts[0].Trim() $avPresentation = if ($avParts.Count -gt 1) { $avParts[1].Trim() } else { "" } @@ -1735,61 +1775,18 @@ switch ($Operation) { $avLines += "$childIndent" $fragXml = $avLines -join "`r`n" - # Insert before denyIncompleteValues/use or at end + # Insert before first of (denyIncompleteValues, use) in document order $refNode = $null - foreach ($tag in @("denyIncompleteValues","use")) { - $found = $paramEl.SelectSingleNode($tag) - if ($found) { $refNode = $found; break } + foreach ($child in $paramEl.ChildNodes) { + if ($child.NodeType -eq 'Element' -and ($child.LocalName -eq 'denyIncompleteValues' -or $child.LocalName -eq 'use')) { + $refNode = $child; break + } } $nodes = Import-Fragment $xmlDoc $fragXml foreach ($node in $nodes) { Insert-BeforeElement $paramEl $node $refNode $childIndent } Write-Host "[OK] Parameter `"$paramName`": availableValue added" - } else { - # Simple key=value pairs: use=Always, denyIncompleteValues=true - $kvPairs = [regex]::Matches($rest, '(\w+)=(\S+)') - foreach ($kv in $kvPairs) { - $key = $kv.Groups[1].Value - $value = $kv.Groups[2].Value - - $existing = $paramEl.SelectSingleNode($key) - if ($existing) { - $existing.InnerText = $value - Write-Host "[OK] Parameter `"$paramName`": $key updated to $value" - } else { - # Determine insertion order - $afterTags = switch ($key) { - "denyIncompleteValues" { @("availableValue","useRestriction","availableAsField","expression","value","valueType","title","name") } - "use" { @("denyIncompleteValues","availableValue","useRestriction","availableAsField","expression","value","valueType","title","name") } - default { @("name") } - } - $refNode = $null - foreach ($tag in @("denyIncompleteValues","use")) { - if ($tag -eq $key) { continue } - $found = $paramEl.SelectSingleNode($tag) - if ($found -and ($afterTags -contains $tag -eq $false)) { - $refNode = $found; break - } - } - - $fragXml = "$childIndent<$key>$(Esc-Xml $value)" - $nodes = Import-Fragment $xmlDoc $fragXml - foreach ($node in $nodes) { - # Append before closing tag (last whitespace child) - $lastChild = $paramEl.LastChild - if ($lastChild.NodeType -eq 'Whitespace' -or $lastChild.NodeType -eq 'SignificantWhitespace') { - $paramEl.InsertBefore($node, $lastChild) | Out-Null - } else { - $paramEl.AppendChild($node) | Out-Null - } - } - # Add trailing whitespace - $ws = $xmlDoc.CreateWhitespace("`r`n$($childIndent -replace '`t$','')") - $paramEl.AppendChild($ws) | Out-Null - Write-Host "[OK] Parameter `"$paramName`": $key=$value added" - } - } } } } diff --git a/.claude/skills/skd-edit/scripts/skd-edit.py b/.claude/skills/skd-edit/scripts/skd-edit.py index 4172dc1e..b833b7ba 100644 --- a/.claude/skills/skd-edit/scripts/skd-edit.py +++ b/.claude/skills/skd-edit/scripts/skd-edit.py @@ -1,4 +1,4 @@ -# skd-edit v1.5 — Atomic 1C DCS editor (Python port) +# skd-edit v1.6 — Atomic 1C DCS editor (Python port) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os @@ -1481,9 +1481,38 @@ elif operation == "modify-parameter": child_indent = get_child_indent(param_el) - if rest.startswith("availableValue="): - av_rest = rest[len("availableValue="):] - av_parts = av_rest.split(" presentation=", 1) + # Separate availableValue=... from simple kv pairs + simple_rest = rest + av_part = None + av_idx = rest.find("availableValue=") + if av_idx >= 0: + simple_rest = rest[:av_idx].strip() + av_part = rest[av_idx:] + + # Process simple key=value pairs (use, denyIncompleteValues, etc.) + if simple_rest: + for m in re.finditer(r'(\w+)=(\S+)', simple_rest): + key, value = m.group(1), m.group(2) + existing = next((ch for ch in param_el if isinstance(ch.tag, str) and local_name(ch) == key), None) + if existing is not None: + existing.text = value + print(f'[OK] Parameter "{param_name}": {key} updated to {value}') + else: + # Schema order: ...value, useRestriction, availableValue*, denyIncompleteValues, use + ref_node = None + if key == "denyIncompleteValues": + ref_node = next((ch for ch in param_el if isinstance(ch.tag, str) and local_name(ch) == "use"), None) + frag_xml = f"{child_indent}<{key}>{esc_xml(value)}" + nodes = import_fragment(xml_doc, frag_xml) + for node in nodes: + insert_before_element(param_el, node, ref_node, child_indent) + print(f'[OK] Parameter "{param_name}": {key}={value} added') + + # Process availableValue + if av_part: + av_rest = av_part[len("availableValue="):] + # Parse: "Перечисление...X presentation=текст с пробелами" + av_parts = re.split(r'\s+presentation=', av_rest, 1) av_value = av_parts[0].strip() av_presentation = av_parts[1].strip() if len(av_parts) > 1 else "" @@ -1503,32 +1532,16 @@ elif operation == "modify-parameter": av_lines.append(f"{child_indent}") frag_xml = "\r\n".join(av_lines) + # Insert before first of (denyIncompleteValues, use) in document order ref_node = None - for tag in ["denyIncompleteValues", "use"]: - found = param_el.find(tag) - if found is not None: - ref_node = found + for child in param_el: + if isinstance(child.tag, str) and local_name(child) in ("denyIncompleteValues", "use"): + ref_node = child break nodes = import_fragment(xml_doc, frag_xml) for node in nodes: insert_before_element(param_el, node, ref_node, child_indent) print(f'[OK] Parameter "{param_name}": availableValue added') - else: - for m in re.finditer(r'(\w+)=(\S+)', rest): - key, value = m.group(1), m.group(2) - existing = param_el.find(key) - if existing is not None: - existing.text = value - print(f'[OK] Parameter "{param_name}": {key} updated to {value}') - else: - frag_xml = f"{child_indent}<{key}>{esc_xml(value)}" - nodes = import_fragment(xml_doc, frag_xml) - for node in nodes: - last_child = list(param_el)[-1] if len(param_el) else None - if last_child is not None: - last_child.tail = (last_child.tail or "") + "\r\n" + child_indent - param_el.append(node) - print(f'[OK] Parameter "{param_name}": {key}={value} added') elif operation == "add-filter": settings = resolve_variant_settings() diff --git a/tests/skills/cases/skd-edit/modify-parameter-combined.json b/tests/skills/cases/skd-edit/modify-parameter-combined.json new file mode 100644 index 00000000..3d393da6 --- /dev/null +++ b/tests/skills/cases/skd-edit/modify-parameter-combined.json @@ -0,0 +1,22 @@ +{ + "name": "modify-parameter: combined kv + availableValue in single entry", + "preRun": [ + { + "script": "skd-compile/scripts/skd-compile", + "input": { + "dataSets": [{ + "name": "Основной", + "query": "ВЫБРАТЬ Т.Сумма ИЗ Регистр КАК Т", + "fields": ["Сумма: decimal(15,2)"] + }], + "parameters": [{"name": "ПорядокОкругления", "type": "string", "value": "Окр1_00"}] + }, + "args": { "-DefinitionFile": "{inputFile}", "-OutputPath": "{workDir}/Template.xml" } + } + ], + "params": { + "templatePath": "Template.xml", + "operation": "modify-parameter", + "value": "ПорядокОкругления denyIncompleteValues=true use=Always availableValue=Перечисление.Округления.Окр1_00 presentation=руб. коп ;; ПорядокОкругления availableValue=Перечисление.Округления.Окр1 presentation=руб. ;; ПорядокОкругления availableValue=Перечисление.Округления.Окр1000 presentation=тыс. руб" + } +} diff --git a/tests/skills/cases/skd-edit/snapshots/modify-parameter-combined/Template.xml b/tests/skills/cases/skd-edit/snapshots/modify-parameter-combined/Template.xml new file mode 100644 index 00000000..2e531531 --- /dev/null +++ b/tests/skills/cases/skd-edit/snapshots/modify-parameter-combined/Template.xml @@ -0,0 +1,85 @@ + + + + ИсточникДанных1 + Local + + + Основной + + Сумма + Сумма + + xs:decimal + + 15 + 2 + Any + + + + ИсточникДанных1 + ВЫБРАТЬ Т.Сумма ИЗ Регистр КАК Т + + + ПорядокОкругления + + xs:string + + 0 + Variable + + + Окр1_00 + + Перечисление.Округления.Окр1_00 + + + ru + руб. коп + + + + + Перечисление.Округления.Окр1 + + + ru + руб. + + + + + Перечисление.Округления.Окр1000 + + + ru + тыс. руб + + + + true + Always + + + Основной + + + ru + Основной + + + + + + + + + + + + + + + + diff --git a/tests/skills/cases/skd-edit/snapshots/modify-parameter/Template.xml b/tests/skills/cases/skd-edit/snapshots/modify-parameter/Template.xml index a2fde25a..35c109ee 100644 --- a/tests/skills/cases/skd-edit/snapshots/modify-parameter/Template.xml +++ b/tests/skills/cases/skd-edit/snapshots/modify-parameter/Template.xml @@ -30,9 +30,7 @@ Variable - Окр1_00Always - true - + Окр1_00 Перечисление.Округления.Окр1_00 @@ -51,7 +49,9 @@ - + true + Always + Основной