diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index b318ca08..8c45986c 100644 --- a/.claude/skills/form-compile/scripts/form-compile.ps1 +++ b/.claude/skills/form-compile/scripts/form-compile.ps1 @@ -1,4 +1,4 @@ -# form-compile v1.155 — Compile 1C managed form from JSON or object metadata +# form-compile v1.156 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -5434,6 +5434,12 @@ function Emit-DLParameter { $valIsArray = ($parsed.value -is [array]) -or ($parsed.value -is [System.Collections.IList] -and $parsed.value -isnot [string]) if ($valIsArray) { foreach ($v in @($parsed.value)) { Emit-DLValue -type $parsed.type -val $v -indent $ci -valueListAllowed $false } + } elseif ($parsed.valueExplicit -and ($null -ne $parsed.value) -and ("$($parsed.value)" -eq '') -and (("$($parsed.type)" -eq '') -or ("$($parsed.type)" -match '^string'))) { + # Явный пустой СТРОКОВЫЙ параметр (value:"" от декомпилятора) → типизированный пустой + # , НЕ nil. Решается ФОРМОЙ value (""→typed-empty, + # null/отсутствие→nil), независимо от valueListAllowed; декомпилятор различает ""/null + # (Convert-TypedValue пустого xs:string → "", nil → value опущен/null). Корпус: 26 xs:string. + X "$ci" } elseif ($vla -and (Test-DLEmptyValue $parsed.value) -and $parsed.valueExplicit) { # valueListAllowed + явный пустой (value:null от декомпилятора) → платформа здесь пишет nil X "$ci" diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index d8113dff..0857c605 100644 --- a/.claude/skills/form-compile/scripts/form-compile.py +++ b/.claude/skills/form-compile/scripts/form-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-compile v1.155 — Compile 1C managed form from JSON or object metadata +# form-compile v1.156 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -5198,6 +5198,12 @@ def emit_dl_parameter(lines, p, parsed, indent): if isinstance(pv, list): for v in pv: emit_dl_value(lines, parsed.get('type', ''), v, ci, False) + elif parsed.get('value_explicit') and pv is not None and str(pv) == '' and (str(parsed.get('type', '')) == '' or re.match(r'^string', str(parsed.get('type', '')))): + # Явный пустой СТРОКОВЫЙ параметр (value:"" от декомпилятора) → типизированный пустой + # , НЕ nil. Решается ФОРМОЙ value (""→typed-empty, + # null/отсутствие→nil), независимо от valueListAllowed; декомпилятор различает ""/null. + # Корпус: 26 xs:string typed-empty. + lines.append(f'{ci}') elif vla and is_dl_empty_value(pv) and parsed.get('value_explicit'): # valueListAllowed + явный пустой (value:null от декомпилятора) → платформа пишет nil lines.append(f'{ci}') diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index b2a9cea9..5f2c0858 100644 --- a/.claude/skills/form-decompile/scripts/form-decompile.ps1 +++ b/.claude/skills/form-decompile/scripts/form-decompile.ps1 @@ -1,4 +1,4 @@ -# form-decompile v0.130 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.131 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( @@ -2474,7 +2474,7 @@ $titleNode = $root.SelectSingleNode("lf:Title", $ns) if ($titleNode) { $t = Get-LangText $titleNode; if ($null -ne $t) { $dsl['title'] = $t } } # properties (прямые скаляры под
, PascalCase → camelCase) -$KNOWN_FORM_PROPS = @('AutoTitle','ReportResult','DetailsData','ReportFormType','AutoShowState','ReportResultViewMode','ViewModeApplicationOnSetReportResult','WindowOpeningMode','CommandBarLocation','SaveDataInSettings','AutoSaveDataInSettings','AutoTime','UsePostingMode','RepostOnWrite','AutoURL','AutoFillCheck','Customizable','EnterKeyBehavior','VerticalScroll','Width','Height','Group','UseForFoldersAndItems','SaveWindowSettings','ScalingMode','VerticalSpacing','VariantAppearance','ShowCloseButton','HorizontalAlign','ChildrenAlign','ShowTitle','ConversationsRepresentation','CollapseItemsByImportanceVariant','GroupList','ChildItemsWidth','VerticalAlign','HorizontalSpacing','CustomSettingsFolder') +$KNOWN_FORM_PROPS = @('AutoTitle','ReportResult','DetailsData','ReportFormType','AutoShowState','ReportResultViewMode','ViewModeApplicationOnSetReportResult','WindowOpeningMode','CommandBarLocation','SaveDataInSettings','AutoSaveDataInSettings','AutoTime','UsePostingMode','RepostOnWrite','AutoURL','AutoFillCheck','Customizable','EnterKeyBehavior','VerticalScroll','Width','Height','Group','UseForFoldersAndItems','SaveWindowSettings','ScalingMode','VerticalSpacing','VariantAppearance','ShowCloseButton','HorizontalAlign','ChildrenAlign','ShowTitle','ConversationsRepresentation','CollapseItemsByImportanceVariant','GroupList','ChildItemsWidth','VerticalAlign','HorizontalSpacing','CustomSettingsFolder','SettingsStorage') $props = [ordered]@{} foreach ($pn in $KNOWN_FORM_PROPS) { $v = Get-Child $root $pn diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md index e061a264..6a83c677 100644 --- a/docs/form-dsl-spec.md +++ b/docs/form-dsl-spec.md @@ -984,7 +984,7 @@ Forgiving-синонимы типа: XML-имя (`SpreadSheetDocumentField`) и |-----------|-----------| | `title` | Авто из имени (camelCase → «Заполнена серия»); явный `title`/`[Заголовок]` — только для переопределения | | `useRestriction` | Эмитится всегда, **умолчание `true`**; для выключения — объект `{ "useRestriction": false }` | -| `value` | Умолчание — пустое (`xsi:nil`), даже при заданном типе | +| `value` | Нет ключа → `xsi:nil`. **Явная пустая строка `value: ""`** → типизированный пустой `` (НЕ nil; платформа так пишет часть пустых строковых параметров — корпус 27). Декомпилятор различает: пустой строковый тег → `""`, nil-тег → ключ опущен/`null` | Объектные ключи (как в СКД): `name`, `title`, `type`/`valueType`, `value`, `valueListAllowed`, `useRestriction`, `availableAsField`, `expression`, `availableValues` (`[{ value, presentation }]`), `inputParameters`, `denyIncompleteValues`, `use`.