From 8bff8d7e058aec95e757001088a461cefda17571 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Tue, 9 Jun 2026 11:12:56 +0300 Subject: [PATCH] =?UTF-8?q?fix(form-compile,form-decompile):=20Table=20=20vs=20=20=E2=80=94=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D0=B2=D0=BE=D0=B4=20=D1=81=D0=B2=D0=BE=D0=B9=D1=81=D1=82?= =?UTF-8?q?=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DSL зря сводил оба тега в height, а компилятор для таблицы всегда эмитил → таблица с 5 регенерилась как 5 (форма БизнесСеть/ВыборОрганизации). Это РАЗНЫЕ свойства (высота элемента vs высота в строках), сосуществуют в 237 таблицах корпуса (Height-only 1242, HeightInTableRows-only 755). - Развёл: height → (generic Emit-Layout, как у всех элементов), новый heightInTableRows → . - Декомпилятор: Add-Layout ловит → height, Table-блок → heightInTableRows. Зеркало py. Кейс table расширен (оба тега), сертифицирован в 1С (платформа принимает оба). Регресс 39/39 в обоих рантаймах. Раундтрип TOTAL 68→61. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../skills/form-compile/scripts/form-compile.ps1 | 12 +++++++----- .../skills/form-compile/scripts/form-compile.py | 14 ++++++++------ .../form-decompile/scripts/form-decompile.ps1 | 9 +++++---- docs/form-dsl-spec.md | 5 +++-- .../Таблица/Forms/Форма/Ext/Form.xml | 2 ++ tests/skills/cases/form-compile/table.json | 2 +- 6 files changed, 26 insertions(+), 18 deletions(-) diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index ad1c0b84..d5778f16 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.87 — Compile 1C managed form from JSON or object metadata +# form-compile v1.88 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -2603,7 +2603,7 @@ function Emit-Element { "commandBarLocation"=1;"searchStringLocation"=1;"viewStatusLocation"=1;"searchControlLocation"=1 "excludedCommands"=1 "choiceMode"=1;"initialTreeView"=1;"enableDrag"=1;"enableStartDrag"=1 - "rowPictureDataPath"=1;"tableAutofill"=1 + "rowPictureDataPath"=1;"tableAutofill"=1;"heightInTableRows"=1 "rowSelectionMode"=1;"verticalLines"=1;"horizontalLines"=1 # dynamic-list table block "defaultItem"=1;"useAlternationRowColor"=1;"fileDragMode"=1;"autoRefresh"=1 @@ -2713,7 +2713,7 @@ function Emit-CommonFlags { # Общие layout-свойства — применимы ко всем элементам. Порядок согласован с # историческим выводом input/label, чтобы не сдвигать существующие снапшоты. -# -skipHeight: для Table (height → HeightInTableRows, эмитится в Emit-Table). +# -skipHeight: подавить (зарезервирован; Table теперь эмитит generic-ом + свой ). # -multiLineDefault: input без явного autoMaxWidth при multiLine → AutoMaxWidth=false. # Общие свойства элемента (любой тип, включая Button/cmdBar): default/skip/drag. function Emit-CommonElementProps { @@ -3768,7 +3768,9 @@ function Emit-Table { if ($el.autoInsertNewRow -eq $true) { X "$innertrue" } # RowFilter — nil-плейсхолдер (всегда пустой); ключ присутствует → эмитим if ($el.PSObject.Properties['rowFilter']) { X "$inner" } - if ($el.height) { X "$inner$($el.height)" } + # Высота в строках таблицы () — отдельное свойство от (высота элемента, + # эмитится generic-ом Emit-Layout ниже). Таблица может нести оба (237 в корпусе). + if ($el.heightInTableRows) { X "$inner$($el.heightInTableRows)" } if ($el.header -eq $false) { X "$inner
false
" } if ($el.footer -eq $true) { X "$inner
true
" } @@ -3797,7 +3799,7 @@ function Emit-Table { if ($el.PSObject.Properties["_dynList"] -and $el._dynList) { Emit-DynListTableBlock -el $el -indent $inner } if ($el.viewStatusLocation) { X "$inner$($el.viewStatusLocation)" } if ($el.searchControlLocation) { X "$inner$($el.searchControlLocation)" } - Emit-Layout -el $el -indent $inner -skipHeight + Emit-Layout -el $el -indent $inner if ($el.excludedCommands -and $el.excludedCommands.Count -gt 0) { X "$inner" diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 0cb0b4c4..239a9da0 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.87 — Compile 1C managed form from JSON or object metadata +# form-compile v1.88 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -1802,7 +1802,7 @@ KNOWN_KEYS = { "autofill", "choiceMode", "initialTreeView", "enableDrag", "enableStartDrag", "rowSelectionMode", "verticalLines", "horizontalLines", - "rowPictureDataPath", "tableAutofill", + "rowPictureDataPath", "tableAutofill", "heightInTableRows", # dynamic-list table block "defaultItem", "useAlternationRowColor", "fileDragMode", "autoRefresh", "autoRefreshPeriod", "choiceFoldersAndItems", "restoreCurrentRow", "showRoot", @@ -2707,7 +2707,7 @@ def emit_generic_scalars(lines, el, indent): def emit_layout(lines, el, indent, skip_height=False, multi_line_default=False): # Общие layout-свойства — применимы ко всем элементам. Порядок согласован # с историческим выводом input/label, чтобы не сдвигать существующие снапшоты. - # skip_height: для Table (height → HeightInTableRows, эмитится в emit_table). + # skip_height: подавить (зарезервирован; Table теперь эмитит generic-ом + свой ). # multi_line_default: input без явного autoMaxWidth при multiLine → AutoMaxWidth=false. emit_common_element_props(lines, el, indent) if 'autoMaxWidth' in el: @@ -3468,8 +3468,10 @@ def emit_table(lines, el, name, eid, indent): # RowFilter — nil-плейсхолдер (ключ присутствует → эмитим) if 'rowFilter' in el: lines.append(f'{inner}') - if el.get('height'): - lines.append(f'{inner}{el["height"]}') + # Высота в строках () — отдельное свойство от (высота элемента, + # эмитится generic-ом emit_layout ниже). Таблица может нести оба (237 в корпусе). + if el.get('heightInTableRows'): + lines.append(f'{inner}{el["heightInTableRows"]}') if el.get('header') is False: lines.append(f'{inner}
false
') if el.get('footer') is True: @@ -3510,7 +3512,7 @@ def emit_table(lines, el, name, eid, indent): lines.append(f'{inner}{el["viewStatusLocation"]}') if el.get('searchControlLocation'): lines.append(f'{inner}{el["searchControlLocation"]}') - emit_layout(lines, el, inner, skip_height=True) + emit_layout(lines, el, inner) if el.get('excludedCommands'): lines.append(f'{inner}') diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index 2ad7282b..440b3671 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.63 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.64 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( @@ -756,8 +756,8 @@ function Build-ConditionalAppearance { } # Общие layout-свойства → в $obj (симметрично Emit-Layout компилятора). -# Вызывается один раз для любого элемента. Height тут — пиксельная высота -# (); Table хранит высоту в строках () и ловит её сам. +# Вызывается один раз для любого элемента. Height тут — высота элемента (), +# в т.ч. у Table; высоту в строках () Table ловит отдельно в heightInTableRows. function Add-Layout { param($obj, $node) # Общие свойства элемента (любой тип): default/drag/skip @@ -1480,7 +1480,8 @@ function Decompile-Element { if ($node.SelectSingleNode("lf:RowFilter", $ns)) { $obj['rowFilter'] = $null } if ((Get-Child $node 'Header') -eq 'false') { $obj['header'] = $false } if ((Get-Child $node 'Footer') -eq 'true') { $obj['footer'] = $true } - $htr = Get-Child $node 'HeightInTableRows'; if ($htr) { $obj['height'] = [int]$htr } + # Высота в строках — отдельный ключ heightInTableRows (≠ height = , его ловит Add-Layout) + $htr = Get-Child $node 'HeightInTableRows'; if ($htr) { $obj['heightInTableRows'] = [int]$htr } # CommandBarLocation: для дин-список-таблицы компилятор авто-инжектит "None" → инвертируем # (нет тега → суппресс-маркер ""; "None" → опускаем = авто-дефолт; иначе → захват). $cbl = Get-Child $node 'CommandBarLocation' diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md index dfb29a65..38d14603 100644 --- a/docs/form-dsl-spec.md +++ b/docs/form-dsl-spec.md @@ -237,7 +237,7 @@ companion-панели с собственным контентом. Оба не | Свойство | XML | Значения | |----------|-----|----------| | `width` | `` | число | -| `height` | `` | число (у `table` → ``, высота в строках) | +| `height` | `` | число (высота элемента; у `table` — тоже ``. Высота в строках таблицы — отдельный ключ `heightInTableRows`, см. §table) | | `horizontalStretch` | `` | `true`/`false` (эмитится явное значение; отсутствие = дефолт) | | `verticalStretch` | `` | `true`/`false` (аналогично) | | `autoMaxWidth` | `` | `false` (у `input` при `multiLine` подставляется автоматически) | @@ -529,7 +529,8 @@ companion-панели с собственным контентом. Оба не | `verticalLines` / `horizontalLines` | bool | Линии сетки (эмитится явное `false`) | | `initialTreeView` | string | `ExpandTopLevel`, `ExpandAllLevels`, `NoExpand` | | `rowsPicture` | string | Картинка строк (`CommonPicture.X`) | -| `height` | int | Высота в строках таблицы | +| `height` | int | Высота элемента таблицы (``, как у прочих элементов) | +| `heightInTableRows` | int | Высота в строках (``) — отдельное свойство от `height`; таблица может нести оба | | `header` | bool | Показывать шапку | | `footer` | bool | Показывать подвал | | `commandBarLocation` | string | `None`, `Top`, `Bottom`, `Auto` | diff --git a/tests/skills/cases/form-compile/snapshots/table/DataProcessors/Таблица/Forms/Форма/Ext/Form.xml b/tests/skills/cases/form-compile/snapshots/table/DataProcessors/Таблица/Forms/Форма/Ext/Form.xml index a514ad06..6c2f34f9 100644 --- a/tests/skills/cases/form-compile/snapshots/table/DataProcessors/Таблица/Forms/Форма/Ext/Form.xml +++ b/tests/skills/cases/form-compile/snapshots/table/DataProcessors/Таблица/Forms/Форма/Ext/Form.xml @@ -13,8 +13,10 @@ Данные Top true + 5 None None + 80 Add Delete diff --git a/tests/skills/cases/form-compile/table.json b/tests/skills/cases/form-compile/table.json index 2331a57f..dc487404 100644 --- a/tests/skills/cases/form-compile/table.json +++ b/tests/skills/cases/form-compile/table.json @@ -16,7 +16,7 @@ "input": { "title": "Просмотр данных", "elements": [ - { "table": "Данные", "path": "Данные", "changeRowSet": true, "titleLocation": "top", + { "table": "Данные", "path": "Данные", "changeRowSet": true, "titleLocation": "top", "height": 80, "heightInTableRows": 5, "viewStatusLocation": "None", "searchControlLocation": "None", "excludedCommands": ["Add", "Delete", "MoveUp", "MoveDown"], "commandBar": { "autofill": false, "children": [