From 9af86b78108ce3541372dd759892b2c6b124ab52 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sat, 13 Jun 2026 12:48:07 +0300 Subject: [PATCH] feat(form-decompile,form-compile): ColumnGroup HeaderDataPath + HeaderFormat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Группа колонок таблицы может нести динамический заголовок из данных (путь) и формат заголовка (, ML-текст). Декомпилятор не захватывал, компилятор не эмитил → теряло (14 строк на форме БольничныйЛист/ФормаПодробнееОРасчете, 2 ColumnGroup'ы). Ключи на columnGroup: headerDataPath (path-скаляр), headerFormat (ML — строка/{ru,en}). Эмиссия в общем cell-блоке Emit-Layout: headerDataPath перед HeaderHorizontalAlign, headerFormat после (порядок XSD, рядом с уже сертифицированным HeaderHorizontalAlign). Добавлены в allowlist knownKeys (ps1+py). Корпус 8.3.24: HeaderDataPath/HeaderFormat = по 2 (обе в этой форме — редкий край). Форма → match (TOTAL 14→0). Зеркало py байт-в-байт (сверено нормализованным diff). Регресс 43/43 (ps1+py). Spec обновлён (раздел columnGroup). Cert: раундтрип + смежность с сертиф. HeaderHorizontalAlign в том же эмит-блоке. Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/skills/form-compile/scripts/form-compile.ps1 | 7 ++++++- .claude/skills/form-compile/scripts/form-compile.py | 9 ++++++++- .claude/skills/form-decompile/scripts/form-decompile.ps1 | 5 ++++- docs/form-dsl-spec.md | 2 ++ 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index aa5cb55f..3af22bb0 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.150 — Compile 1C managed form from JSON or object metadata +# form-compile v1.151 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -2914,6 +2914,7 @@ function Emit-Element { "wrap"=1;"openButton"=1;"listChoiceMode"=1;"showInFooter"=1 "extendedEditMultipleValues"=1;"chooseType"=1;"autoCellHeight"=1 "choiceButtonRepresentation"=1;"footerHorizontalAlign"=1;"headerHorizontalAlign"=1 + "headerDataPath"=1;"headerFormat"=1 "format"=1;"editFormat"=1;"choiceParameters"=1;"choiceParameterLinks"=1;"typeLink"=1 # label/hyperlink "hyperlink"=1;"formatted"=1 @@ -3067,8 +3068,12 @@ function Emit-CommonElementProps { foreach ($p in @(@('showInHeader','ShowInHeader'), @('showInFooter','ShowInFooter'), @('autoCellHeight','AutoCellHeight'))) { if ($null -ne $el.($p[0])) { X "$indent<$($p[1])>$(if ($el.($p[0])){'true'}else{'false'})" } } + # Динамический заголовок колонки-группы из данных (HeaderDataPath) — перед HeaderHorizontalAlign (порядок XSD) + if ($el.headerDataPath) { X "$indent$(Esc-Xml "$($el.headerDataPath)")" } if ($el.footerHorizontalAlign) { X "$indent$($el.footerHorizontalAlign)" } if ($el.headerHorizontalAlign) { X "$indent$($el.headerHorizontalAlign)" } + # Формат заголовка колонки-группы (ML-текст) — после HeaderHorizontalAlign (порядок XSD) + if ($el.headerFormat) { Emit-MLText -tag "HeaderFormat" -text $el.headerFormat -indent $indent } } # Картинка-ссылка с прозрачностью (HeaderPicture/FooterPicture/ValuesPicture/Page Picture). diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index cae41157..8b122b96 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.150 — Compile 1C managed form from JSON or object metadata +# form-compile v1.151 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -2028,6 +2028,7 @@ KNOWN_KEYS = { "wrap", "openButton", "listChoiceMode", "showInHeader", "showInFooter", "extendedEditMultipleValues", "chooseType", "autoCellHeight", "choiceButtonRepresentation", "footerHorizontalAlign", "headerHorizontalAlign", + "headerDataPath", "headerFormat", "format", "editFormat", "choiceParameters", "choiceParameterLinks", "typeLink", "hyperlink", "formatted", "collapsedTitle", "showTitle", "united", "collapsed", "behavior", @@ -2814,10 +2815,16 @@ def emit_common_element_props(lines, el, indent): for key, tag in (('showInHeader', 'ShowInHeader'), ('showInFooter', 'ShowInFooter'), ('autoCellHeight', 'AutoCellHeight')): if el.get(key) is not None: lines.append(f'{indent}<{tag}>{"true" if el[key] else "false"}') + # Динамический заголовок колонки-группы из данных (HeaderDataPath) — перед HeaderHorizontalAlign (порядок XSD) + if el.get('headerDataPath'): + lines.append(f"{indent}{esc_xml(str(el['headerDataPath']))}") if el.get('footerHorizontalAlign'): lines.append(f"{indent}{el['footerHorizontalAlign']}") if el.get('headerHorizontalAlign'): lines.append(f"{indent}{el['headerHorizontalAlign']}") + # Формат заголовка колонки-группы (ML-текст) — после HeaderHorizontalAlign (порядок XSD) + if el.get('headerFormat'): + emit_mltext(lines, indent, 'HeaderFormat', el['headerFormat']) def emit_picture_ref(lines, val, pic_tag, indent): diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index 147650fc..510e3eba 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.125 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.126 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( @@ -997,6 +997,9 @@ function Add-Layout { } $fha = Get-Child $node 'FooterHorizontalAlign'; if ($fha) { $obj['footerHorizontalAlign'] = $fha } $hha = Get-Child $node 'HeaderHorizontalAlign'; if ($hha) { $obj['headerHorizontalAlign'] = $hha } + # ColumnGroup: динамический заголовок из данных + формат заголовка (ML-текст) + $hdp = Get-Child $node 'HeaderDataPath'; if ($hdp) { $obj['headerDataPath'] = $hdp } + $hfNode = $node.SelectSingleNode("lf:HeaderFormat", $ns); if ($hfNode) { $hf = Get-LangText $hfNode; if ($null -ne $hf) { $obj['headerFormat'] = $hf } } } # TitleLocation у check/radio (зеркало Emit-TitleLocation): diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md index 004cbae4..28ab3256 100644 --- a/docs/form-dsl-spec.md +++ b/docs/form-dsl-spec.md @@ -647,6 +647,8 @@ companion-панели с собственным контентом. Оба не | `title` | string/object | Заголовок группы | | `showTitle` | bool | Показывать заголовок | | `showInHeader` | bool | Показывать в шапке таблицы | +| `headerDataPath` | string | Динамический заголовок группы из данных (``, путь реквизита — заголовок берётся из значения) | +| `headerFormat` | string/object | Формат заголовка группы (``, ML-текст — строка ru или `{ru,en}`) | | `width` | int | Ширина | | `horizontalStretch` | bool | Растягивание | | `children` | array | Колонки внутри группы |