diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1
index 756feff8..9a53169b 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.44 — Compile 1C managed form from JSON or object metadata
+# form-compile v1.45 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[string]$JsonPath,
@@ -2950,23 +2950,31 @@ function Emit-Radio {
X "$indent"
}
+# Заголовок декорации (Label/Picture): formatted-aware
через единую ML-text форму
+# (reuse Resolve-MLFormatted, как у extendedTooltip). Атрибут formatted эмитится ВСЕГДА
+# (специфика декораций). Sibling-ключ `formatted` — back-compat override авто-детекта.
+function Emit-DecorationTitle {
+ param($el, [string]$name, [string]$indent, [switch]$auto)
+ $hasKey = $null -ne $el.PSObject.Properties['title']
+ $titleVal = if ($hasKey) { $el.title } elseif ($auto -and $name) { Title-FromName -name $name } else { $null }
+ if ($titleVal) {
+ $r = Resolve-MLFormatted $titleVal
+ $fmt = if ($null -ne $el.PSObject.Properties['formatted']) { [bool]$el.formatted } else { $r.formatted }
+ X "$indent"
+ Emit-MLItems -val $r.text -indent "$indent`t"
+ X "$indent"
+ }
+ if ($el.tooltip) { Emit-MLText -tag "ToolTip" -text $el.tooltip -indent $indent }
+ if ($el.tooltipRepresentation) { X "$indent$($el.tooltipRepresentation)" }
+}
+
function Emit-Label {
param($el, [string]$name, [int]$id, [string]$indent)
X "$indent"
$inner = "$indent`t"
- $hasTitleKey = $null -ne $el.PSObject.Properties['title']
- $labelTitle = if ($hasTitleKey) { $el.title } else { Title-FromName -name $name }
- if ($labelTitle) {
- # formatted — независимое свойство (НЕ выводится из hyperlink): ссылка может быть не-форматированной и наоборот.
- $formatted = if ($el.formatted -eq $true) { "true" } else { "false" }
- X "$inner"
- Emit-MLItems -val $labelTitle -indent "$inner`t"
- X "$inner"
- }
- if ($el.tooltip) { Emit-MLText -tag "ToolTip" -text $el.tooltip -indent $inner }
- if ($el.tooltipRepresentation) { X "$inner$($el.tooltipRepresentation)" }
+ Emit-DecorationTitle -el $el -name $name -indent $inner -auto
Emit-CommonFlags -el $el -indent $inner
@@ -3297,7 +3305,7 @@ function Emit-PictureDecoration {
X "$indent"
$inner = "$indent`t"
- Emit-Title -el $el -name $name -indent $inner
+ Emit-DecorationTitle -el $el -name $name -indent $inner
Emit-CommonFlags -el $el -indent $inner
if ($el.picture -or $el.src) {
diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py
index 4e991026..cc8c9bf2 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.44 — Compile 1C managed form from JSON or object metadata
+# form-compile v1.45 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import copy
@@ -2639,21 +2639,29 @@ def emit_radio_button_field(lines, el, name, eid, indent):
lines.append(f'{indent}')
+# Заголовок декорации (Label/Picture): formatted-aware через единую ML-text форму
+# (reuse resolve_ml_formatted, как у extendedTooltip). Sibling-ключ formatted — back-compat override.
+def emit_decoration_title(lines, el, name, indent, auto=False):
+ has_key = 'title' in el
+ title_val = el['title'] if has_key else (title_from_name(name) if (auto and name) else None)
+ if title_val:
+ text, fmt = resolve_ml_formatted(title_val)
+ if 'formatted' in el:
+ fmt = bool(el['formatted'])
+ lines.append(f'{indent}')
+ emit_ml_items(lines, f'{indent}\t', text)
+ lines.append(f'{indent}')
+ if el.get('tooltip'):
+ emit_mltext(lines, indent, 'ToolTip', el['tooltip'])
+ if el.get('tooltipRepresentation'):
+ lines.append(f'{indent}{el["tooltipRepresentation"]}')
+
+
def emit_label(lines, el, name, eid, indent):
lines.append(f'{indent}')
inner = f'{indent}\t'
- label_title = el['title'] if 'title' in el else title_from_name(name)
- if label_title:
- # formatted — независимое свойство (НЕ выводится из hyperlink).
- formatted = 'true' if el.get('formatted') is True else 'false'
- lines.append(f'{inner}')
- emit_ml_items(lines, f'{inner}\t', label_title)
- lines.append(f'{inner}')
- if el.get('tooltip'):
- emit_mltext(lines, inner, 'ToolTip', el['tooltip'])
- if el.get('tooltipRepresentation'):
- lines.append(f'{inner}{el["tooltipRepresentation"]}')
+ emit_decoration_title(lines, el, name, inner, auto=True)
emit_common_flags(lines, el, inner)
@@ -2971,7 +2979,7 @@ def emit_picture_decoration(lines, el, name, eid, indent):
lines.append(f'{indent}')
inner = f'{indent}\t'
- emit_title(lines, el, name, inner)
+ emit_decoration_title(lines, el, name, inner)
emit_common_flags(lines, el, inner)
if el.get('picture') or el.get('src'):
diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1
index 74595cb6..2f14b3b7 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.26 — Decompile 1C managed Form.xml to JSON DSL (draft)
+# form-decompile v0.27 — Decompile 1C managed Form.xml to JSON DSL (draft)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
param(
@@ -951,9 +951,9 @@ function Decompile-Element {
$obj[$key] = $name
Add-CommonProps $obj $node $name
if ((Get-Child $node 'Hyperlink') -eq 'true') { $obj['hyperlink'] = $true }
- # formatted — атрибут , НЕЗАВИСИМ от hyperlink (true → ключ, false → опускаем)
+ # title декорации — единая ML-text форма с авто-детектом formatted (как extendedTooltip)
$tiNode = $node.SelectSingleNode("lf:Title", $ns)
- if ($tiNode -and $tiNode.GetAttribute('formatted') -eq 'true') { $obj['formatted'] = $true }
+ if ($tiNode) { $tv = Get-MLFormattedValue $tiNode; if ($null -ne $tv) { $obj['title'] = $tv } }
}
'LabelField' {
$obj[$key] = $name
@@ -967,6 +967,9 @@ function Decompile-Element {
'PictureDecoration' {
$obj[$key] = $name
Add-CommonProps $obj $node $name
+ # title декорации — единая ML-text форма с formatted (атрибут у PictureDecoration)
+ $tiNode = $node.SelectSingleNode("lf:Title", $ns)
+ if ($tiNode) { $tv = Get-MLFormattedValue $tiNode; if ($null -ne $tv) { $obj['title'] = $tv } }
$ref = $node.SelectSingleNode("lf:Picture/xr:Ref", $ns); if ($ref) { $obj['src'] = $ref.InnerText }
$lt = $node.SelectSingleNode("lf:Picture/xr:LoadTransparent", $ns); if ($lt -and $lt.InnerText -eq 'true') { $obj['loadTransparent'] = $true }
if ((Get-Child $node 'Hyperlink') -eq 'true') { $obj['hyperlink'] = $true }
diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md
index bd800883..daa92667 100644
--- a/docs/form-dsl-spec.md
+++ b/docs/form-dsl-spec.md
@@ -291,9 +291,9 @@
| Свойство | Тип | Описание |
|----------|-----|----------|
-| `title` | string | Текст надписи |
+| `title` | string/object | Текст надписи. Единая ML-text форма (см. §4.1): строка / `{ru,en}` / `{text, formatted}`. У декораций `` всегда несёт атрибут `formatted` (авто-детект по разметке) |
| `hyperlink` | bool | Режим гиперссылки |
-| `formatted` | bool | Форматированный текст (``). **Независим от `hyperlink`** — выводится только при `true` |
+| `formatted` | bool | **Back-compat**: явный override авто-детекта formatted (раньше — отдельный ключ). Предпочтительно — форма `title: {text, formatted}` |
| `width` | int | Ширина |
| `height` | int | Высота |
| `autoMaxWidth` | bool | Автомаксимальная ширина |