diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1
index 1ffce5ee..1895357a 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.96 — Compile 1C managed form from JSON or object metadata
+# form-compile v1.97 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[string]$JsonPath,
@@ -2616,6 +2616,8 @@ function Emit-Element {
"pointerType"=1;"drawingSelectionShowMode"=1;"warningOnEditRepresentation"=1;"markingAppearance"=1
# report-form контекст (generic-скаляры элементов)
"horizontalSpacing"=1;"representationInContextMenu"=1;"settingsNamedItemDetailedRepresentation"=1
+ # хвост: высота элемента списка / ширина выпадающего списка / картинка кнопки выбора / прозрачный пиксель
+ "itemHeight"=1;"dropListWidth"=1;"choiceButtonPicture"=1;"transparentPixel"=1
# columnGroup-specific
"showInHeader"=1
# radio-specific
@@ -2920,6 +2922,9 @@ $script:genericScalars = @(
@{ Tag='HorizontalSpacing'; Key='horizontalSpacing'; Kind='value' }
@{ Tag='RepresentationInContextMenu'; Key='representationInContextMenu'; Kind='value' }
@{ Tag='SettingsNamedItemDetailedRepresentation'; Key='settingsNamedItemDetailedRepresentation'; Kind='bool' }
+ # Хвост: высота элемента списка (radio) / ширина выпадающего списка (input)
+ @{ Tag='ItemHeight'; Key='itemHeight'; Kind='value' }
+ @{ Tag='DropListWidth'; Key='dropListWidth'; Kind='value' }
)
function Emit-GenericScalars {
@@ -3259,6 +3264,7 @@ function Emit-Input {
}
}
if ($el.choiceButtonRepresentation) { X "$inner$($el.choiceButtonRepresentation)" }
+ Emit-PictureRef -val $el.choiceButtonPicture -picTag 'ChoiceButtonPicture' -indent $inner
Emit-Layout -el $el -indent $inner -multiLineDefault ([bool]($el.multiLine -eq $true))
if ($el.inputHint) {
@@ -3625,11 +3631,23 @@ function Emit-ChoiceParameters {
foreach ($item in @($cp)) {
if ($item -is [string]) { $item = ConvertFrom-ChoiceParamShorthand $item }
$name = Get-ElProp $item @('name','имя')
+ # Наличие ключа value (≠ значения): hashtable (shorthand) vs PSCustomObject (JSON-объект)
+ if ($item -is [System.Collections.IDictionary]) {
+ $hasVal = $item.Contains('value') -or $item.Contains('значение')
+ } else {
+ $hasVal = ($null -ne $item.PSObject.Properties['value']) -or ($null -ne $item.PSObject.Properties['значение'])
+ }
$val = Get-ElProp $item @('value','значение')
X "$indent`t"
- X "$indent`t`t"
- Emit-ChoiceParamValue -value $val -indent "$indent`t`t`t"
- X "$indent`t`t"
+ # Параметр выбора без значения → (платформа, 13 в корпусе);
+ # со значением (в т.ч. пустой строкой) → FormChoiceListDesTimeValue.
+ if (-not $hasVal) {
+ X "$indent`t`t"
+ } else {
+ X "$indent`t`t"
+ Emit-ChoiceParamValue -value $val -indent "$indent`t`t`t"
+ X "$indent`t`t"
+ }
X "$indent`t"
}
X "$indent"
@@ -3777,6 +3795,8 @@ function Emit-LabelField {
if ($el.titleLocation) { X "$inner$(Map-TitleLoc "$($el.titleLocation)")" }
if ($el.editMode) { X "$inner$($el.editMode)" }
+ # PasswordMode на LabelField — платформа эмитит явный false (редко); факт. значение
+ if ($null -ne $el.passwordMode) { X "$inner$(if ($el.passwordMode){'true'}else{'false'})" }
Emit-ColumnPics -el $el -indent $inner
# ВНИМАНИЕ: у LabelField платформенный тег именно (опечатка 1С), не .
if ($el.hyperlink -eq $true) { X "$innertrue" }
@@ -4125,6 +4145,7 @@ function Emit-PictureDecoration {
if ($srcStr -match '^abs:(.*)$') { X "$inner`t$(Esc-Xml $matches[1])" }
else { X "$inner`t$(Esc-Xml $srcStr)" }
X "$inner`t$lt"
+ if ($el.transparentPixel) { X "$inner`t" }
X "$inner"
}
diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py
index 1553d3a4..73a651ef 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.96 — Compile 1C managed form from JSON or object metadata
+# form-compile v1.97 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import copy
@@ -1837,6 +1837,8 @@ KNOWN_KEYS = {
"pointerType", "drawingSelectionShowMode", "warningOnEditRepresentation", "markingAppearance",
# report-form контекст (generic-скаляры элементов)
"horizontalSpacing", "representationInContextMenu", "settingsNamedItemDetailedRepresentation",
+ # хвост: высота элемента списка / ширина выпадающего списка / картинка кнопки выбора / прозрачный пиксель
+ "itemHeight", "dropListWidth", "choiceButtonPicture", "transparentPixel",
}
# picture/picField — НИЗКИЙ приоритет: 'picture' это и тип (PictureDecoration), и свойство-иконка
@@ -2175,12 +2177,18 @@ def emit_choice_parameters(lines, el, indent):
if isinstance(item, str):
item = from_choice_param_shorthand(item)
name = get_el_prop(item, ('name', 'имя'))
+ has_val = isinstance(item, dict) and ('value' in item or 'значение' in item)
val = get_el_prop(item, ('value', 'значение'))
name_s = '' if name is None else str(name)
lines.append(f'{indent}\t')
- lines.append(f'{indent}\t\t')
- emit_choice_param_value(lines, val, f'{indent}\t\t\t')
- lines.append(f'{indent}\t\t')
+ # Параметр выбора без значения → (платформа, 13 в корпусе);
+ # со значением (в т.ч. пустой строкой) → FormChoiceListDesTimeValue.
+ if not has_val:
+ lines.append(f'{indent}\t\t')
+ else:
+ lines.append(f'{indent}\t\t')
+ emit_choice_param_value(lines, val, f'{indent}\t\t\t')
+ lines.append(f'{indent}\t\t')
lines.append(f'{indent}\t')
lines.append(f'{indent}')
@@ -2741,6 +2749,9 @@ GENERIC_SCALARS = [
('HorizontalSpacing', 'horizontalSpacing', 'value'),
('RepresentationInContextMenu', 'representationInContextMenu', 'value'),
('SettingsNamedItemDetailedRepresentation', 'settingsNamedItemDetailedRepresentation', 'bool'),
+ # Хвост: высота элемента списка (radio) / ширина выпадающего списка (input)
+ ('ItemHeight', 'itemHeight', 'value'),
+ ('DropListWidth', 'dropListWidth', 'value'),
]
@@ -3313,6 +3324,7 @@ def emit_input(lines, el, name, eid, indent):
lines.append(f'{inner}<{tag} xsi:type="{mvt}">{esc_xml(str(el[key]))}{tag}>')
if el.get('choiceButtonRepresentation'):
lines.append(f'{inner}{el["choiceButtonRepresentation"]}')
+ emit_picture_ref(lines, el.get('choiceButtonPicture'), 'ChoiceButtonPicture', inner)
emit_layout(lines, el, inner, multi_line_default=(el.get('multiLine') is True))
if el.get('inputHint'):
@@ -3474,6 +3486,9 @@ def emit_label_field(lines, el, name, eid, indent):
lines.append(f'{inner}{map_title_loc(el["titleLocation"])}')
if el.get('editMode'):
lines.append(f'{inner}{el["editMode"]}')
+ # PasswordMode на LabelField — платформа эмитит явный false (редко); факт. значение
+ if el.get('passwordMode') is not None:
+ lines.append(f'{inner}{"true" if el["passwordMode"] else "false"}')
emit_column_pics(lines, el, inner)
# ВНИМАНИЕ: у LabelField платформенный тег (опечатка 1С), не .
if el.get('hyperlink') is True:
@@ -3819,6 +3834,9 @@ def emit_picture_decoration(lines, el, name, eid, indent):
else:
lines.append(f'{inner}\t{esc_xml(src_str)}')
lines.append(f'{inner}\t{lt}')
+ tpx = el.get('transparentPixel')
+ if tpx:
+ lines.append(f'{inner}\t')
lines.append(f'{inner}')
if el.get('hyperlink') is True:
diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1
index 814dd5a7..01385a2c 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.72 — Decompile 1C managed Form.xml to JSON DSL (draft)
+# form-decompile v0.73 — Decompile 1C managed Form.xml to JSON DSL (draft)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
param(
@@ -1192,6 +1192,9 @@ $GENERIC_SCALARS = @(
@{ Tag='HorizontalSpacing'; Key='horizontalSpacing'; Kind='value' }
@{ Tag='RepresentationInContextMenu'; Key='representationInContextMenu'; Kind='value' }
@{ Tag='SettingsNamedItemDetailedRepresentation'; Key='settingsNamedItemDetailedRepresentation'; Kind='bool' }
+ # Хвост: высота элемента списка (radio) / ширина выпадающего списка (input)
+ @{ Tag='ItemHeight'; Key='itemHeight'; Kind='value' }
+ @{ Tag='DropListWidth'; Key='dropListWidth'; Kind='value' }
)
# Захват generic-скаляров. Специфичная обработка (если ключ уже задан) — побеждает.
@@ -1479,6 +1482,7 @@ function Decompile-Element {
}
}
$cbr = Get-Child $node 'ChoiceButtonRepresentation'; if ($cbr) { $obj['choiceButtonRepresentation'] = $cbr }
+ $cbp = Get-PictureRef $node 'ChoiceButtonPicture'; if ($null -ne $cbp) { $obj['choiceButtonPicture'] = $cbp }
if ((Get-Child $node 'TextEdit') -eq 'false') { $obj['textEdit'] = $false }
$cl = Decompile-ChoiceList $node; if ($cl) { $obj['choiceList'] = $cl }
Add-FormatProps $obj $node
@@ -1524,6 +1528,8 @@ function Decompile-Element {
$em = Get-Child $node 'EditMode'; if ($em) { $obj['editMode'] = $em }
# LabelField: тег (опечатка платформы), не
if ((Get-Child $node 'Hiperlink') -eq 'true') { $obj['hyperlink'] = $true }
+ # PasswordMode на LabelField — платформа эмитит явный false (редко); захват факт. значения
+ $pm = Get-Child $node 'PasswordMode'; if ($null -ne $pm) { $obj['passwordMode'] = ($pm -eq 'true') }
Add-FormatProps $obj $node
}
'PictureDecoration' {
@@ -1536,6 +1542,9 @@ function Decompile-Element {
$abs = $node.SelectSingleNode("lf:Picture/xr:Abs", $ns)
if ($ref) { $obj['src'] = $ref.InnerText } elseif ($abs) { $obj['src'] = "abs:$($abs.InnerText)" } # встроенная картинка → префикс abs:
$lt = $node.SelectSingleNode("lf:Picture/xr:LoadTransparent", $ns); if ($lt -and $lt.InnerText -eq 'true') { $obj['loadTransparent'] = $true }
+ # Прозрачный пиксель картинки () — координаты фона прозрачности
+ $tpx = $node.SelectSingleNode("lf:Picture/xr:TransparentPixel", $ns)
+ if ($tpx) { $obj['transparentPixel'] = [ordered]@{ x = [int]$tpx.GetAttribute('x'); y = [int]$tpx.GetAttribute('y') } }
if ((Get-Child $node 'Hyperlink') -eq 'true') { $obj['hyperlink'] = $true }
}
'PictureField' {
@@ -1762,7 +1771,7 @@ $titleNode = $root.SelectSingleNode("lf:Title", $ns)
if ($titleNode) { $t = Get-LangText $titleNode; if ($null -ne $t) { $dsl['title'] = $t } }
# properties (прямые скаляры под