feat(form-decompile,form-compile): суппресс-маркер title:"" для команд (подавление авто-вывода заголовка)

Раундтрип додумывал <Title> команды из имени, когда в оригинале заголовка нет
(напр. ФормаРабочегоМеста_320х320: 126 строк ADDED — «Задания выбрать», «Сканирование
далее» и т.п. на ~30 командах-кнопках с одной картинкой).

Корпус (acc+erp 8.3.24): из 92040 команд форм 99.87% имеют <Title> (захват штатный),
лишь 121 (0.13%) — без заголовка. Значит авто-вывод как дефолт верен (помощь модели),
а для редкого хвоста нужен суппресс-маркер — ровно как уже сделано для элементов
(Emit-Title) и формы (autoTitle).

compile (ps1+py): Emit-Commands зеркалит Emit-Title — ключ title есть+непустой → эмитим;
есть+"" → суппресс (не эмитим, не додумываем); отсутствует → авто-вывод из имени.
decompile: нет <Title> у команды → title:"" (иначе компилятор додумает).

Верификация: таргет-раундтрип формы → match (было 126 → 0); регресс form-compile 43/43
(ps1+py); 1С-cert кейса commands (команда с title:"" грузится без <Title>). spec обновлён.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-12 11:22:52 +03:00
co-authored by Claude Opus 4.8
parent 6377cdfba5
commit da1d8c9297
6 changed files with 35 additions and 12 deletions
@@ -1,4 +1,4 @@
# form-compile v1.126 — Compile 1C managed form from JSON or object metadata # form-compile v1.127 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param( param(
[string]$JsonPath, [string]$JsonPath,
@@ -5390,9 +5390,13 @@ function Emit-Commands {
X "$indent`t<Command name=`"$($cmd.name)`" id=`"$cmdId`">" X "$indent`t<Command name=`"$($cmd.name)`" id=`"$cmdId`">"
$inner = "$indent`t`t" $inner = "$indent`t`t"
$cmdTitle = if ($cmd.title) { $cmd.title } else { Title-FromName -name "$($cmd.name)" } # Заголовок команды (зеркало Emit-Title): ключ есть+непустой → эмитим; ключ есть+"" → суппресс
if ($cmdTitle) { # (в оригинале <Title> нет — не додумывать); ключ отсутствует → авто-вывод из имени (помощь модели).
Emit-MLText -tag "Title" -text $cmdTitle -indent $inner if ($null -ne $cmd.PSObject.Properties['title']) {
if ($cmd.title) { Emit-MLText -tag "Title" -text $cmd.title -indent $inner }
} else {
$cmdTitle = Title-FromName -name "$($cmd.name)"
if ($cmdTitle) { Emit-MLText -tag "Title" -text $cmdTitle -indent $inner }
} }
if ($cmd.tooltip) { if ($cmd.tooltip) {
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# form-compile v1.126 — Compile 1C managed form from JSON or object metadata # form-compile v1.127 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
import copy import copy
@@ -5111,9 +5111,15 @@ def emit_commands(lines, cmds, indent):
lines.append(f'{indent}\t<Command name="{cmd["name"]}" id="{cmd_id}">') lines.append(f'{indent}\t<Command name="{cmd["name"]}" id="{cmd_id}">')
inner = f'{indent}\t\t' inner = f'{indent}\t\t'
cmd_title = cmd.get('title') or title_from_name(str(cmd['name'])) # Заголовок команды (зеркало emit_title): ключ есть+непустой → эмитим; ключ есть+"" → суппресс
if cmd_title: # (в оригинале <Title> нет — не додумывать); ключ отсутствует → авто-вывод из имени.
emit_mltext(lines, inner, 'Title', cmd_title) if 'title' in cmd:
if cmd['title']:
emit_mltext(lines, inner, 'Title', cmd['title'])
else:
cmd_title = title_from_name(str(cmd['name']))
if cmd_title:
emit_mltext(lines, inner, 'Title', cmd_title)
if cmd.get('tooltip'): if cmd.get('tooltip'):
emit_mltext(lines, inner, 'ToolTip', cmd['tooltip']) emit_mltext(lines, inner, 'ToolTip', cmd['tooltip'])
@@ -1,4 +1,4 @@
# form-decompile v1.00 — Decompile 1C managed Form.xml to JSON DSL (draft) # form-decompile v1.01 — Decompile 1C managed Form.xml to JSON DSL (draft)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
param( param(
@@ -2517,7 +2517,11 @@ if ($cmdsNode) {
$co = [ordered]@{}; $co['name'] = $c.GetAttribute("name") $co = [ordered]@{}; $co['name'] = $c.GetAttribute("name")
$act = Get-Child $c 'Action'; if ($act) { $co['action'] = $act } $act = Get-Child $c 'Action'; if ($act) { $co['action'] = $act }
if ((Get-Child $c 'ModifiesSavedData') -eq 'true') { $co['modifiesSavedData'] = $true } if ((Get-Child $c 'ModifiesSavedData') -eq 'true') { $co['modifiesSavedData'] = $true }
$tNode = $c.SelectSingleNode("lf:Title", $ns); if ($tNode) { $t = Get-LangText $tNode; if ($null -ne $t) { $co['title'] = $t } } # Заголовок команды: есть <Title> → захват; нет → суппресс-маркер "" (иначе компилятор
# додумает из имени — авто-вывод неверен для ~0.13% команд без заголовка в оригинале).
$tNode = $c.SelectSingleNode("lf:Title", $ns)
if ($tNode) { $t = Get-LangText $tNode; if ($null -ne $t) { $co['title'] = $t } }
else { $co['title'] = '' }
$ttNode = $c.SelectSingleNode("lf:ToolTip", $ns); if ($ttNode) { $t = Get-LangText $ttNode; if ($null -ne $t) { $co['tooltip'] = $t } } $ttNode = $c.SelectSingleNode("lf:ToolTip", $ns); if ($ttNode) { $t = Get-LangText $ttNode; if ($null -ne $t) { $co['tooltip'] = $t } }
$us = Decompile-XrFlag $c 'Use'; if ($null -ne $us) { $co['use'] = $us } $us = Decompile-XrFlag $c 'Use'; if ($null -ne $us) { $co['use'] = $us }
$cfo = Decompile-FunctionalOptions $c; if ($cfo) { $co['functionalOptions'] = $cfo } $cfo = Decompile-FunctionalOptions $c; if ($cfo) { $co['functionalOptions'] = $cfo }
+1 -1
View File
@@ -1027,7 +1027,7 @@ Forgiving-синонимы типа: XML-имя (`SpreadSheetDocumentField`) и
|----------|-----|----------| |----------|-----|----------|
| `name` | string | Имя команды (обязательно) | | `name` | string | Имя команды (обязательно) |
| `action` | string | Имя процедуры-обработчика | | `action` | string | Имя процедуры-обработчика |
| `title` | string | Заголовок | | `title` | string/object | Заголовок (`<Title>`, мультиязычный объект `{ru,en}` поддерживается). **Авто-вывод:** ключ отсутствует → компилятор додумывает заголовок из имени (`ЗаданияВыбрать` → «Задания выбрать»), помощь модели. Суппресс-маркер `title: ""` → заголовок не эмитить и не додумывать (для команд без `<Title>` в оригинале — редкие ~0.13%) |
| `tooltip` | string/object | Всплывающая подсказка команды (`<ToolTip>`) | | `tooltip` | string/object | Всплывающая подсказка команды (`<ToolTip>`) |
| `use` | bool/object | Доступность команды по ролям (`<Use>`). См. §4.1c | | `use` | bool/object | Доступность команды по ролям (`<Use>`). См. §4.1c |
| `functionalOptions` | array | Функциональные опции команды (см. §5) | | `functionalOptions` | array | Функциональные опции команды (см. §5) |
@@ -28,7 +28,8 @@
{ "name": "Результат", "type": "string" } { "name": "Результат", "type": "string" }
], ],
"commands": [ "commands": [
{ "name": "Выполнить", "action": "ВыполнитьОбработка", "shortcut": "Ctrl+Enter", "use": false, "modifiesSavedData": true, "picture": { "src": "StdPicture.ExecuteTask", "transparentPixel": { "x": 1, "y": 1 } } } { "name": "Выполнить", "action": "ВыполнитьОбработка", "shortcut": "Ctrl+Enter", "use": false, "modifiesSavedData": true, "picture": { "src": "StdPicture.ExecuteTask", "transparentPixel": { "x": 1, "y": 1 } } },
{ "name": "БезЗаголовка", "action": "БезЗаголовкаОбработка", "title": "", "representation": "Picture", "picture": { "src": "StdPicture.Refresh" } }
], ],
"commandInterface": { "commandInterface": {
"commandBar": { "commandBar": {
@@ -94,6 +94,14 @@
<xr:TransparentPixel x="1" y="1"/> <xr:TransparentPixel x="1" y="1"/>
</Picture> </Picture>
</Command> </Command>
<Command name="БезЗаголовка" id="13">
<Action>БезЗаголовкаОбработка</Action>
<Picture>
<xr:Ref>StdPicture.Refresh</xr:Ref>
<xr:LoadTransparent>true</xr:LoadTransparent>
</Picture>
<Representation>Picture</Representation>
</Command>
</Commands> </Commands>
<CommandInterface> <CommandInterface>
<CommandBar> <CommandBar>