fix(form-decompile,form-compile): dataParameters мульти-value + SpellCheckingOnTextInput

(1) dcsset:dataParameters — параметр с НЕСКОЛЬКИМИ <dcscor:value> (valueListAllowed,
напр. два DesignTimeValue Перечисление.X) — декомпилятор читал ОДНО (SelectSingleNode),
2-е/3-е дропались. Фикс: SelectNodes → массив (декомпилятор) + ветка массива в
Emit-DataParameters (компилятор ps1+py, отдельный <dcscor:value> на каждое значение по типу).
(2) SpellCheckingOnTextInput (input) → GENERIC_SCALARS (обе стороны+py).

Формы Организации/ФормаСписка (dataParameters мульти-DesignTimeValue) + ВводАдреса
(SpellChecking) → match. ps1==py байт-в-байт. Регресс 43/43.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-13 18:07:14 +03:00
parent 9ec5857e22
commit 06331a9b80
3 changed files with 36 additions and 7 deletions
@@ -1,4 +1,4 @@
# form-compile v1.169 — Compile 1C managed form from JSON or object metadata
# form-compile v1.170 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[string]$JsonPath,
@@ -3272,6 +3272,7 @@ $script:genericScalars = @(
# Хвост листовых скаляров (по 1 в корпусе): автокоррекция ввода (input) / уникальность команды
# (button) / допуск пустого множ. значения (input) / поведение при гориз. сжатии (table)
@{ Tag='AutoCorrectionOnTextInput'; Key='autoCorrectionOnTextInput'; Kind='value' }
@{ Tag='SpellCheckingOnTextInput'; Key='spellCheckingOnTextInput'; Kind='value' }
@{ Tag='CommandUniqueness'; Key='commandUniqueness'; Kind='bool' }
@{ Tag='AllowInputEmptyMultipleValues';Key='allowInputEmptyMultipleValues';Kind='bool' }
@{ Tag='BehaviorOnHorizontalCompression'; Key='behaviorOnHorizontalCompression'; Kind='value' }
@@ -5407,7 +5408,17 @@ function Emit-DataParameters {
X "$indent`t<dcscor:item xsi:type=`"dcsset:SettingsParameterValue`">"
if ($dp.use -eq $false) { X "$indent`t`t<dcscor:use>false</dcscor:use>" }
X "$indent`t`t<dcscor:parameter>$(Esc-Xml "$($dp.parameter)")</dcscor:parameter>"
if ($dp.nilValue -eq $true) {
$dpValIsArr = ($dp.value -is [array]) -or ($dp.value -is [System.Collections.IList] -and $dp.value -isnot [string])
if ($dpValIsArr) {
# Список значений параметра (valueListAllowed) — отдельный <dcscor:value> на каждое.
$avtype = "$($dp.valueType)"
foreach ($v in @($dp.value)) {
$vStr = if ($v -is [bool]) { "$v".ToLower() } else { "$v" }
if ($avtype -match '^[a-zA-Z]+:') { X "$indent`t`t<dcscor:value xsi:type=`"$avtype`">$(Esc-Xml $vStr)</dcscor:value>" }
elseif ("$vStr" -match '^(ПланСчетов|Справочник|Перечисление|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена)\.' -or "$vStr" -match '^(ChartOfAccounts|Catalog|Enum|Document|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.') { X "$indent`t`t<dcscor:value xsi:type=`"dcscor:DesignTimeValue`">$(Esc-Xml $vStr)</dcscor:value>" }
else { X "$indent`t`t<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml $vStr)</dcscor:value>" }
}
} elseif ($dp.nilValue -eq $true) {
X "$indent`t`t<dcscor:value xsi:nil=`"true`"/>"
} elseif ((Test-EmptyValue $dp.value) -and $dp.valueType) {
# Явный типизированный пустой (xs:string-плейсхолдер и т.п.)
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# form-compile v1.169 — Compile 1C managed form from JSON or object metadata
# form-compile v1.170 — Compile 1C managed form from JSON or object metadata
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
import copy
@@ -3393,6 +3393,7 @@ GENERIC_SCALARS = [
('MultipleValuePictureDataPath', 'multipleValuePictureDataPath', 'value'),
# Хвост листовых скаляров (по 1): автокоррекция / уникальность команды / пустое множ.значение / гориз.сжатие
('AutoCorrectionOnTextInput', 'autoCorrectionOnTextInput', 'value'),
('SpellCheckingOnTextInput', 'spellCheckingOnTextInput', 'value'),
('CommandUniqueness', 'commandUniqueness', 'bool'),
('AllowInputEmptyMultipleValues', 'allowInputEmptyMultipleValues', 'bool'),
('BehaviorOnHorizontalCompression', 'behaviorOnHorizontalCompression', 'value'),
@@ -5174,7 +5175,18 @@ def emit_data_parameters(lines, items, indent, block_view_mode=None):
lines.append(f'{indent}\t\t<dcscor:parameter>{esc_xml(str(dp.get("parameter", "")))}</dcscor:parameter>')
vtype = str(dp.get('valueType') or '')
val = dp.get('value')
if dp.get('nilValue') is True:
if isinstance(val, list):
# Список значений параметра (valueListAllowed) — отдельный <dcscor:value> на каждое.
avtype = str(dp.get('valueType', ''))
for v in val:
v_str = ('true' if v else 'false') if isinstance(v, bool) else str(v)
if re.match(r'^[a-zA-Z]+:', avtype):
lines.append(f'{indent}\t\t<dcscor:value xsi:type="{avtype}">{esc_xml(v_str)}</dcscor:value>')
elif re.match(r'^(ПланСчетов|Справочник|Перечисление|Документ|ПланВидовХарактеристик|ПланВидовРасчета|БизнесПроцесс|Задача|РегистрСведений|ПланОбмена)\.', v_str) or re.match(r'^(ChartOfAccounts|Catalog|Enum|Document|ChartOfCharacteristicTypes|ChartOfCalculationTypes|BusinessProcess|Task|InformationRegister|ExchangePlan)\.', v_str):
lines.append(f'{indent}\t\t<dcscor:value xsi:type="dcscor:DesignTimeValue">{esc_xml(v_str)}</dcscor:value>')
else:
lines.append(f'{indent}\t\t<dcscor:value xsi:type="xs:string">{esc_xml(v_str)}</dcscor:value>')
elif dp.get('nilValue') is True:
lines.append(f'{indent}\t\t<dcscor:value xsi:nil="true"/>')
elif _test_empty_value(val) and vtype:
emit_empty_value(lines, vtype, f'{indent}\t\t', tag_prefix='dcscor:', value_list_allowed=False)
@@ -1,4 +1,4 @@
# form-decompile v0.145 — Decompile 1C managed Form.xml to JSON DSL (draft)
# form-decompile v0.146 — Decompile 1C managed Form.xml to JSON DSL (draft)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
param(
@@ -1441,13 +1441,18 @@ function Build-FormDataParameters {
foreach ($it in @($dpNode.SelectNodes("dcscor:item", $ns))) {
$pn = Get-Text $it "dcscor:parameter"
$use = Get-Text $it "dcscor:use"
$valNode = $it.SelectSingleNode("dcscor:value", $ns)
$valNodes = @($it.SelectNodes("dcscor:value", $ns))
$valNode = if ($valNodes.Count -ge 1) { $valNodes[0] } else { $null }
$usidN = $it.SelectSingleNode("dcsset:userSettingID", $ns)
$vmN = $it.SelectSingleNode("dcsset:viewMode", $ns)
$uspN = $it.SelectSingleNode("dcsset:userSettingPresentation", $ns)
if ($valNode -or $usidN -or $vmN -or $uspN) {
$obj = [ordered]@{ parameter = $pn }
if ($valNode) {
if ($valNodes.Count -gt 1) {
# Список значений параметра (valueListAllowed) — захватываем ВСЕ <dcscor:value> массивом
$obj['value'] = @($valNodes | ForEach-Object { $_.InnerText })
$vt0 = $valNodes[0].GetAttribute("type", $NS_XSI); if ($vt0) { $obj['valueType'] = $vt0 }
} elseif ($valNode) {
if ($valNode.GetAttribute("nil", $NS_XSI) -eq 'true') { $obj['nilValue'] = $true }
else {
$vType = $valNode.GetAttribute("type", $NS_XSI); $vVal = $valNode.InnerText
@@ -1640,6 +1645,7 @@ $GENERIC_SCALARS = @(
@{ Tag='MultipleValuePictureDataPath'; Key='multipleValuePictureDataPath'; Kind='value' }
# Хвост листовых скаляров (по 1): автокоррекция / уникальность команды / пустое множ.значение / гориз.сжатие
@{ Tag='AutoCorrectionOnTextInput'; Key='autoCorrectionOnTextInput'; Kind='value' }
@{ Tag='SpellCheckingOnTextInput'; Key='spellCheckingOnTextInput'; Kind='value' }
@{ Tag='CommandUniqueness'; Key='commandUniqueness'; Kind='bool' }
@{ Tag='AllowInputEmptyMultipleValues'; Key='allowInputEmptyMultipleValues'; Kind='bool' }
@{ Tag='BehaviorOnHorizontalCompression'; Key='behaviorOnHorizontalCompression'; Kind='value' }