From a3395d4abebd5f6db60feb997e3e4fbef64e169f Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Thu, 11 Jun 2026 11:49:45 +0300 Subject: [PATCH] =?UTF-8?q?feat(form-decompile,form-compile):=20Horizontal?= =?UTF-8?q?IfPossible=20=D0=B2=20=D0=BE=D1=80=D0=B8=D0=B5=D0=BD=D1=82?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B8=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=86=D1=8B/=D0=B3=D1=80=D1=83=D0=BF=D0=BF=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Страница (Page) и обычная группа (UsualGroup) теряли HorizontalIfPossible — orientation-карта содержала Horizontal/Vertical/AlwaysHorizontal/ AlwaysVertical, но не HorizontalIfPossible (ROOT Page>Group 359 на 189 формах). Доступные значения (по конфигуратору + корпусу): страница/обычная группа — Vertical/HorizontalIfPossible/AlwaysHorizontal (+ Horizontal реально встречается: 1288 форм на странице — XML-enum шире UI-дропдауна, оставлен forgiving); группа колонок таблицы — Vertical/Horizontal/InCell (уже обрабатывалось, не трогаем). InCell на странице/группе не добавляем — в корпусе не встречается. Коэрция не делается: фактическое значение сохраняется как есть (верность раундтрипа). Добавлен horizontalIfPossible в Emit-Page + Emit-Group switch (ps1+py) и в gmap декомпилятора (Page + UsualGroup). Таргет-верификация (выборка 50 из 189): 0 остатка, 29 стали match, 0 регрессов. Кейс pages пере-сертифицирован в 1С (HorizontalIfPossible грузится). Регресс 43/43. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../skills/form-compile/scripts/form-compile.ps1 | 16 ++++++++++------ .../skills/form-compile/scripts/form-compile.py | 4 +++- .../form-decompile/scripts/form-decompile.ps1 | 6 +++--- docs/form-dsl-spec.md | 4 ++-- tests/skills/cases/form-compile/pages.json | 4 ++-- .../Мастер/Forms/Форма/Ext/Form.xml | 4 ++-- 6 files changed, 22 insertions(+), 16 deletions(-) diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index deee8b2b..ddaf8d0f 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.110 — Compile 1C managed form from JSON or object metadata +# form-compile v1.111 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -3429,6 +3429,7 @@ function Emit-Group { "vertical" { "Vertical" } "alwayshorizontal" { "AlwaysHorizontal" } "alwaysvertical" { "AlwaysVertical" } + "horizontalifpossible" { "HorizontalIfPossible" } "collapsible" { "Vertical" } default { $null } } @@ -4323,12 +4324,15 @@ function Emit-Page { Emit-CommonFlags -el $el -indent $inner if ($el.group) { + # Доступные значения страницы/обычной группы: Vertical / HorizontalIfPossible / AlwaysHorizontal + # (InCell — только у columnGroup). Horizontal/AlwaysVertical оставлены forgiving (legacy). $orientation = switch ("$($el.group)") { - "horizontal" { "Horizontal" } - "vertical" { "Vertical" } - "alwaysHorizontal" { "AlwaysHorizontal" } - "alwaysVertical" { "AlwaysVertical" } - default { $null } + "horizontal" { "Horizontal" } + "vertical" { "Vertical" } + "alwaysHorizontal" { "AlwaysHorizontal" } + "alwaysVertical" { "AlwaysVertical" } + "horizontalIfPossible" { "HorizontalIfPossible" } + default { $null } } if ($orientation) { X "$inner$orientation" } } diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 8e07ec57..e02c9c2c 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.110 — Compile 1C managed form from JSON or object metadata +# form-compile v1.111 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -3514,6 +3514,7 @@ def emit_group(lines, el, name, eid, indent): 'vertical': 'Vertical', 'alwayshorizontal': 'AlwaysHorizontal', 'alwaysvertical': 'AlwaysVertical', + 'horizontalifpossible': 'HorizontalIfPossible', 'collapsible': 'Vertical', } orientation = orientation_map.get(group_val) @@ -4048,6 +4049,7 @@ def emit_page(lines, el, name, eid, indent): 'vertical': 'Vertical', 'alwaysHorizontal': 'AlwaysHorizontal', 'alwaysVertical': 'AlwaysVertical', + 'horizontalIfPossible': 'HorizontalIfPossible', } orientation = orientation_map.get(str(el['group'])) if orientation: diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index 1bae0ad8..b724efd1 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.86 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.87 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( @@ -1495,7 +1495,7 @@ function Decompile-Element { # не эмитим). Платформа явно пишет Vertical в большинстве случаев, поэтому '' ≠ 'vertical' # — иначе компилятор додумает Vertical там, где его нет. $g = Get-Child $node 'Group' - $gmap = @{ 'Horizontal'='horizontal'; 'Vertical'='vertical'; 'AlwaysHorizontal'='alwaysHorizontal'; 'AlwaysVertical'='alwaysVertical' } + $gmap = @{ 'Horizontal'='horizontal'; 'Vertical'='vertical'; 'AlwaysHorizontal'='alwaysHorizontal'; 'AlwaysVertical'='alwaysVertical'; 'HorizontalIfPossible'='horizontalIfPossible' } if ($g -and $gmap.ContainsKey($g)) { $obj[$key] = $gmap[$g] } else { $obj[$key] = '' } $behavior = Get-Child $node 'Behavior' if ($behavior) { @@ -1734,7 +1734,7 @@ function Decompile-Element { $obj[$key] = $name Add-CommonProps $obj $node $name $g = Get-Child $node 'Group' - $gmap = @{ 'Horizontal'='horizontal'; 'Vertical'='vertical'; 'AlwaysHorizontal'='alwaysHorizontal'; 'AlwaysVertical'='alwaysVertical' } + $gmap = @{ 'Horizontal'='horizontal'; 'Vertical'='vertical'; 'AlwaysHorizontal'='alwaysHorizontal'; 'AlwaysVertical'='alwaysVertical'; 'HorizontalIfPossible'='horizontalIfPossible' } if ($g -and $gmap.ContainsKey($g)) { $obj['group'] = $gmap[$g] } if ((Get-Child $node 'ShowTitle') -eq 'false') { $obj['showTitle'] = $false } $kids = Decompile-Children $node diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md index fe9cf762..ef093fe3 100644 --- a/docs/form-dsl-spec.md +++ b/docs/form-dsl-spec.md @@ -65,7 +65,7 @@ | `verticalScroll` | `` | `useIfNecessary`, `Auto`, `AlwaysShow`, `Never` | | `width` | `` | число | | `height` | `` | число | -| `group` | `` | `Vertical`, `Horizontal`, `AlwaysHorizontal`, `AlwaysVertical` | +| `group` | `` | `Vertical`, `Horizontal`, `AlwaysHorizontal`, `AlwaysVertical`, `HorizontalIfPossible` | | `useForFoldersAndItems` | `` | `Folders`, `Items`, `FoldersAndItems` | | `reportResult` | `` | Имя реквизита-результата (форма отчёта) | | `detailsData` | `` | Имя реквизита данных расшифровки (форма отчёта) | @@ -351,7 +351,7 @@ companion-панели с собственным контентом. Оба не | Свойство | Тип | Описание | |----------|-----|----------| -| `group` | string | Ориентация: `horizontal`, `vertical`, `alwaysHorizontal`, `alwaysVertical`. **`""`** → `` не эмитится (тег отсутствовал в исходнике; платформа сериализует «Группировку», только если она задана в конфигураторе — даже явный `Vertical` хранится, поэтому `""` ≠ `vertical`). Ключ обязателен как тип-маркер группы. (Legacy: `collapsible` = `vertical` + `behavior:'collapsible'`) | +| `group` | string | Ориентация: `vertical`, `horizontalIfPossible`, `alwaysHorizontal` (страница/обычная группа); `horizontal`, `vertical`, `inCell` (группа колонок таблицы — `columnGroup`). `horizontal`/`alwaysVertical` принимаются forgiving (реальные значения в корпусе, хотя UI конфигуратора их не предлагает). **`""`** → `` не эмитится (тег отсутствовал в исходнике; платформа сериализует «Группировку», только если она задана в конфигураторе — даже явный `Vertical` хранится, поэтому `""` ≠ `vertical`). Ключ обязателен как тип-маркер группы. (Legacy: `collapsible` = `vertical` + `behavior:'collapsible'`) | | `behavior` | string | Поведение (``): `usual`, `collapsible`, `popup`. **Отсутствие = Авто** (дефолт, не эмитится). Свёртываемая/всплывающая несут доп. свойства | | `collapsed` | bool | Свёрнута (у `collapsible`/`popup`) | | `collapsedTitle` | string/object | Заголовок свёрнутого представления (``), мультиязычный текст | diff --git a/tests/skills/cases/form-compile/pages.json b/tests/skills/cases/form-compile/pages.json index 6c079523..78234823 100644 --- a/tests/skills/cases/form-compile/pages.json +++ b/tests/skills/cases/form-compile/pages.json @@ -21,11 +21,11 @@ { "page": "Шаг1", "title": "", "showTitle": false, "children": [ { "input": "Параметр1", "path": "Параметр1" } ]}, - { "page": "Шаг2", "title": "Результат", "titleDataPath": "Итог", "tooltip": "Шаг \"Результат\"", "group": "horizontal", "children": [ + { "page": "Шаг2", "title": "Результат", "titleDataPath": "Итог", "tooltip": "Шаг \"Результат\"", "group": "horizontalIfPossible", "children": [ { "input": "Итог", "path": "Итог", "readOnly": true } ]} ]}, - { "group": "horizontal", "name": "Навигация", "children": [ + { "group": "horizontalIfPossible", "name": "Навигация", "children": [ { "button": "Назад", "command": "Назад", "title": "< Назад" }, { "button": "Далее", "command": "Далее", "title": "Далее >" } ]} diff --git a/tests/skills/cases/form-compile/snapshots/pages/DataProcessors/Мастер/Forms/Форма/Ext/Form.xml b/tests/skills/cases/form-compile/snapshots/pages/DataProcessors/Мастер/Forms/Форма/Ext/Form.xml index 7168ac00..3dc54417 100644 --- a/tests/skills/cases/form-compile/snapshots/pages/DataProcessors/Мастер/Forms/Форма/Ext/Form.xml +++ b/tests/skills/cases/form-compile/snapshots/pages/DataProcessors/Мастер/Forms/Форма/Ext/Form.xml @@ -43,7 +43,7 @@ Шаг "Результат" - Horizontal + HorizontalIfPossible Итог @@ -58,7 +58,7 @@ - Horizontal + HorizontalIfPossible