diff --git a/.claude/skills/skd-compile/scripts/skd-compile.ps1 b/.claude/skills/skd-compile/scripts/skd-compile.ps1 index 863af634..9aa3814d 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.ps1 +++ b/.claude/skills/skd-compile/scripts/skd-compile.ps1 @@ -1,4 +1,4 @@ -# skd-compile v1.67 — Compile 1C DCS from JSON +# skd-compile v1.68 — Compile 1C DCS from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, @@ -2356,23 +2356,29 @@ function Emit-OutputParameters { foreach ($prop in $params.PSObject.Properties) { $key = $prop.Name $rawVal = $prop.Value - # Распознаём wrapper {value, use?, viewMode?, userSettingID?, userSettingPresentation?} + # Распознаём wrapper {value, valueType?, use?, items?, viewMode?, userSettingID?, userSettingPresentation?} # отличая от multilang dict ({ru, en, ...}). Wrapper всегда имеет ключ 'value'. $useFalse = $false $wrapVM = $null $wrapUSID = $null $wrapUSP = $null + $wrapVT = $null + $wrapItems = $null $hasValueKey = $false if ($rawVal -is [PSCustomObject] -and $rawVal.PSObject.Properties['value']) { $hasValueKey = $true + if ($rawVal.PSObject.Properties['valueType']) { $wrapVT = "$($rawVal.valueType)" } if ($rawVal.PSObject.Properties['use'] -and $rawVal.use -eq $false) { $useFalse = $true } + if ($rawVal.PSObject.Properties['items']) { $wrapItems = $rawVal.items } if ($rawVal.PSObject.Properties['viewMode']) { $wrapVM = "$($rawVal.viewMode)" } if ($rawVal.PSObject.Properties['userSettingID']) { $wrapUSID = "$($rawVal.userSettingID)" } if ($rawVal.PSObject.Properties['userSettingPresentation']) { $wrapUSP = $rawVal.userSettingPresentation } $rawVal = $rawVal.value } elseif (($rawVal -is [hashtable] -or $rawVal -is [System.Collections.IDictionary]) -and $rawVal.Contains('value')) { $hasValueKey = $true + if ($rawVal.Contains('valueType')) { $wrapVT = "$($rawVal['valueType'])" } if ($rawVal.Contains('use') -and $rawVal['use'] -eq $false) { $useFalse = $true } + if ($rawVal.Contains('items')) { $wrapItems = $rawVal['items'] } if ($rawVal.Contains('viewMode')) { $wrapVM = "$($rawVal['viewMode'])" } if ($rawVal.Contains('userSettingID')) { $wrapUSID = "$($rawVal['userSettingID'])" } if ($rawVal.Contains('userSettingPresentation')) { $wrapUSP = $rawVal['userSettingPresentation'] } @@ -2386,8 +2392,12 @@ function Emit-OutputParameters { } elseif ($rawVal -is [System.Collections.IDictionary]) { if ($rawVal.Contains('@type') -and "$($rawVal['@type'])" -eq 'Font') { $isFontDict = $true } } - $ptype = $script:outputParamTypes[$key] - if (-not $ptype) { $ptype = "xs:string" } + # Приоритет: явный wrapVT > известный тип ключа > xs:string + if ($wrapVT) { $ptype = $wrapVT } + else { + $ptype = $script:outputParamTypes[$key] + if (-not $ptype) { $ptype = "xs:string" } + } # Auto-promote to mltext if value is a multilang dict (но не Font/wrapper) if (-not $isFontDict -and ($rawVal -is [System.Management.Automation.PSCustomObject] -or $rawVal -is [hashtable] -or $rawVal -is [System.Collections.IDictionary])) { $ptype = "mltext" @@ -2414,6 +2424,31 @@ function Emit-OutputParameters { } else { X "$indent`t`t$(Esc-Xml "$rawVal")" } + # Nested sub-параметры (ТипДиаграммы.ВидПодписей и т.п.) — эмитим между value и extras + if ($wrapItems) { + $itemProps = if ($wrapItems -is [PSCustomObject]) { $wrapItems.PSObject.Properties } else { $null } + if ($itemProps) { + foreach ($ip in $itemProps) { + $subName = $ip.Name; $subWrap = $ip.Value + $subVal = if ($subWrap -is [PSCustomObject] -and $subWrap.PSObject.Properties['value']) { $subWrap.value } else { $subWrap } + $subVT = if ($subWrap -is [PSCustomObject] -and $subWrap.PSObject.Properties['valueType']) { "$($subWrap.valueType)" } else { 'xs:string' } + X "$indent`t`t" + X "$indent`t`t`t$(Esc-Xml $subName)" + X "$indent`t`t`t$(Esc-Xml "$subVal")" + X "$indent`t`t" + } + } elseif ($wrapItems -is [System.Collections.IDictionary]) { + foreach ($k in $wrapItems.Keys) { + $subWrap = $wrapItems[$k] + $subVal = if ($subWrap -is [System.Collections.IDictionary] -and $subWrap.Contains('value')) { $subWrap['value'] } else { $subWrap } + $subVT = if ($subWrap -is [System.Collections.IDictionary] -and $subWrap.Contains('valueType')) { "$($subWrap['valueType'])" } else { 'xs:string' } + X "$indent`t`t" + X "$indent`t`t`t$(Esc-Xml $k)" + X "$indent`t`t`t$(Esc-Xml "$subVal")" + X "$indent`t`t" + } + } + } if ($wrapVM) { X "$indent`t`t$(Esc-Xml $wrapVM)" } if ($wrapUSID) { $uid = if ("$wrapUSID" -eq 'auto') { New-Guid-String } else { "$wrapUSID" } diff --git a/.claude/skills/skd-compile/scripts/skd-compile.py b/.claude/skills/skd-compile/scripts/skd-compile.py index 21c5e3e1..daff98e9 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.py +++ b/.claude/skills/skd-compile/scripts/skd-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# skd-compile v1.67 — Compile 1C DCS from JSON +# skd-compile v1.68 — Compile 1C DCS from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -1948,19 +1948,26 @@ def emit_output_parameters(lines, params, indent): lines.append(f'{indent}') for key, val in params.items(): - # wrapper {value, use?, viewMode?, userSettingID?, userSettingPresentation?} + # wrapper {value, valueType?, use?, items?, viewMode?, userSettingID?, userSettingPresentation?} use_false = False wrap_vm = None wrap_usid = None wrap_usp = None + wrap_vt = None + wrap_items = None if isinstance(val, dict) and 'value' in val: + wrap_vt = val.get('valueType') if val.get('use') is False: use_false = True + wrap_items = val.get('items') wrap_vm = val.get('viewMode') wrap_usid = val.get('userSettingID') wrap_usp = val.get('userSettingPresentation') val = val['value'] is_font_dict = isinstance(val, dict) and val.get('@type') == 'Font' - ptype = OUTPUT_PARAM_TYPES.get(key, 'xs:string') + if wrap_vt: + ptype = wrap_vt + else: + ptype = OUTPUT_PARAM_TYPES.get(key, 'xs:string') # Auto-promote to mltext if value is a multilang dict (but not Font) if not is_font_dict and isinstance(val, dict): ptype = 'mltext' @@ -1979,6 +1986,19 @@ def emit_output_parameters(lines, params, indent): emit_mltext(lines, f'{indent}\t\t', 'dcscor:value', val) else: lines.append(f'{indent}\t\t{esc_xml(str(val))}') + # Nested sub-параметры (ТипДиаграммы.ВидПодписей и т.п.) + if wrap_items and isinstance(wrap_items, dict): + for sub_name, sub_wrap in wrap_items.items(): + if isinstance(sub_wrap, dict) and 'value' in sub_wrap: + sub_val = sub_wrap['value'] + sub_vt = sub_wrap.get('valueType', 'xs:string') + else: + sub_val = sub_wrap + sub_vt = 'xs:string' + lines.append(f'{indent}\t\t') + lines.append(f'{indent}\t\t\t{esc_xml(sub_name)}') + lines.append(f'{indent}\t\t\t{esc_xml(str(sub_val))}') + lines.append(f'{indent}\t\t') if wrap_vm: lines.append(f'{indent}\t\t{esc_xml(str(wrap_vm))}') if wrap_usid: diff --git a/.claude/skills/skd-decompile/scripts/skd-decompile.ps1 b/.claude/skills/skd-decompile/scripts/skd-decompile.ps1 index 55e79701..9d4d1ea0 100644 --- a/.claude/skills/skd-decompile/scripts/skd-decompile.ps1 +++ b/.claude/skills/skd-decompile/scripts/skd-decompile.ps1 @@ -1,4 +1,4 @@ -# skd-decompile v0.51 — Decompile 1C DCS Template.xml to JSON DSL (draft) +# skd-decompile v0.52 — Decompile 1C DCS Template.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -1671,18 +1671,42 @@ function Build-OutputParameters { $val = $it.SelectSingleNode("dcscor:value", $ns) if (-not $pName -or -not $val) { continue } $vType = Get-LocalXsiType $val + # Полный xsi:type (с префиксом) — нужен compile для bit-perfect, если ключ не в outputParamTypes. + $fullType = $null + $ta = $val.Attributes['xsi:type'] + if ($ta) { $fullType = $ta.Value } if ($vType -eq 'LocalStringType') { $rawVal = Get-MLText $val } elseif ($vType -eq 'Font') { $rawVal = Get-FontValue $val } else { $rawVal = $val.InnerText } - # Extras (use=false / viewMode / userSettingID / userSettingPresentation) → wrapper. + # Nested dcscor:items (sub-параметры типа ТипДиаграммы.ВидПодписей) + $nestedItems = [ordered]@{} + foreach ($sub in $it.SelectNodes("dcscor:item", $ns)) { + $subName = Get-Text $sub "dcscor:parameter" + $subVal = $sub.SelectSingleNode("dcscor:value", $ns) + if (-not $subName -or -not $subVal) { continue } + $subType = Get-LocalXsiType $subVal + $subFull = $null + $subTA = $subVal.Attributes['xsi:type'] + if ($subTA) { $subFull = $subTA.Value } + if ($subType -eq 'LocalStringType') { $subRaw = Get-MLText $subVal } + elseif ($subType -eq 'Font') { $subRaw = Get-FontValue $subVal } + else { $subRaw = $subVal.InnerText } + # Сохраняем как {value, valueType} чтобы compile воспроизвёл xsi:type + $nestedItems[$subName] = [ordered]@{ value = $subRaw; valueType = $subFull } + } + # Extras (use=false / viewMode / userSettingID / userSettingPresentation / nested items) → wrapper. $useV = Get-Text $it "dcscor:use" $vmN = $it.SelectSingleNode("dcsset:viewMode", $ns) $usidV = Get-Text $it "dcsset:userSettingID" $uspN = $it.SelectSingleNode("dcsset:userSettingPresentation", $ns) - $hasExtras = ($useV -eq 'false') -or $vmN -or $usidV -or $uspN + $hasExtras = ($useV -eq 'false') -or $vmN -or $usidV -or $uspN -or ($nestedItems.Count -gt 0) if ($hasExtras) { $wrap = [ordered]@{ value = $rawVal } + if ($fullType -and -not (($vType -eq 'LocalStringType') -or ($vType -eq 'Font'))) { + $wrap['valueType'] = $fullType + } if ($useV -eq 'false') { $wrap['use'] = $false } + if ($nestedItems.Count -gt 0) { $wrap['items'] = $nestedItems } if ($vmN) { $wrap['viewMode'] = $vmN.InnerText } if ($usidV) { $wrap['userSettingID'] = 'auto' } if ($uspN) { $wrap['userSettingPresentation'] = Get-MLText $uspN }