feat(form-decompile,form-compile): семантика TitleLocation (кластер G2)

Принцип: компилятор не эмитит значение, равное дефолту платформы (который
платформа сама не пишет в XML). Умный дефолт (check→Right, radio→None) —
отдельная вещь, эмитится (он ≠ дефолт платформы Left).

- net ключа titleLocation → умный дефолт; titleLocation: "" → подавить
  (дефолт платформы); значение → эмитить с маппингом регистра.
- compiler PS1+PY: Emit-TitleLocation/emit_title_location + Map-TitleLoc
  (общий маппинг; у check раньше его не было — сырьё).
- decompiler: Add-TitleLocation (дефолт → опустить, нет тега → "", иначе значение).
- docs/form-dsl-spec: семантика titleLocation у check/radio.
- tests: input-fields расширен (Right-дефолт / ""-подавление / явный Top), сертифицирован.

АварийныйРежим: полный MATCH. Регресс 32/32 PS1+PY, churn нулевой.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-04 18:53:28 +03:00
co-authored by Claude Opus 4.8
parent 4ba1e595bf
commit 0941fc717d
6 changed files with 119 additions and 38 deletions
@@ -1,4 +1,4 @@
# form-decompile v0.5 — Decompile 1C managed Form.xml to JSON DSL (draft)
# form-decompile v0.6 — Decompile 1C managed Form.xml to JSON DSL (draft)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
param(
@@ -203,6 +203,15 @@ function Add-Layout {
$ha = Get-Child $node 'HorizontalAlign'; if ($ha) { $obj['horizontalAlign'] = $ha }
}
# TitleLocation у check/radio (зеркало Emit-TitleLocation):
# тега нет → "" (дефолт платформы); значение = умный дефолт → опускаем; иначе пишем.
function Add-TitleLocation {
param($obj, $node, [string]$smartDefault)
$tl = Get-Child $node 'TitleLocation'
if ($null -eq $tl) { $obj['titleLocation'] = '' }
elseif ($tl -ne $smartDefault) { $obj['titleLocation'] = $tl.ToLower() }
}
# Суффиксы авто-имён обработчиков (инверсия компилятора)
$HANDLER_SUFFIX = @{
'OnChange'='ПриИзменении'; 'StartChoice'='НачалоВыбора'; 'ChoiceProcessing'='ОбработкаВыбора';
@@ -375,12 +384,13 @@ function Decompile-Element {
$obj[$key] = $name
$dp = Get-Child $node 'DataPath'; if ($dp) { $obj['path'] = $dp }
Add-CommonProps $obj $node $name
$tl = Get-Child $node 'TitleLocation'; if ($tl) { $obj['titleLocation'] = $tl.ToLower() }
Add-TitleLocation $obj $node 'Right'
}
'RadioButtonField' {
$obj[$key] = $name
$dp = Get-Child $node 'DataPath'; if ($dp) { $obj['path'] = $dp }
Add-CommonProps $obj $node $name
Add-TitleLocation $obj $node 'None'
$rbt = Get-Child $node 'RadioButtonType'; if ($rbt) { $obj['radioButtonType'] = $rbt }
$cc = Get-Child $node 'ColumnsCount'; if ($cc) { $obj['columnsCount'] = [int]$cc }
$cl = $node.SelectSingleNode("lf:ChoiceList", $ns)