diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1
index 040b2367..6aac38b0 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.33 — Compile 1C managed form from JSON or object metadata
+# form-compile v1.34 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[string]$JsonPath,
@@ -2551,6 +2551,7 @@ function Emit-LabelField {
Emit-Title -el $el -name $name -indent $inner -auto:(-not $el.path)
Emit-CommonFlags -el $el -indent $inner
+ if ($el.titleLocation) { X "$inner$(Map-TitleLoc "$($el.titleLocation)")" }
if ($el.editMode) { X "$inner$($el.editMode)" }
# ВНИМАНИЕ: у LabelField платформенный тег именно (опечатка 1С), не .
if ($el.hyperlink -eq $true) { X "$innertrue" }
@@ -2579,6 +2580,7 @@ function Emit-Table {
if ($el.representation) {
X "$inner$($el.representation)"
}
+ if ($el.titleLocation) { X "$inner$(Map-TitleLoc "$($el.titleLocation)")" }
if ($el.changeRowSet -eq $true) { X "$innertrue" }
if ($el.changeRowOrder -eq $true) { X "$innertrue" }
if ($el.height) { X "$inner$($el.height)" }
@@ -2833,6 +2835,8 @@ function Emit-PictureField {
Emit-Title -el $el -name $name -indent $inner
Emit-CommonFlags -el $el -indent $inner
+ if ($el.titleLocation) { X "$inner$(Map-TitleLoc "$($el.titleLocation)")" }
+
# ValuesPicture — picture (collection) used to render the field's value.
# Required for a Boolean-bound PictureField to actually show an icon.
# loadTransparent emitted only when true (1С default is false).
diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py
index 7f8f86d8..9dd3a3ac 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.33 — Compile 1C managed form from JSON or object metadata
+# form-compile v1.34 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import copy
@@ -2199,6 +2199,8 @@ def emit_label_field(lines, el, name, eid, indent):
emit_title(lines, el, name, inner, auto=not el.get('path'))
emit_common_flags(lines, el, inner)
+ if el.get('titleLocation'):
+ lines.append(f'{inner}{map_title_loc(el["titleLocation"])}')
if el.get('editMode'):
lines.append(f'{inner}{el["editMode"]}')
# ВНИМАНИЕ: у LabelField платформенный тег (опечатка 1С), не .
@@ -2227,6 +2229,8 @@ def emit_table(lines, el, name, eid, indent):
if el.get('representation'):
lines.append(f'{inner}{el["representation"]}')
+ if el.get('titleLocation'):
+ lines.append(f'{inner}{map_title_loc(el["titleLocation"])}')
if el.get('changeRowSet') is True:
lines.append(f'{inner}true')
if el.get('changeRowOrder') is True:
@@ -2465,6 +2469,9 @@ def emit_picture_field(lines, el, name, eid, indent):
emit_title(lines, el, name, inner)
emit_common_flags(lines, el, inner)
+ if el.get('titleLocation'):
+ lines.append(f'{inner}{map_title_loc(el["titleLocation"])}')
+
# ValuesPicture \u2014 picture (collection) used to render the field's value.
# Required for a Boolean-bound PictureField to actually show an icon.
# loadTransparent emitted only when true (1\u0421 default is false).
diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1
index 309a93de..bc4c36cc 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.13 — Decompile 1C managed Form.xml to JSON DSL (draft)
+# form-decompile v0.14 — Decompile 1C managed Form.xml to JSON DSL (draft)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
param(
@@ -401,6 +401,7 @@ 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() }
$em = Get-Child $node 'EditMode'; if ($em) { $obj['editMode'] = $em }
# LabelField: тег (опечатка платформы), не
if ((Get-Child $node 'Hiperlink') -eq 'true') { $obj['hyperlink'] = $true }
@@ -416,6 +417,7 @@ 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() }
$ref = $node.SelectSingleNode("lf:ValuesPicture/xr:Ref", $ns); if ($ref) { $obj['valuesPicture'] = $ref.InnerText }
}
'CalendarField' {
@@ -433,6 +435,7 @@ 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() }
$rep = Get-Child $node 'Representation'; if ($rep) { $obj['representation'] = $rep }
if ((Get-Child $node 'ChangeRowSet') -eq 'true') { $obj['changeRowSet'] = $true }
if ((Get-Child $node 'ChangeRowOrder') -eq 'true') { $obj['changeRowOrder'] = $true }
diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md
index 793924fd..e4b8820a 100644
--- a/docs/form-dsl-spec.md
+++ b/docs/form-dsl-spec.md
@@ -115,6 +115,7 @@
| `disabled` | bool | `true` → `false` |
| `readOnly` | bool | `true` → `true` |
| `events` | object | Обработчики событий: `{ "ИмяСобытия": "ИмяОбработчика" }` — тот же формат, что у событий формы (§3). Значение `null` → имя по конвенции (§4.2). См. §4.2 |
+| `titleLocation` | string | Расположение заголовка: `none`/`left`/`right`/`top`/`bottom`/`auto`. Эмитится при наличии (input, labelField, picField, table, calendar). У `check`/`radio` — особая семантика с умным дефолтом (см. их разделы) |
### 4.1a. Общие layout-свойства
diff --git a/tests/skills/cases/form-compile/input-fields.json b/tests/skills/cases/form-compile/input-fields.json
index 86bcfaf3..1a7ecb3c 100644
--- a/tests/skills/cases/form-compile/input-fields.json
+++ b/tests/skills/cases/form-compile/input-fields.json
@@ -17,7 +17,7 @@
"title": "Поля ввода",
"elements": [
{ "input": "ОбычноеПоле", "path": "ОбычноеПоле", "title": "Обычное поле", "editMode": "EnterOnInput" },
- { "labelField": "Ссылка", "path": "ОбычноеПоле", "hyperlink": true },
+ { "labelField": "Ссылка", "path": "ОбычноеПоле", "titleLocation": "left", "hyperlink": true },
{ "input": "МногострочноеПоле", "path": "МногострочноеПоле", "multiLine": true, "height": 5, "title": "Комментарий" },
{ "input": "ПолеПароля", "path": "ПолеПароля", "passwordMode": true, "title": "Пароль" },
{ "input": "ПолеСКнопками", "path": "ПолеСКнопками", "choiceButton": true, "clearButton": true, "title": "Выбор" },
diff --git a/tests/skills/cases/form-compile/picture-field.json b/tests/skills/cases/form-compile/picture-field.json
index 1352ed49..b84f89e9 100644
--- a/tests/skills/cases/form-compile/picture-field.json
+++ b/tests/skills/cases/form-compile/picture-field.json
@@ -20,7 +20,7 @@
"on": ["Selection"], "handlers": { "Selection": "ТаблицаДанныхВыбор" },
"columns": [
{ "input": "ТаблицаДанныхНоменклатура", "path": "ТаблицаДанных.Номенклатура" },
- { "picField": "ТаблицаДанныхКартинка", "path": "ТаблицаДанных.Картинка", "valuesPicture": "StdPicture.Favorites", "loadTransparent": true },
+ { "picField": "ТаблицаДанныхКартинка", "path": "ТаблицаДанных.Картинка", "titleLocation": "none", "valuesPicture": "StdPicture.Favorites", "loadTransparent": true },
{ "check": "ТаблицаДанныхКартинкаФлаг", "path": "ТаблицаДанных.Картинка", "title": "Флаг" }
]}
],
diff --git a/tests/skills/cases/form-compile/snapshots/input-fields/DataProcessors/ПоляВвода/Forms/Форма/Ext/Form.xml b/tests/skills/cases/form-compile/snapshots/input-fields/DataProcessors/ПоляВвода/Forms/Форма/Ext/Form.xml
index 9d975018..c8742959 100644
--- a/tests/skills/cases/form-compile/snapshots/input-fields/DataProcessors/ПоляВвода/Forms/Форма/Ext/Form.xml
+++ b/tests/skills/cases/form-compile/snapshots/input-fields/DataProcessors/ПоляВвода/Forms/Форма/Ext/Form.xml
@@ -23,6 +23,7 @@
ОбычноеПоле
+ Left
true
diff --git a/tests/skills/cases/form-compile/snapshots/picture-field/DataProcessors/КартинкаВСтроке/Forms/Форма/Ext/Form.xml b/tests/skills/cases/form-compile/snapshots/picture-field/DataProcessors/КартинкаВСтроке/Forms/Форма/Ext/Form.xml
index 31c545ce..7abc74ff 100644
--- a/tests/skills/cases/form-compile/snapshots/picture-field/DataProcessors/КартинкаВСтроке/Forms/Форма/Ext/Form.xml
+++ b/tests/skills/cases/form-compile/snapshots/picture-field/DataProcessors/КартинкаВСтроке/Forms/Форма/Ext/Form.xml
@@ -45,6 +45,7 @@
ТаблицаДанных.Картинка
+ None
StdPicture.Favorites
true
diff --git a/tests/skills/cases/form-compile/snapshots/table/DataProcessors/Таблица/Forms/Форма/Ext/Form.xml b/tests/skills/cases/form-compile/snapshots/table/DataProcessors/Таблица/Forms/Форма/Ext/Form.xml
index eaa9d72e..5c3bd19c 100644
--- a/tests/skills/cases/form-compile/snapshots/table/DataProcessors/Таблица/Forms/Форма/Ext/Form.xml
+++ b/tests/skills/cases/form-compile/snapshots/table/DataProcessors/Таблица/Forms/Форма/Ext/Form.xml
@@ -11,6 +11,7 @@
Данные
+ Top
true
None
None
diff --git a/tests/skills/cases/form-compile/table.json b/tests/skills/cases/form-compile/table.json
index 4ceea0b7..311d81f7 100644
--- a/tests/skills/cases/form-compile/table.json
+++ b/tests/skills/cases/form-compile/table.json
@@ -16,7 +16,7 @@
"input": {
"title": "Просмотр данных",
"elements": [
- { "table": "Данные", "path": "Данные", "changeRowSet": true,
+ { "table": "Данные", "path": "Данные", "changeRowSet": true, "titleLocation": "top",
"viewStatusLocation": "None", "searchControlLocation": "None",
"excludedCommands": ["Add", "Delete", "MoveUp", "MoveDown"], "columns": [
{ "input": "Дата", "path": "Данные.Дата" },