feat(form-decompile,form-compile): картинки заголовка/подвала колонок + объектная модель картинки-ссылки (кластер column-pictures)

Декомпилятор терял картинки колонок таблиц формы:
- HeaderPicture/FooterPicture (общие для любого поля-колонки: input/check/labelField/picField)
- ValuesPicture: захват флага LoadTransparent (раньше брался только Ref)
- EditMode у PictureField

Единый формат "картинка-ссылка" (headerPicture/footerPicture/valuesPicture):
скаляр (Ref, loadTransparent=false — частый случай по корпусу ~64%) ИЛИ
объект {src, loadTransparent:true} для отклонения. Платформа всегда эмитит
<xr:LoadTransparent>, дефолт DSL=false. Флаг на каждой картинке (на одном
поле их бывает несколько).

Компилятор: HeaderPicture эмитится сразу после <EditMode> (порядок XDTO
строгий — иначе LoadConfigFromFiles падает с XDTO-исключением).

Forgiving-объект для <Picture> кнопки/попапа/команды: общий хелпер
Emit-CommandPicture принимает скаляр ИЛИ {src, loadTransparent}, чтобы
модель могла описать картинку объектно по аналогии с headerPicture.
Полярность кнопки сохранена (дефолт true). Декомпилятор не трогали —
объект только на вход, раундтрип без изменений.

Раундтрип sample-2.17: TOTAL 1582→1457, dec-fail/compile-fail 0.
Снапшот picture-field пересертифицирован в 1С. Регресс 34/34 ps+python.
Декомпилятор v0.45, компилятор v1.63.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-07 18:16:38 +03:00
co-authored by Claude Opus 4.8
parent 0636ac6877
commit bc53ee2a14
6 changed files with 177 additions and 66 deletions
@@ -1,4 +1,4 @@
# form-decompile v0.44 — Decompile 1C managed Form.xml to JSON DSL (draft)
# form-decompile v0.45 — Decompile 1C managed Form.xml to JSON DSL (draft)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
param(
@@ -853,6 +853,20 @@ function Decompile-AttrColumn {
}
# Общие свойства элемента (visible/enabled/readonly/title/events) → в hash
# Картинка-ссылка с прозрачностью (HeaderPicture/FooterPicture/ValuesPicture).
# Платформа ВСЕГДА эмитит <xr:LoadTransparent> (и true, и false) → дефолт DSL = false.
# Скаляр (Ref) при loadTransparent=false; объект {src,loadTransparent:true} при true.
function Get-PictureRef {
param($node, [string]$picTag)
$ref = $node.SelectSingleNode("lf:$picTag/xr:Ref", $ns)
if (-not $ref) { return $null }
$lt = $node.SelectSingleNode("lf:$picTag/xr:LoadTransparent", $ns)
if ($lt -and $lt.InnerText -eq 'true') {
return [ordered]@{ src = $ref.InnerText; loadTransparent = $true }
}
return $ref.InnerText
}
function Add-CommonProps {
param($obj, $node, [string]$elName)
if ((Get-Child $node 'Visible') -eq 'false') { $obj['hidden'] = $true }
@@ -868,6 +882,9 @@ function Add-CommonProps {
$ttNode = $node.SelectSingleNode("lf:ToolTip", $ns)
if ($ttNode) { $tt = Get-LangText $ttNode; if ($null -ne $tt) { $obj['tooltip'] = $tt } }
$ttr = Get-Child $node 'ToolTipRepresentation'; if ($ttr) { $obj['tooltipRepresentation'] = $ttr }
# Картинки заголовка/подвала колонки (любой field-тип, эмитятся платформой как column header/footer icon)
$hp = Get-PictureRef $node 'HeaderPicture'; if ($null -ne $hp) { $obj['headerPicture'] = $hp }
$fp = Get-PictureRef $node 'FooterPicture'; if ($null -ne $fp) { $obj['footerPicture'] = $fp }
$ev = Get-Events $node $elName
if ($ev) { $obj['events'] = $ev }
}
@@ -1121,8 +1138,9 @@ function Decompile-Element {
$obj[$key] = $name
$dp = Get-Child $node 'DataPath'; if ($dp) { $obj['path'] = $dp }
Add-CommonProps $obj $node $name
$em = Get-Child $node 'EditMode'; if ($em) { $obj['editMode'] = $em }
$tl = Get-Child $node 'TitleLocation'; if ($tl) { $obj['titleLocation'] = $tl.ToLower() }
$ref = $node.SelectSingleNode("lf:ValuesPicture/xr:Ref", $ns); if ($ref) { $obj['valuesPicture'] = $ref.InnerText }
$vp = Get-PictureRef $node 'ValuesPicture'; if ($null -ne $vp) { $obj['valuesPicture'] = $vp }
}
'CalendarField' {
$obj[$key] = $name