diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1
index c6a145ec..c2b5263b 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.127 — Compile 1C managed form from JSON or object metadata
+# form-compile v1.128 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[string]$JsonPath,
@@ -3640,6 +3640,10 @@ function Emit-Input {
)) {
if ($null -ne $el.($p[0])) { X "$inner<$($p[1])>$(if ($el.($p[0])){'true'}else{'false'})$($p[1])>" }
}
+ # Ограничение доступных типов (поле на составном типе): домен типов + явный набор.
+ # availableTypes — формат типа реквизита (§type); Emit-Type сам разбирает мультитип "a | b".
+ if ($null -ne $el.typeDomainEnabled) { X "$inner$(if ($el.typeDomainEnabled){'true'}else{'false'})" }
+ if ($el.availableTypes) { Emit-Type -typeStr $el.availableTypes -indent $inner -tag 'AvailableTypes' }
# InputField-специфичные value-скаляры
foreach ($p in @(
@('choiceForm','ChoiceForm'), @('choiceHistoryOnInput','ChoiceHistoryOnInput'),
diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py
index b940c055..690edb91 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.127 — Compile 1C managed form from JSON or object metadata
+# form-compile v1.128 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import copy
@@ -3728,6 +3728,12 @@ def emit_input(lines, el, name, eid, indent):
('quickChoice', 'QuickChoice'), ('autoChoiceIncomplete', 'AutoChoiceIncomplete')):
if el.get(key) is not None:
lines.append(f'{inner}<{tag}>{"true" if el[key] else "false"}{tag}>')
+ # Ограничение доступных типов (поле на составном типе): домен типов + явный набор.
+ # availableTypes — формат типа реквизита (§type); emit_type сам разбирает мультитип "a | b".
+ if el.get('typeDomainEnabled') is not None:
+ lines.append(f'{inner}{"true" if el["typeDomainEnabled"] else "false"}')
+ if el.get('availableTypes'):
+ emit_type(lines, el['availableTypes'], inner, tag='AvailableTypes')
# InputField-специфичные value-скаляры
for key, tag in (('choiceForm', 'ChoiceForm'), ('choiceHistoryOnInput', 'ChoiceHistoryOnInput'),
('choiceFoldersAndItems', 'ChoiceFoldersAndItems'), ('footerDataPath', 'FooterDataPath')):
diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1
index bb4919d3..9b8dc107 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 v1.01 — Decompile 1C managed Form.xml to JSON DSL (draft)
+# form-decompile v1.02 — Decompile 1C managed Form.xml to JSON DSL (draft)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
param(
@@ -1651,6 +1651,10 @@ function Decompile-Element {
} else { $obj[$key] = $txt }
}
}
+ # Ограничение доступных типов (поле на составном/характеристика-типе): домен типов + явный набор.
+ # availableTypes — тот же формат типа, что у реквизитов (§type), захват через Decompile-Type.
+ $tde = Get-Child $node 'TypeDomainEnabled'; if ($null -ne $tde) { $obj['typeDomainEnabled'] = (To-Bool $tde) }
+ $atNode = $node.SelectSingleNode("lf:AvailableTypes", $ns); if ($atNode) { $at = Decompile-Type $atNode; if ($at) { $obj['availableTypes'] = $at } }
$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 }
diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md
index d651b4b2..a7e039ad 100644
--- a/docs/form-dsl-spec.md
+++ b/docs/form-dsl-spec.md
@@ -407,6 +407,8 @@ companion-панели с собственным контентом. Оба не
| `choiceFoldersAndItems` | string | Выбор групп и элементов (``): `Items`, `Folders`, `FoldersAndItems` |
| `fixingInTable` | string | Фиксация колонки в таблице (``): `Left`, `Right`, `None`. Так же у `labelField` и др. полей |
| `footerDataPath` | string | DataPath подвала колонки таблицы (``) |
+| `availableTypes` | string | Ограничение доступных типов поля на составном/характеристика-типе (``). Формат типа реквизита (§«Типы»): одиночный (`string`, `CatalogRef.Валюты`) или составной через `\|` (`string \| boolean \| decimal(10,2)`). Редкое (~18 в корпусе, только InputField) |
+| `typeDomainEnabled` | bool | Включён ли домен типов (``); обычно `false` при заданном `availableTypes`. Захват «как есть» |
| `choiceButtonRepresentation` | string | `ShowInInputField`, `ShowInDropList`, `ShowInDropListAndInInputField` |
| `minValue` / `maxValue` | number/string | Мин./макс. значение (``/`` с обязательным `xsi:type`). **JSON-число → `xs:decimal`, строка → `xs:string`** (тип сохраняется декомпилятором через тип JSON-значения) |
| `width` | int | Ширина |
diff --git a/tests/skills/cases/form-compile/input-fields.json b/tests/skills/cases/form-compile/input-fields.json
index 6ad314ab..32da4b8d 100644
--- a/tests/skills/cases/form-compile/input-fields.json
+++ b/tests/skills/cases/form-compile/input-fields.json
@@ -50,7 +50,8 @@
{ "check": "Флаг", "path": "Флаг", "title": "Включено", "warningOnEdit": { "ru": "Изменение флага требует подтверждения", "en": "Confirm flag change" }, "extendedTooltip": { "width": 45 } },
{ "check": "ФлагПлатформенный", "path": "ФлагПлатформенный", "title": "Слева", "titleLocation": "" },
{ "check": "ФлагЯвный", "path": "ФлагЯвный", "title": "Сверху", "titleLocation": "top" },
- { "check": "ФлагТумблер", "path": "ФлагТумблер", "title": "Тумблер", "checkBoxType": "switcher", "format": "БЛ=Нет; БИ=Да" }
+ { "check": "ФлагТумблер", "path": "ФлагТумблер", "title": "Тумблер", "checkBoxType": "switcher", "format": "БЛ=Нет; БИ=Да" },
+ { "input": "ПолеСоставное", "path": "ПолеСоставное", "title": "Ограничение типов", "typeDomainEnabled": false, "availableTypes": "string | boolean" }
],
"attributes": [
{ "name": "Объект", "type": "DataProcessorObject.ПоляВвода", "main": true },
@@ -67,7 +68,8 @@
{ "name": "ФлагЯвный", "type": "boolean" },
{ "name": "ФлагТумблер", "type": "boolean" },
{ "name": "ЧисловоеПоле", "type": "number(10,2)" },
- { "name": "ДатаПоля", "type": "dateTime" }
+ { "name": "ДатаПоля", "type": "dateTime" },
+ { "name": "ПолеСоставное", "type": "string | boolean" }
],
"conditionalAppearance": [
{ "selection": ["ОбычноеПоле"], "filter": ["ЧисловоеПоле > 100"], "appearance": { "ЦветФона": "style:FormBackColor", "Текст": "Плоский текст" },
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 618dfa34..e7ae7804 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
@@ -427,15 +427,35 @@
+
+ ПолеСоставное
+
+
+ ru
+ Ограничение типов
+
+
+ false
+
+ xs:string
+
+ 0
+ Variable
+
+ xs:boolean
+
+
+
+
-
+
cfg:DataProcessorObject.ПоляВвода
true
-
+
ru
@@ -450,7 +470,7 @@
-
+
ru
@@ -465,7 +485,7 @@
-
+
ru
@@ -480,7 +500,7 @@
-
+
ru
@@ -495,7 +515,7 @@
-
+
ru
@@ -510,7 +530,7 @@
-
+
ru
@@ -525,7 +545,7 @@
-
+
ru
@@ -540,7 +560,7 @@
-
+
ru
@@ -555,7 +575,7 @@
-
+
ru
@@ -566,7 +586,7 @@
xs:boolean
-
+
ru
@@ -577,7 +597,7 @@
xs:boolean
-
+
ru
@@ -588,7 +608,7 @@
xs:boolean
-
+
ru
@@ -599,7 +619,7 @@
xs:boolean
-
+
ru
@@ -615,7 +635,7 @@
-
+
ru
@@ -629,6 +649,22 @@
+
+
+
+ ru
+ Поле составное
+
+
+
+ xs:string
+
+ 0
+ Variable
+
+ xs:boolean
+
+