diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index 1d12b1b4..fc8df131 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.84 — Compile 1C managed form from JSON or object metadata +# form-compile v1.86 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -380,10 +380,9 @@ function New-FieldElement { $el = [ordered]@{ $elType = $attrName; path = $dataPath } - # Apply ref defaults - if ($isRef -and $fieldDefaults -and $fieldDefaults.ref) { - if ($fieldDefaults.ref.choiceButton -eq $true) { $el["choiceButton"] = $true } - } + # (ChoiceButton у ref-полей платформа выводит сама; компилятор эмитит true по StartChoice-эвристике. + # Явный choiceButton из декомпиляции эмитится verbatim. Дефолт-«true» здесь НЕ ставим, чтобы + # from-object вывод совпадал с сертифицированным и не плодил ChoiceButton на каждом ref-поле.) # Extra props if ($extraProps) { @@ -2527,6 +2526,20 @@ function Emit-Element { } } + # Синонимы ключей-свойств (русские имена 1С → канон. англ.). Case/space-insensitive. + # Канон побеждает: если задан и русский, и англ. ключ — англ. остаётся, русский отбрасываем. + foreach ($pn in @($el.PSObject.Properties.Name)) { + $norm = ($pn -replace '\s','').ToLower() + $canon = $script:propSynonyms[$norm] + if ($canon -and $pn -ne $canon) { + if ($null -eq $el.PSObject.Properties[$canon]) { + $val = $el.($pn) + $el | Add-Member -NotePropertyName $canon -NotePropertyValue $val -Force + } + $el.PSObject.Properties.Remove($pn) | Out-Null + } + } + # Determine element type from key $typeKey = $null $xmlTag = $null @@ -2614,12 +2627,18 @@ function Emit-Element { # generic-скаляры (pass-through) + точечные "verticalAlign"=1;"throughAlign"=1;"enableContentChange"=1;"pictureSize"=1;"titleHeight"=1 "childItemsWidth"=1;"showLeftMargin"=1;"cellHyperlink"=1;"viewMode"=1;"verticalScrollBar"=1 - "rowInputMode"=1;"mask"=1;"createButton"=1 + "rowInputMode"=1;"mask"=1;"createButton"=1;"fixingInTable"=1 + # InputField choice-скаляры + "choiceListButton"=1;"quickChoice"=1;"autoChoiceIncomplete"=1 + "choiceForm"=1;"choiceHistoryOnInput"=1;"footerDataPath"=1 + # Button — пометка toggle-кнопки (ключ 'checked', не 'check' — во избежание конфликта с типом) + "checked"=1 } # Оформление (цвета/шрифты/граница) — авто-регистрация из самих структур, чтобы allowlist # не дрейфовал при добавлении новых ключей/синонимов. Канонические + forgiving-синонимы. foreach ($k in $script:appearanceSpec.Keys) { $knownKeys[$k] = 1 } foreach ($k in $script:appearanceSynonyms.Keys) { $knownKeys[$k] = 1 } + foreach ($k in $script:propSynonyms.Keys) { $knownKeys[$k] = 1 } foreach ($p in $el.PSObject.Properties) { if ($p.Name -like '_*') { continue } # внутренние маркеры (напр. _dynList) if (-not $knownKeys.ContainsKey($p.Name)) { @@ -2782,6 +2801,22 @@ $script:appearanceSynonyms = @{ 'цветтекстаподвала'='footerTextColor'; 'цветфонаподвала'='footerBackColor'; 'шрифтподвала'='footerFont' 'шрифт'='font'; 'рамка'='border' } +# Синонимы ключей-свойств: русские имена свойств 1С (как в Конфигураторе) → канон. англ. ключ. +# Ключи карты нормализованы (lowercase, без пробелов); сопоставление в Normalize-PropSynonyms тоже. +# Прощающий ввод: модель может писать свойство по-русски. Англ. ключ работает всегда (это доп. слой). +# Видимость/Доступность НЕ включаем — наш hidden/disabled инвертирован, был бы баг семантики. +$script:propSynonyms = @{ + 'пометка'='checked' + 'кнопкавыбора'='choiceButton'; 'кнопкаочистки'='clearButton'; 'кнопкарегулирования'='spinButton' + 'кнопкавыпадающегосписка'='dropListButton'; 'кнопкасписковоговыбора'='choiceListButton' + 'кнопкаоткрытия'='openButton'; 'кнопкапоумолчанию'='defaultButton' + 'быстрыйвыбор'='quickChoice'; 'формавыбора'='choiceForm'; 'историявыборапривводе'='choiceHistoryOnInput' + 'выборгруппиэлементов'='choiceFoldersAndItems'; 'фиксациявтаблице'='fixingInTable' + 'путькданнымподвала'='footerDataPath'; 'автоотметканезаполненного'='markIncomplete' + 'многострочныйрежим'='multiLine'; 'режимпароля'='passwordMode'; 'переноспословам'='wrap' + 'расположениезаголовка'='titleLocation'; 'пропускатьпривводе'='skipOnInput' + 'заголовок'='title'; 'ширина'='width'; 'высота'='height'; 'подсказкаввода'='inputHint' +} # Профили порядка тегов по базовым типам (XSD-последовательность) $script:appOrderField = @('titleTextColor','titleBackColor','titleFont','footerTextColor','footerBackColor','footerFont','textColor','backColor','borderColor','border','font') $script:appOrderDecoration = @('textColor','font','backColor','borderColor','border') @@ -2803,6 +2838,7 @@ $script:genericScalars = @( @{ Tag='RowInputMode'; Key='rowInputMode'; Kind='value' } @{ Tag='Mask'; Key='mask'; Kind='value' } @{ Tag='CreateButton'; Key='createButton'; Kind='bool' } + @{ Tag='FixingInTable'; Key='fixingInTable'; Kind='value' } ) function Emit-GenericScalars { @@ -3107,11 +3143,14 @@ function Emit-Input { if ($el.multiLine -eq $true) { X "$innertrue" } if ($el.passwordMode -eq $true) { X "$innertrue" } - if ($el.choiceButton -eq $false) { X "$innerfalse" } - elseif ($el.choiceButton -eq $true -and (Test-ElementEvent $el 'StartChoice')) { X "$innertrue" } - if ($el.clearButton -eq $true) { X "$innertrue" } - if ($el.spinButton -eq $true) { X "$innertrue" } - if ($el.dropListButton -eq $true) { X "$innertrue" } + # ChoiceButton — захват «как есть» (платформа эмитит явное значение; ref-поля выводят сама, + # декомпилятор фиксирует факт. значение). Нет ключа → не эмитим (не додумываем по событию). + if ($null -ne $el.choiceButton) { X "$inner$(if ($el.choiceButton){'true'}else{'false'})" } + # Кнопки поля ввода — захват «как есть» (платформа эмитит явное значение, в т.ч. false) + if ($null -ne $el.clearButton) { X "$inner$(if ($el.clearButton){'true'}else{'false'})" } + if ($null -ne $el.spinButton) { X "$inner$(if ($el.spinButton){'true'}else{'false'})" } + if ($null -ne $el.dropListButton) { X "$inner$(if ($el.dropListButton){'true'}else{'false'})" } + if ($null -ne $el.choiceListButton) { X "$inner$(if ($el.choiceListButton){'true'}else{'false'})" } if ($el.markIncomplete -eq $true) { X "$innertrue" } if ($el.editMode) { X "$inner$($el.editMode)" } Emit-ColumnPics -el $el -indent $inner @@ -3119,10 +3158,18 @@ function Emit-Input { # InputField-специфичные скаляры (захват «как есть»: платформа эмитит явное не-дефолтное значение) foreach ($p in @( @('wrap','Wrap'), @('openButton','OpenButton'), @('listChoiceMode','ListChoiceMode'), - @('extendedEditMultipleValues','ExtendedEditMultipleValues'), @('chooseType','ChooseType') + @('extendedEditMultipleValues','ExtendedEditMultipleValues'), @('chooseType','ChooseType'), + @('quickChoice','QuickChoice'), @('autoChoiceIncomplete','AutoChoiceIncomplete') )) { if ($null -ne $el.($p[0])) { X "$inner<$($p[1])>$(if ($el.($p[0])){'true'}else{'false'})" } } + # InputField-специфичные value-скаляры + foreach ($p in @( + @('choiceForm','ChoiceForm'), @('choiceHistoryOnInput','ChoiceHistoryOnInput'), + @('choiceFoldersAndItems','ChoiceFoldersAndItems'), @('footerDataPath','FooterDataPath') + )) { + if ($el.($p[0])) { X "$inner<$($p[1])>$(Esc-Xml "$($el.($p[0]))")" } + } if ($el.choiceButtonRepresentation) { X "$inner$($el.choiceButtonRepresentation)" } Emit-Layout -el $el -indent $inner -multiLineDefault ([bool]($el.multiLine -eq $true)) @@ -3935,6 +3982,9 @@ function Emit-Button { Emit-CommonFlags -el $el -indent $inner if ($el.defaultButton -eq $true) { X "$innertrue" } + # Check (пометка toggle-кнопки командной панели) — платформа эмитит только true. + # Ключ 'checked' (не 'check': 'check' — тип-ключ CheckBoxField, был бы конфликт диспетчера типов) + if ($el.checked -eq $true) { X "$innertrue" } # Picture Emit-CommandPicture -pic $el.picture -elemLt $el.loadTransparent -indent $inner diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 055649ad..d25d01b7 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.84 — Compile 1C managed form from JSON or object metadata +# form-compile v1.86 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -357,10 +357,9 @@ def new_field_element(attr_name, data_path, attr_type, field_defaults, extra_pro el[el_type] = attr_name el['path'] = data_path - # Apply ref defaults - if is_ref and field_defaults and field_defaults.get('ref'): - if field_defaults['ref'].get('choiceButton') is True: - el['choiceButton'] = True + # (ChoiceButton у ref-полей платформа выводит сама; компилятор эмитит true по StartChoice-эвристике. + # Явный choiceButton из декомпиляции эмитится verbatim. Дефолт-«true» здесь НЕ ставим, чтобы + # from-object вывод совпадал с сертифицированным и не плодил ChoiceButton на каждом ref-поле.) # Extra props if extra_props: @@ -1816,7 +1815,12 @@ KNOWN_KEYS = { # generic-скаляры (pass-through) "verticalAlign", "throughAlign", "enableContentChange", "pictureSize", "titleHeight", "childItemsWidth", "showLeftMargin", "cellHyperlink", "viewMode", "verticalScrollBar", - "rowInputMode", "mask", "createButton", + "rowInputMode", "mask", "createButton", "fixingInTable", + # InputField choice-скаляры + "choiceListButton", "quickChoice", "autoChoiceIncomplete", + "choiceForm", "choiceHistoryOnInput", "footerDataPath", + # Button — пометка toggle-кнопки + "checked", } # picture/picField — НИЗКИЙ приоритет: 'picture' это и тип (PictureDecoration), и свойство-иконка @@ -2588,7 +2592,22 @@ APPEARANCE_SYNONYMS = { 'цветтекстаподвала': 'footerTextColor', 'цветфонаподвала': 'footerBackColor', 'шрифтподвала': 'footerFont', 'шрифт': 'font', 'рамка': 'border', } -APP_ORDER_FIELD = ['titleTextColor', 'titleBackColor', 'titleFont', 'footerTextColor', 'footerBackColor', 'footerFont', 'textColor', 'backColor', 'borderColor', 'border', 'font'] +# Синонимы ключей-свойств: русские имена свойств 1С (как в Конфигураторе) → канон. англ. ключ. +# Ключи нормализованы (lowercase, без пробелов); сопоставление в emit_element тоже. Англ. ключ +# работает всегда (доп. слой прощающего ввода). Видимость/Доступность НЕ включаем (hidden/disabled инвертирован). +PROP_SYNONYMS = { + 'пометка': 'checked', + 'кнопкавыбора': 'choiceButton', 'кнопкаочистки': 'clearButton', 'кнопкарегулирования': 'spinButton', + 'кнопкавыпадающегосписка': 'dropListButton', 'кнопкасписковоговыбора': 'choiceListButton', + 'кнопкаоткрытия': 'openButton', 'кнопкапоумолчанию': 'defaultButton', + 'быстрыйвыбор': 'quickChoice', 'формавыбора': 'choiceForm', 'историявыборапривводе': 'choiceHistoryOnInput', + 'выборгруппиэлементов': 'choiceFoldersAndItems', 'фиксациявтаблице': 'fixingInTable', + 'путькданнымподвала': 'footerDataPath', 'автоотметканезаполненного': 'markIncomplete', + 'многострочныйрежим': 'multiLine', 'режимпароля': 'passwordMode', 'переноспословам': 'wrap', + 'расположениезаголовка': 'titleLocation', 'пропускатьпривводе': 'skipOnInput', + 'заголовок': 'title', 'ширина': 'width', 'высота': 'height', 'подсказкаввода': 'inputHint', +} +APP_ORDER_FIELD =['titleTextColor', 'titleBackColor', 'titleFont', 'footerTextColor', 'footerBackColor', 'footerFont', 'textColor', 'backColor', 'borderColor', 'border', 'font'] APP_ORDER_DECORATION = ['textColor', 'font', 'backColor', 'borderColor', 'border'] APP_ORDER_BUTTON = ['textColor', 'backColor', 'borderColor', 'font'] @@ -2668,6 +2687,7 @@ GENERIC_SCALARS = [ ('RowInputMode', 'rowInputMode', 'value'), ('Mask', 'mask', 'value'), ('CreateButton', 'createButton', 'bool'), + ('FixingInTable', 'fixingInTable', 'value'), ] @@ -2985,6 +3005,16 @@ def emit_element(lines, el, indent, in_cmd_bar=False): continue el[dst] = el.pop(src) + # Синонимы ключей-свойств (русские имена 1С → канон. англ.). Case/space-insensitive. + # Канон побеждает: если задан и русский, и англ. ключ — англ. остаётся, русский отбрасываем. + for p_name in list(el.keys()): + norm = p_name.replace(' ', '').lower() + canon = PROP_SYNONYMS.get(norm) + if canon and p_name != canon: + val = el.pop(p_name) + if canon not in el: + el[canon] = val + type_key = None for key in TYPE_KEYS: if el.get(key) is not None: @@ -3165,16 +3195,19 @@ def emit_input(lines, el, name, eid, indent): lines.append(f'{inner}true') if el.get('passwordMode') is True: lines.append(f'{inner}true') - if el.get('choiceButton') is False: - lines.append(f'{inner}false') - elif el.get('choiceButton') is True and test_element_event(el, 'StartChoice'): - lines.append(f'{inner}true') - if el.get('clearButton') is True: - lines.append(f'{inner}true') - if el.get('spinButton') is True: - lines.append(f'{inner}true') - if el.get('dropListButton') is True: - lines.append(f'{inner}true') + # ChoiceButton — захват «как есть» (платформа эмитит явное значение; ref-поля выводят сама, + # декомпилятор фиксирует факт. значение). Нет ключа → не эмитим (не додумываем по событию). + if el.get('choiceButton') is not None: + lines.append(f'{inner}{"true" if el["choiceButton"] else "false"}') + # Кнопки поля ввода — захват «как есть» (платформа эмитит явное значение, в т.ч. false) + if el.get('clearButton') is not None: + lines.append(f'{inner}{"true" if el["clearButton"] else "false"}') + if el.get('spinButton') is not None: + lines.append(f'{inner}{"true" if el["spinButton"] else "false"}') + if el.get('dropListButton') is not None: + lines.append(f'{inner}{"true" if el["dropListButton"] else "false"}') + if el.get('choiceListButton') is not None: + lines.append(f'{inner}{"true" if el["choiceListButton"] else "false"}') if el.get('markIncomplete') is True: lines.append(f'{inner}true') if el.get('editMode'): @@ -3184,9 +3217,15 @@ def emit_input(lines, el, name, eid, indent): lines.append(f'{inner}false') # InputField-специфичные скаляры (захват «как есть»: платформа эмитит явное не-дефолтное значение) for key, tag in (('wrap', 'Wrap'), ('openButton', 'OpenButton'), ('listChoiceMode', 'ListChoiceMode'), - ('extendedEditMultipleValues', 'ExtendedEditMultipleValues'), ('chooseType', 'ChooseType')): + ('extendedEditMultipleValues', 'ExtendedEditMultipleValues'), ('chooseType', 'ChooseType'), + ('quickChoice', 'QuickChoice'), ('autoChoiceIncomplete', 'AutoChoiceIncomplete')): if el.get(key) is not None: lines.append(f'{inner}<{tag}>{"true" if el[key] else "false"}') + # InputField-специфичные value-скаляры + for key, tag in (('choiceForm', 'ChoiceForm'), ('choiceHistoryOnInput', 'ChoiceHistoryOnInput'), + ('choiceFoldersAndItems', 'ChoiceFoldersAndItems'), ('footerDataPath', 'FooterDataPath')): + if el.get(key): + lines.append(f'{inner}<{tag}>{esc_xml(str(el[key]))}') if el.get('choiceButtonRepresentation'): lines.append(f'{inner}{el["choiceButtonRepresentation"]}') emit_layout(lines, el, inner, multi_line_default=(el.get('multiLine') is True)) @@ -3636,6 +3675,10 @@ def emit_button(lines, el, name, eid, indent, in_cmd_bar=False): if el.get('defaultButton') is True: lines.append(f'{inner}true') + # Check (пометка toggle-кнопки командной панели) — платформа эмитит только true. + # Ключ 'checked' (не 'check': 'check' — тип-ключ CheckBoxField, был бы конфликт диспетчера типов) + if el.get('checked') is True: + lines.append(f'{inner}true') # Picture emit_command_picture(lines, el.get('picture'), el.get('loadTransparent'), inner) diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index 8b12f590..cfda5071 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.61 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.62 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( @@ -1135,6 +1135,7 @@ $GENERIC_SCALARS = @( @{ Tag='RowInputMode'; Key='rowInputMode'; Kind='value' } @{ Tag='Mask'; Key='mask'; Kind='value' } @{ Tag='CreateButton'; Key='createButton'; Kind='bool' } + @{ Tag='FixingInTable'; Key='fixingInTable'; Kind='value' } ) # Захват generic-скаляров. Специфичная обработка (если ключ уже задан) — побеждает. @@ -1376,13 +1377,17 @@ function Decompile-Element { $em = Get-Child $node 'EditMode'; if ($em) { $obj['editMode'] = $em } $tl = Get-Child $node 'TitleLocation'; if ($tl) { $obj['titleLocation'] = $tl.ToLower() } $ih = $node.SelectSingleNode("lf:InputHint", $ns); if ($ih) { $t = Get-LangText $ih; if ($t) { $obj['inputHint'] = $t } } - foreach ($p in @('ChoiceButton','ClearButton','SpinButton','DropListButton')) { + foreach ($p in @('ChoiceButton','ClearButton','SpinButton','DropListButton','ChoiceListButton')) { $v = Get-Child $node $p; if ($null -ne $v) { $obj[($p.Substring(0,1).ToLower()+$p.Substring(1))] = (To-Bool $v) } } - # InputField-специфичные скаляры (захват «как есть») - foreach ($p in @('Wrap','OpenButton','ListChoiceMode','ExtendedEditMultipleValues','ChooseType')) { + # InputField-специфичные bool-скаляры (захват «как есть») + foreach ($p in @('Wrap','OpenButton','ListChoiceMode','ExtendedEditMultipleValues','ChooseType','QuickChoice','AutoChoiceIncomplete')) { $v = Get-Child $node $p; if ($null -ne $v) { $obj[($p.Substring(0,1).ToLower()+$p.Substring(1))] = (To-Bool $v) } } + # InputField-специфичные value-скаляры (захват «как есть») + foreach ($p in @('ChoiceForm','ChoiceHistoryOnInput','ChoiceFoldersAndItems','FooterDataPath')) { + $v = Get-Child $node $p; if ($null -ne $v) { $obj[($p.Substring(0,1).ToLower()+$p.Substring(1))] = $v } + } $cbr = Get-Child $node 'ChoiceButtonRepresentation'; if ($cbr) { $obj['choiceButtonRepresentation'] = $cbr } if ((Get-Child $node 'TextEdit') -eq 'false') { $obj['textEdit'] = $false } $cl = Decompile-ChoiceList $node; if ($cl) { $obj['choiceList'] = $cl } @@ -1554,6 +1559,7 @@ function Decompile-Element { $type = Get-Child $node 'Type' if ($type) { $tmap=@{'CommandBarButton'='commandBar';'UsualButton'='usual';'Hyperlink'='hyperlink';'CommandBarHyperlink'='hyperlink'}; if ($tmap.ContainsKey($type)) { $obj['type']=$tmap[$type] } else { $obj['type']=$type } } if ((Get-Child $node 'DefaultButton') -eq 'true') { $obj['defaultButton'] = $true } + if ((Get-Child $node 'Check') -eq 'true') { $obj['checked'] = $true } $ref = $node.SelectSingleNode("lf:Picture/xr:Ref", $ns); if ($ref) { $obj['picture'] = $ref.InnerText } # Дефолт у picture кнопки/попапа = true → фиксируем только отклонение false (true опускаем) $lt = $node.SelectSingleNode("lf:Picture/xr:LoadTransparent", $ns); if ($lt -and $lt.InnerText -eq 'false') { $obj['loadTransparent'] = $false } diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md index 7e867481..6b49e2a6 100644 --- a/docs/form-dsl-spec.md +++ b/docs/form-dsl-spec.md @@ -135,6 +135,10 @@ Флаг авто-детектится по наличию известной разметки/``: для plain-строки объект не нужен. Явная форма `{text, formatted}` — только когда авто-детект неверен (formatted-текст без разметки, либо буквальные `<…>`-плейсхолдеры в неформатированном). +#### Русские синонимы ключей-свойств (прощающий ввод) + +Скалярные свойства элементов можно писать русскими именами 1С (как в Конфигураторе) — компилятор молча нормализует их в канонические англ. ключи. Сопоставление **регистро- и пробело-независимое** (`Пометка` = `пометка`, `Быстрый выбор` = `быстрыйВыбор`). Англ. ключ работает всегда; если заданы оба — побеждает англ. Поддержаны (в т.ч.): `Пометка`→`checked`, `Заголовок`→`title`, `Ширина`→`width`, `Высота`→`height`, `КнопкаВыбора`→`choiceButton`, `КнопкаОчистки`→`clearButton`, `КнопкаВыпадающегоСписка`→`dropListButton`, `КнопкаСписковогоВыбора`→`choiceListButton`, `БыстрыйВыбор`→`quickChoice`, `ФормаВыбора`→`choiceForm`, `ИсторияВыбораПриВводе`→`choiceHistoryOnInput`, `ВыборГруппИЭлементов`→`choiceFoldersAndItems`, `ФиксацияВТаблице`→`fixingInTable`, `ПутьКДаннымПодвала`→`footerDataPath`, `МногострочныйРежим`→`multiLine`, `РежимПароля`→`passwordMode`, `РасположениеЗаголовка`→`titleLocation`. (`Видимость`/`Доступность` НЕ синонимы — у нас `hidden`/`disabled` с обратной полярностью.) Оформление имеет свой набор рус. синонимов (§4.1e). + ### 4.1c. Доступ по ролям (`userVisible` / `view` / `edit` / `use`) Единый механизм платформы (role-adjustable boolean): «общее значение + исключения по ролям». @@ -373,6 +377,14 @@ companion-панели с собственным контентом. Оба не | `listChoiceMode` | bool | Режим выбора из списка (``) | | `extendedEditMultipleValues` | bool | Расширенное редактирование нескольких значений | | `chooseType` | bool | Выбор типа (``) | +| `choiceListButton` | bool | Кнопка списочного выбора (``) | +| `quickChoice` | bool | Быстрый выбор (``) | +| `autoChoiceIncomplete` | bool | Автоматический выбор незаполненного (``) | +| `choiceForm` | string | Форма выбора (``), напр. `Catalog.X.Form.ФормаВыбора` | +| `choiceHistoryOnInput` | string | История выбора при вводе (``): `Auto`, `DontUse` | +| `choiceFoldersAndItems` | string | Выбор групп и элементов (``): `Items`, `Folders`, `FoldersAndItems` | +| `fixingInTable` | string | Фиксация колонки в таблице (``): `Left`, `Right`, `None`. Так же у `labelField` и др. полей | +| `footerDataPath` | string | DataPath подвала колонки таблицы (``) | | `choiceButtonRepresentation` | string | `ShowInInputField`, `ShowInDropList`, `ShowInDropListAndInInputField` | | `width` | int | Ширина | | `height` | int | Высота | @@ -623,6 +635,7 @@ Pages поддерживает `pagesRepresentation`: `None`, `TabsOnTop`, `Tabs | `stdCommand` | string | Стандартная команда (→ `Form.StandardCommand.`; `X.Y` → `Form.Item.X.StandardCommand.Y`) | | `type` | string | `usual`, `hyperlink`, `commandBar` | | `defaultButton` | bool | Кнопка по умолчанию | +| `checked` | bool | Пометка (нажатое состояние toggle-кнопки командной панели) → `true`. Платформа эмитит только `true`. Ключ `checked` (не `check` — `check` — тип-ключ ПоляФлажка) | | `picture` | string \| object | Ссылка на картинку (`StdPicture.Name`). Скаляр-строка ИЛИ объект `{src, loadTransparent}` (прощающий ввод — флаг можно задать прямо в объекте) | | `loadTransparent` | bool | Загружать картинку прозрачной (у `` кнопки/команды/попапа). **Дефолт `true`** (эмитится всегда; `false` — явно). Элемент-уровневый ключ ИЛИ поле объекта `picture`. Также у `command` (§7) и `popup`. ⚠️ Полярность обратна `headerPicture`/`valuesPicture` (там дефолт `false`, см. §4.1) | | `path` | string | DataPath кнопки общей команды (`Объект.Ref`, `Items.X.CurrentData.Поле`) — привязка к контексту | diff --git a/tests/skills/cases/form-compile/input-fields.json b/tests/skills/cases/form-compile/input-fields.json index bfe26a96..6b0e490d 100644 --- a/tests/skills/cases/form-compile/input-fields.json +++ b/tests/skills/cases/form-compile/input-fields.json @@ -20,7 +20,7 @@ { "labelField": "Ссылка", "path": "ОбычноеПоле", "titleLocation": "left", "hyperlink": true, "format": { "ru": "ДЛФ=D", "en": "DLF=D" } }, { "input": "МногострочноеПоле", "path": "МногострочноеПоле", "multiLine": true, "height": 5, "title": "Комментарий", "wrap": false, "showInHeader": false, "showInFooter": false, "autoCellHeight": true, "footerHorizontalAlign": "Right", "openButton": false, "chooseType": false }, { "input": "ПолеПароля", "path": "ПолеПароля", "passwordMode": true, "title": "Пароль" }, - { "input": "ПолеСКнопками", "path": "ПолеСКнопками", "choiceButton": true, "clearButton": true, "title": "Выбор" }, + { "input": "ПолеСКнопками", "path": "ПолеСКнопками", "choiceButton": true, "clearButton": true, "dropListButton": false, "spinButton": true, "choiceListButton": true, "quickChoice": false, "autoChoiceIncomplete": true, "choiceHistoryOnInput": "DontUse", "choiceForm": "DataProcessor.ПоляВвода.Form.Форма", "title": "Выбор" }, { "input": "ПолеСписокВыбора", "path": "ПолеСписокВыбора", "title": "Список выбора", "choiceList": [ { "value": "", "presentation": "Все" }, { "value": "Первый" }, 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 54bac057..cebe81fb 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 @@ -109,7 +109,15 @@ Выбор + true true + true + false + true + false + true + DataProcessor.ПоляВвода.Form.Форма + DontUse diff --git a/tests/skills/cases/form-compile/snapshots/synonyms/DataProcessors/Тест/Forms/Форма/Ext/Form.xml b/tests/skills/cases/form-compile/snapshots/synonyms/DataProcessors/Тест/Forms/Форма/Ext/Form.xml index 5cfbf55b..1f524315 100644 --- a/tests/skills/cases/form-compile/snapshots/synonyms/DataProcessors/Тест/Forms/Форма/Ext/Form.xml +++ b/tests/skills/cases/form-compile/snapshots/synonyms/DataProcessors/Тест/Forms/Форма/Ext/Form.xml @@ -19,6 +19,9 @@ Поле + true + false + 15 @@ -28,6 +31,7 @@ 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 c7fd5f9e..a514ad06 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 @@ -41,6 +41,7 @@ @@ -73,6 +74,7 @@ Данные.Дата + Left diff --git a/tests/skills/cases/form-compile/synonyms.json b/tests/skills/cases/form-compile/synonyms.json index 9cc7c469..e30b1f1c 100644 --- a/tests/skills/cases/form-compile/synonyms.json +++ b/tests/skills/cases/form-compile/synonyms.json @@ -1,5 +1,5 @@ { - "name": "Синонимы commandBar/autoCommandBar нормализуются молча", + "name": "Синонимы commandBar/autoCommandBar + русские имена свойств нормализуются молча", "preRun": [ { "script": "meta-compile/scripts/meta-compile", @@ -23,9 +23,9 @@ { "autoCommandBar": "ФормаКоманднаяПанель", "children": [ { "button": "Кн1", "command": "Кн1" } ]}, - { "input": "Поле", "path": "Поле" }, + { "input": "Поле", "path": "Поле", "КнопкаВыбора": true, "Быстрый выбор": false, "Ширина": 15 }, { "commandBar": "ДопПанель", "children": [ - { "button": "Кн2", "command": "Кн2" } + { "button": "Кн2", "command": "Кн2", "Пометка": true } ]} ], "commands": [ diff --git a/tests/skills/cases/form-compile/table.json b/tests/skills/cases/form-compile/table.json index 8f007f3e..2331a57f 100644 --- a/tests/skills/cases/form-compile/table.json +++ b/tests/skills/cases/form-compile/table.json @@ -20,7 +20,7 @@ "viewStatusLocation": "None", "searchControlLocation": "None", "excludedCommands": ["Add", "Delete", "MoveUp", "MoveDown"], "commandBar": { "autofill": false, "children": [ - { "button": "ПанельОбновить", "command": "Обновить" } + { "button": "ПанельОбновить", "command": "Обновить", "checked": true } ]}, "contextMenu": { "children": [ { "buttonGroup": "МенюГруппа", "children": [ @@ -28,7 +28,7 @@ ]} ]}, "columns": [ - { "input": "Дата", "path": "Данные.Дата" }, + { "input": "Дата", "path": "Данные.Дата", "fixingInTable": "Left" }, { "input": "Сумма", "path": "Данные.Сумма" }, { "input": "Комментарий", "path": "Данные.Комментарий" } ]}