mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-16 15:55:16 +03:00
fix(form-compile): пустая строка-значение self-closing + Enum.X.EmptyRef без EnumValue
Два общих бага value (всплыли на полном прогоне 2.17, чинят и choiceList, и параметры выбора): - Пустое строковое значение эмитилось <Value xsi:type="xs:string"></Value> вместо самозакрывающегося <Value xsi:type="xs:string"/>. Введён хелпер Get-ChoiceValueTag (3 места: choiceList scalar + choiceParam scalar + FixedArray inner). Форма АктивныеПользователи теперь round-trip match. - Enum.X.EmptyRef нормализатор ломал вставкой .EnumValue. → EnumValue.EmptyRef (EmptyRef — пустая ссылка перечисления, не значение). Фикс в Normalize- ChoiceValue (Enum-ветка): EmptyRef сохраняется как есть. Зеркало py. Кейсы: input-fields (пустая строка в choiceList), radio-auto-enum (Enum.X.EmptyRef) — оба сертифицированы загрузкой в 1С. Регресс 36/36 ps1+py. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
# form-compile v1.70 — Compile 1C managed form from JSON or object metadata
|
# form-compile v1.71 — Compile 1C managed form from JSON or object metadata
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[string]$JsonPath,
|
[string]$JsonPath,
|
||||||
@@ -3070,8 +3070,9 @@ function Normalize-ChoiceValue {
|
|||||||
if ($parts.Count -eq 2) {
|
if ($parts.Count -eq 2) {
|
||||||
# "Enum.X" alone — not a value, treat as string
|
# "Enum.X" alone — not a value, treat as string
|
||||||
} elseif ($parts.Count -eq 3) {
|
} elseif ($parts.Count -eq 3) {
|
||||||
# "Enum.X.Y" — insert .EnumValue.
|
# "Enum.X.Y" — insert .EnumValue. ("EmptyRef" — пустая ссылка, БЕЗ вставки)
|
||||||
$normalized = "Enum.$typeName.EnumValue.$($parts[2])"
|
if ($parts[2] -eq 'EmptyRef') { $normalized = "Enum.$typeName.EmptyRef" }
|
||||||
|
else { $normalized = "Enum.$typeName.EnumValue.$($parts[2])" }
|
||||||
} else {
|
} else {
|
||||||
# "Enum.X.<member>.Y..." — replace member with EnumValue (handles ЗначениеПеречисления too)
|
# "Enum.X.<member>.Y..." — replace member with EnumValue (handles ЗначениеПеречисления too)
|
||||||
$member = $parts[2]
|
$member = $parts[2]
|
||||||
@@ -3131,6 +3132,13 @@ function Emit-ChoicePresentation {
|
|||||||
X "$indent</Presentation>"
|
X "$indent</Presentation>"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# <Value> для choiceList/choiceParameters: пустой текст → самозакрывающийся тег (зеркало платформы).
|
||||||
|
function Get-ChoiceValueTag {
|
||||||
|
param($norm)
|
||||||
|
if ([string]::IsNullOrEmpty($norm.Text)) { return "<Value xsi:type=`"$($norm.XsiType)`"/>" }
|
||||||
|
return "<Value xsi:type=`"$($norm.XsiType)`">$(Esc-Xml $norm.Text)</Value>"
|
||||||
|
}
|
||||||
|
|
||||||
# Emit <ChoiceList> (список выбора) — у RadioButtonField и InputField.
|
# Emit <ChoiceList> (список выбора) — у RadioButtonField и InputField.
|
||||||
# Элемент: { value, presentation?/title? } (+ рус. синонимы значение/представление).
|
# Элемент: { value, presentation?/title? } (+ рус. синонимы значение/представление).
|
||||||
function Emit-ChoiceList {
|
function Emit-ChoiceList {
|
||||||
@@ -3180,7 +3188,7 @@ function Emit-ChoiceList {
|
|||||||
X "$valIndent<xr:CheckState>0</xr:CheckState>"
|
X "$valIndent<xr:CheckState>0</xr:CheckState>"
|
||||||
X "$valIndent<xr:Value xsi:type=`"FormChoiceListDesTimeValue`">"
|
X "$valIndent<xr:Value xsi:type=`"FormChoiceListDesTimeValue`">"
|
||||||
Emit-ChoicePresentation -pres $presRaw -indent "$valIndent`t"
|
Emit-ChoicePresentation -pres $presRaw -indent "$valIndent`t"
|
||||||
X "$valIndent`t<Value xsi:type=`"$($norm.XsiType)`">$(Esc-Xml $norm.Text)</Value>"
|
X "$valIndent`t$(Get-ChoiceValueTag $norm)"
|
||||||
X "$valIndent</xr:Value>"
|
X "$valIndent</xr:Value>"
|
||||||
X "$itemIndent</xr:Item>"
|
X "$itemIndent</xr:Item>"
|
||||||
}
|
}
|
||||||
@@ -3262,13 +3270,13 @@ function Emit-ChoiceParamValue {
|
|||||||
$norm = Normalize-ChoiceValue -value $v
|
$norm = Normalize-ChoiceValue -value $v
|
||||||
X "$indent`t<v8:Value xsi:type=`"FormChoiceListDesTimeValue`">"
|
X "$indent`t<v8:Value xsi:type=`"FormChoiceListDesTimeValue`">"
|
||||||
X "$indent`t`t<Presentation/>"
|
X "$indent`t`t<Presentation/>"
|
||||||
X "$indent`t`t<Value xsi:type=`"$($norm.XsiType)`">$(Esc-Xml $norm.Text)</Value>"
|
X "$indent`t`t$(Get-ChoiceValueTag $norm)"
|
||||||
X "$indent`t</v8:Value>"
|
X "$indent`t</v8:Value>"
|
||||||
}
|
}
|
||||||
X "$indent</Value>"
|
X "$indent</Value>"
|
||||||
} else {
|
} else {
|
||||||
$norm = Normalize-ChoiceValue -value $value
|
$norm = Normalize-ChoiceValue -value $value
|
||||||
X "$indent<Value xsi:type=`"$($norm.XsiType)`">$(Esc-Xml $norm.Text)</Value>"
|
X "$indent$(Get-ChoiceValueTag $norm)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# form-compile v1.70 — Compile 1C managed form from JSON or object metadata
|
# form-compile v1.71 — Compile 1C managed form from JSON or object metadata
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
import argparse
|
import argparse
|
||||||
import copy
|
import copy
|
||||||
@@ -1928,7 +1928,10 @@ def normalize_choice_value(value):
|
|||||||
type_name = parts[1]
|
type_name = parts[1]
|
||||||
normalized = None
|
normalized = None
|
||||||
if canon_root == "Enum":
|
if canon_root == "Enum":
|
||||||
if len(parts) == 3:
|
if len(parts) == 3 and parts[2] == 'EmptyRef':
|
||||||
|
# "Enum.X.EmptyRef" — пустая ссылка, НЕ значение перечисления (без .EnumValue.)
|
||||||
|
normalized = f"Enum.{type_name}.EmptyRef"
|
||||||
|
elif len(parts) == 3:
|
||||||
normalized = f"Enum.{type_name}.EnumValue.{parts[2]}"
|
normalized = f"Enum.{type_name}.EnumValue.{parts[2]}"
|
||||||
elif len(parts) >= 4:
|
elif len(parts) >= 4:
|
||||||
member = parts[2]
|
member = parts[2]
|
||||||
@@ -1970,6 +1973,13 @@ def emit_choice_presentation(lines, pres, indent):
|
|||||||
lines.append(f"{indent}</Presentation>")
|
lines.append(f"{indent}</Presentation>")
|
||||||
|
|
||||||
|
|
||||||
|
def choice_value_tag(norm):
|
||||||
|
# <Value> для choiceList/choiceParameters: пустой текст → самозакрывающийся тег (зеркало платформы).
|
||||||
|
if not norm["text"]:
|
||||||
|
return f'<Value xsi:type="{norm["xsi_type"]}"/>'
|
||||||
|
return f'<Value xsi:type="{norm["xsi_type"]}">{esc_xml(norm["text"])}</Value>'
|
||||||
|
|
||||||
|
|
||||||
def emit_choice_list(lines, el, indent):
|
def emit_choice_list(lines, el, indent):
|
||||||
# <ChoiceList> — у RadioButtonField и InputField. Элемент: { value, presentation?/title? }.
|
# <ChoiceList> — у RadioButtonField и InputField. Элемент: { value, presentation?/title? }.
|
||||||
choice_list = el.get('choiceList') or []
|
choice_list = el.get('choiceList') or []
|
||||||
@@ -1999,7 +2009,7 @@ def emit_choice_list(lines, el, indent):
|
|||||||
lines.append(f'{val_indent}<xr:CheckState>0</xr:CheckState>')
|
lines.append(f'{val_indent}<xr:CheckState>0</xr:CheckState>')
|
||||||
lines.append(f'{val_indent}<xr:Value xsi:type="FormChoiceListDesTimeValue">')
|
lines.append(f'{val_indent}<xr:Value xsi:type="FormChoiceListDesTimeValue">')
|
||||||
emit_choice_presentation(lines, pres_raw, f'{val_indent}\t')
|
emit_choice_presentation(lines, pres_raw, f'{val_indent}\t')
|
||||||
lines.append(f'{val_indent}\t<Value xsi:type="{norm["xsi_type"]}">{esc_xml(norm["text"])}</Value>')
|
lines.append(f'{val_indent}\t{choice_value_tag(norm)}')
|
||||||
lines.append(f'{val_indent}</xr:Value>')
|
lines.append(f'{val_indent}</xr:Value>')
|
||||||
lines.append(f'{item_indent}</xr:Item>')
|
lines.append(f'{item_indent}</xr:Item>')
|
||||||
lines.append(f'{indent}</ChoiceList>')
|
lines.append(f'{indent}</ChoiceList>')
|
||||||
@@ -2075,12 +2085,12 @@ def emit_choice_param_value(lines, value, indent):
|
|||||||
norm = normalize_choice_value(v)
|
norm = normalize_choice_value(v)
|
||||||
lines.append(f'{indent}\t<v8:Value xsi:type="FormChoiceListDesTimeValue">')
|
lines.append(f'{indent}\t<v8:Value xsi:type="FormChoiceListDesTimeValue">')
|
||||||
lines.append(f'{indent}\t\t<Presentation/>')
|
lines.append(f'{indent}\t\t<Presentation/>')
|
||||||
lines.append(f'{indent}\t\t<Value xsi:type="{norm["xsi_type"]}">{esc_xml(norm["text"])}</Value>')
|
lines.append(f'{indent}\t\t{choice_value_tag(norm)}')
|
||||||
lines.append(f'{indent}\t</v8:Value>')
|
lines.append(f'{indent}\t</v8:Value>')
|
||||||
lines.append(f'{indent}</Value>')
|
lines.append(f'{indent}</Value>')
|
||||||
else:
|
else:
|
||||||
norm = normalize_choice_value(value)
|
norm = normalize_choice_value(value)
|
||||||
lines.append(f'{indent}<Value xsi:type="{norm["xsi_type"]}">{esc_xml(norm["text"])}</Value>')
|
lines.append(f'{indent}{choice_value_tag(norm)}')
|
||||||
|
|
||||||
|
|
||||||
def emit_choice_parameters(lines, el, indent):
|
def emit_choice_parameters(lines, el, indent):
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
{ "input": "ПолеПароля", "path": "ПолеПароля", "passwordMode": true, "title": "Пароль" },
|
{ "input": "ПолеПароля", "path": "ПолеПароля", "passwordMode": true, "title": "Пароль" },
|
||||||
{ "input": "ПолеСКнопками", "path": "ПолеСКнопками", "choiceButton": true, "clearButton": true, "title": "Выбор" },
|
{ "input": "ПолеСКнопками", "path": "ПолеСКнопками", "choiceButton": true, "clearButton": true, "title": "Выбор" },
|
||||||
{ "input": "ПолеСписокВыбора", "path": "ПолеСписокВыбора", "title": "Список выбора", "choiceList": [
|
{ "input": "ПолеСписокВыбора", "path": "ПолеСписокВыбора", "title": "Список выбора", "choiceList": [
|
||||||
|
{ "value": "", "presentation": "Все" },
|
||||||
{ "value": "Первый" },
|
{ "value": "Первый" },
|
||||||
{ "value": "Второй", "presentation": "Второй вариант" }
|
{ "value": "Второй", "presentation": "Второй вариант" }
|
||||||
]},
|
]},
|
||||||
|
|||||||
@@ -37,7 +37,8 @@
|
|||||||
"columnsCount": 1,
|
"columnsCount": 1,
|
||||||
"choiceList": [
|
"choiceList": [
|
||||||
{ "value": "Enum.СпособыКурса.EnumValue.Авто", "presentation": { "ru": "Автоматически", "en": "Automatic" } },
|
{ "value": "Enum.СпособыКурса.EnumValue.Авто", "presentation": { "ru": "Автоматически", "en": "Automatic" } },
|
||||||
{ "value": "Enum.СпособыКурса.EnumValue.Ручной", "presentation": "вручную" }
|
{ "value": "Enum.СпособыКурса.EnumValue.Ручной", "presentation": "вручную" },
|
||||||
|
{ "value": "Enum.СпособыКурса.EmptyRef", "presentation": "(не задан)" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
+13
@@ -91,6 +91,19 @@
|
|||||||
</v8:item>
|
</v8:item>
|
||||||
</Title>
|
</Title>
|
||||||
<ChoiceList>
|
<ChoiceList>
|
||||||
|
<xr:Item>
|
||||||
|
<xr:Presentation/>
|
||||||
|
<xr:CheckState>0</xr:CheckState>
|
||||||
|
<xr:Value xsi:type="FormChoiceListDesTimeValue">
|
||||||
|
<Presentation>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>Все</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</Presentation>
|
||||||
|
<Value xsi:type="xs:string"/>
|
||||||
|
</xr:Value>
|
||||||
|
</xr:Item>
|
||||||
<xr:Item>
|
<xr:Item>
|
||||||
<xr:Presentation/>
|
<xr:Presentation/>
|
||||||
<xr:CheckState>0</xr:CheckState>
|
<xr:CheckState>0</xr:CheckState>
|
||||||
|
|||||||
+13
@@ -51,6 +51,19 @@
|
|||||||
<Value xsi:type="xr:DesignTimeRef">Enum.СпособыКурса.EnumValue.Ручной</Value>
|
<Value xsi:type="xr:DesignTimeRef">Enum.СпособыКурса.EnumValue.Ручной</Value>
|
||||||
</xr:Value>
|
</xr:Value>
|
||||||
</xr:Item>
|
</xr:Item>
|
||||||
|
<xr:Item>
|
||||||
|
<xr:Presentation/>
|
||||||
|
<xr:CheckState>0</xr:CheckState>
|
||||||
|
<xr:Value xsi:type="FormChoiceListDesTimeValue">
|
||||||
|
<Presentation>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>(не задан)</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</Presentation>
|
||||||
|
<Value xsi:type="xr:DesignTimeRef">Enum.СпособыКурса.EmptyRef</Value>
|
||||||
|
</xr:Value>
|
||||||
|
</xr:Item>
|
||||||
</ChoiceList>
|
</ChoiceList>
|
||||||
<ContextMenu name="СпособКурсаКонтекстноеМеню" id="2"/>
|
<ContextMenu name="СпособКурсаКонтекстноеМеню" id="2"/>
|
||||||
<ExtendedTooltip name="СпособКурсаРасширеннаяПодсказка" id="3"/>
|
<ExtendedTooltip name="СпособКурсаРасширеннаяПодсказка" id="3"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user