mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-06-14 18:04:58 +03:00
feat(form-decompile,form-compile): частичная/минимальная форма ListSettings (дескриптор settings.listSettings)
Раундтрип TOTAL 21→0, match 153→156. Компилятор всегда эмитил ПОЛНЫЙ каноничный скелет <ListSettings> (filter+order+conditionalAppearance+itemsViewMode+ itemsUserSettingID), а ~7% форм имеют частичный (напр. только <filter> с userSettingID) → лишние контейнеры = ADDED. - Декомпилятор: Get-ListSettingsShape фиксирует «форму» скелета в settings.listSettings (ordered-карта present top-level: filter/order/ conditionalAppearance → блок-мета 'v'/'u'/'vu'/''; itemsViewMode/ itemsUserSettingID → true). Дескриптор пишется ТОЛЬКО для не-каноничных форм ($null для полного канона и неподдержанных top-level item/dataParameters/…). - Компилятор: при наличии дескриптора эмитит ТОЛЬКО указанные части (контент из settings.filter/order/CA, блок-мета из дескриптора); иначе — полный канон (без изменений). Аддитивно, дескриптор-gated → 93% канон-форм не затронуты. Зеркало py. Формы ОстаткиАлкогольнойПродукцииЕГАИС (filter-only) и ОстаткиПартийЗЕРНО (filter+order) → ListSettings бит-в-бит. Регресс 39/39 (канон-путь). Партиал-путь — harness + provenance (подмножество канона). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# form-compile v1.92 — Compile 1C managed form from JSON or object metadata
|
||||
# form-compile v1.93 — Compile 1C managed form from JSON or object metadata
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[string]$JsonPath,
|
||||
@@ -4711,11 +4711,28 @@ function Emit-Attributes {
|
||||
# Нет items → контейнеры всё равно эмитятся (blockMeta) = каноничный пустой скелет платформы.
|
||||
$lsi = "$si`t"
|
||||
X "$si<ListSettings>"
|
||||
Emit-Filter -items $st.filter -indent $lsi -blockViewMode 'Normal' -blockUserSettingID $script:CANON_FILTER_ID
|
||||
Emit-Order -items $st.order -indent $lsi -blockViewMode 'Normal' -blockUserSettingID $script:CANON_ORDER_ID
|
||||
Emit-ConditionalAppearance -items $st.conditionalAppearance -indent $lsi -blockViewMode 'Normal' -blockUserSettingID $script:CANON_CA_ID
|
||||
X "$lsi<dcsset:itemsViewMode>Normal</dcsset:itemsViewMode>"
|
||||
X "$lsi<dcsset:itemsUserSettingID>$($script:CANON_ITEMS_ID)</dcsset:itemsUserSettingID>"
|
||||
if ($st.PSObject.Properties['listSettings'] -and $null -ne $st.listSettings) {
|
||||
# Частичная/минимальная форма скелета — эмитим ТОЛЬКО указанные части с их блок-метой.
|
||||
# meta: 'v'=viewMode, 'u'=userSettingID (контейнеры); itemsViewMode/itemsUserSettingID → present.
|
||||
foreach ($prop in $st.listSettings.PSObject.Properties) {
|
||||
$tag = $prop.Name; $meta = "$($prop.Value)"
|
||||
$bvm = if ($meta -match 'v') { 'Normal' } else { $null }
|
||||
switch ($tag) {
|
||||
'filter' { $bus = if ($meta -match 'u') { $script:CANON_FILTER_ID } else { $null }; Emit-Filter -items $st.filter -indent $lsi -blockViewMode $bvm -blockUserSettingID $bus }
|
||||
'order' { $bus = if ($meta -match 'u') { $script:CANON_ORDER_ID } else { $null }; Emit-Order -items $st.order -indent $lsi -blockViewMode $bvm -blockUserSettingID $bus }
|
||||
'conditionalAppearance' { $bus = if ($meta -match 'u') { $script:CANON_CA_ID } else { $null }; Emit-ConditionalAppearance -items $st.conditionalAppearance -indent $lsi -blockViewMode $bvm -blockUserSettingID $bus }
|
||||
'itemsViewMode' { X "$lsi<dcsset:itemsViewMode>Normal</dcsset:itemsViewMode>" }
|
||||
'itemsUserSettingID' { X "$lsi<dcsset:itemsUserSettingID>$($script:CANON_ITEMS_ID)</dcsset:itemsUserSettingID>" }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# Полный каноничный скелет (умолчание, ~93% форм) — без изменений.
|
||||
Emit-Filter -items $st.filter -indent $lsi -blockViewMode 'Normal' -blockUserSettingID $script:CANON_FILTER_ID
|
||||
Emit-Order -items $st.order -indent $lsi -blockViewMode 'Normal' -blockUserSettingID $script:CANON_ORDER_ID
|
||||
Emit-ConditionalAppearance -items $st.conditionalAppearance -indent $lsi -blockViewMode 'Normal' -blockUserSettingID $script:CANON_CA_ID
|
||||
X "$lsi<dcsset:itemsViewMode>Normal</dcsset:itemsViewMode>"
|
||||
X "$lsi<dcsset:itemsUserSettingID>$($script:CANON_ITEMS_ID)</dcsset:itemsUserSettingID>"
|
||||
}
|
||||
X "$si</ListSettings>"
|
||||
X "$inner</Settings>"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# form-compile v1.92 — Compile 1C managed form from JSON or object metadata
|
||||
# form-compile v1.93 — Compile 1C managed form from JSON or object metadata
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import copy
|
||||
@@ -4414,11 +4414,32 @@ def emit_attributes(lines, attrs, indent):
|
||||
# Нет items → контейнеры всё равно эмитятся (blockMeta) = каноничный пустой скелет платформы.
|
||||
lsi = f'{si}\t'
|
||||
lines.append(f'{si}<ListSettings>')
|
||||
emit_filter(lines, s.get('filter'), lsi, block_view_mode='Normal', block_user_setting_id=CANON_FILTER_ID)
|
||||
emit_order(lines, s.get('order'), lsi, block_view_mode='Normal', block_user_setting_id=CANON_ORDER_ID)
|
||||
emit_conditional_appearance(lines, s.get('conditionalAppearance'), lsi, block_view_mode='Normal', block_user_setting_id=CANON_CA_ID)
|
||||
lines.append(f'{lsi}<dcsset:itemsViewMode>Normal</dcsset:itemsViewMode>')
|
||||
lines.append(f'{lsi}<dcsset:itemsUserSettingID>{CANON_ITEMS_ID}</dcsset:itemsUserSettingID>')
|
||||
ls_shape = s.get('listSettings')
|
||||
if ls_shape is not None:
|
||||
# Частичная/минимальная форма скелета — эмитим ТОЛЬКО указанные части с их блок-метой.
|
||||
for tag, meta in ls_shape.items():
|
||||
meta = str(meta)
|
||||
bvm = 'Normal' if 'v' in meta else None
|
||||
if tag == 'filter':
|
||||
bus = CANON_FILTER_ID if 'u' in meta else None
|
||||
emit_filter(lines, s.get('filter'), lsi, block_view_mode=bvm, block_user_setting_id=bus)
|
||||
elif tag == 'order':
|
||||
bus = CANON_ORDER_ID if 'u' in meta else None
|
||||
emit_order(lines, s.get('order'), lsi, block_view_mode=bvm, block_user_setting_id=bus)
|
||||
elif tag == 'conditionalAppearance':
|
||||
bus = CANON_CA_ID if 'u' in meta else None
|
||||
emit_conditional_appearance(lines, s.get('conditionalAppearance'), lsi, block_view_mode=bvm, block_user_setting_id=bus)
|
||||
elif tag == 'itemsViewMode':
|
||||
lines.append(f'{lsi}<dcsset:itemsViewMode>Normal</dcsset:itemsViewMode>')
|
||||
elif tag == 'itemsUserSettingID':
|
||||
lines.append(f'{lsi}<dcsset:itemsUserSettingID>{CANON_ITEMS_ID}</dcsset:itemsUserSettingID>')
|
||||
else:
|
||||
# Полный каноничный скелет (умолчание, ~93% форм) — без изменений.
|
||||
emit_filter(lines, s.get('filter'), lsi, block_view_mode='Normal', block_user_setting_id=CANON_FILTER_ID)
|
||||
emit_order(lines, s.get('order'), lsi, block_view_mode='Normal', block_user_setting_id=CANON_ORDER_ID)
|
||||
emit_conditional_appearance(lines, s.get('conditionalAppearance'), lsi, block_view_mode='Normal', block_user_setting_id=CANON_CA_ID)
|
||||
lines.append(f'{lsi}<dcsset:itemsViewMode>Normal</dcsset:itemsViewMode>')
|
||||
lines.append(f'{lsi}<dcsset:itemsUserSettingID>{CANON_ITEMS_ID}</dcsset:itemsUserSettingID>')
|
||||
lines.append(f'{si}</ListSettings>')
|
||||
lines.append(f'{inner}</Settings>')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# form-decompile v0.69 — Decompile 1C managed Form.xml to JSON DSL (draft)
|
||||
# form-decompile v0.70 — Decompile 1C managed Form.xml to JSON DSL (draft)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
|
||||
param(
|
||||
@@ -113,6 +113,31 @@ function Test-ListSettingsHasContent {
|
||||
return $false
|
||||
}
|
||||
|
||||
# Форма ListSettings: ordered-карта present top-level элементов (filter/order/conditionalAppearance →
|
||||
# блок-мета 'v'/'u'/'vu'/''; itemsViewMode/itemsUserSettingID → $true). Возвращает $null, если форма ==
|
||||
# полному каноничному скелету (компилятор регенерит сам) ИЛИ содержит неподдержанные top-level элементы
|
||||
# (item/dataParameters/viewMode/userSettingID/… → fallback на канон). Иначе — дескриптор для компилятора.
|
||||
function Get-ListSettingsShape {
|
||||
param($lsNode)
|
||||
if (-not $lsNode) { return $null }
|
||||
$shape = [ordered]@{}
|
||||
foreach ($child in $lsNode.ChildNodes) {
|
||||
if ($child.NodeType -ne [System.Xml.XmlNodeType]::Element) { continue }
|
||||
$tag = $child.LocalName
|
||||
if ($tag -in @('filter','order','conditionalAppearance')) {
|
||||
$hasVM = $null -ne $child.SelectSingleNode("dcsset:viewMode", $ns)
|
||||
$hasUS = $null -ne $child.SelectSingleNode("dcsset:userSettingID", $ns)
|
||||
$shape[$tag] = "$(if ($hasVM) {'v'})$(if ($hasUS) {'u'})"
|
||||
} elseif ($tag -eq 'itemsViewMode') { $shape['itemsViewMode'] = $true }
|
||||
elseif ($tag -eq 'itemsUserSettingID') { $shape['itemsUserSettingID'] = $true }
|
||||
else { return $null } # item/dataParameters/itemsUserSettingPresentation/… → канон-fallback
|
||||
}
|
||||
# Полный каноничный скелет → опускаем (компилятор регенерит)
|
||||
if ($shape.Count -eq 5 -and $shape['filter'] -eq 'vu' -and $shape['order'] -eq 'vu' -and `
|
||||
$shape['conditionalAppearance'] -eq 'vu' -and $shape['itemsViewMode'] -eq $true -and $shape['itemsUserSettingID'] -eq $true) { return $null }
|
||||
return $shape
|
||||
}
|
||||
|
||||
# --- 1b. Ring-3 scan: конструкции вне зоны поддержки (draft list) ---
|
||||
function Fail-Ring3 {
|
||||
param([string]$kind, [string]$loc)
|
||||
@@ -1955,6 +1980,10 @@ if ($attrsNode) {
|
||||
$ca = Build-ConditionalAppearance -caNode $caNode -loc "settings/conditionalAppearance"
|
||||
if (@($ca).Count -gt 0) { $so['conditionalAppearance'] = @($ca) }
|
||||
}
|
||||
# Форма скелета ListSettings: дескриптор только для НЕ-каноничных форм (частичные/минимальные).
|
||||
# Канон → $null (компилятор регенерит полный скелет, как раньше).
|
||||
$lsShape = Get-ListSettingsShape $lsNode
|
||||
if ($null -ne $lsShape) { $so['listSettings'] = $lsShape }
|
||||
}
|
||||
if ($so.Count -gt 0) { $ao['settings'] = $so }
|
||||
}
|
||||
|
||||
@@ -814,7 +814,9 @@ Pages поддерживает `pagesRepresentation`: `None`, `TabsOnTop`, `Tabs
|
||||
|
||||
`ManualQuery` выводится из наличия `query` — отдельным ключом не задаётся.
|
||||
|
||||
Пустой блок настроек компоновщика (`ListSettings`) генерируется автоматически (каноничный скелет платформы); указывать ничего не нужно.
|
||||
Пустой блок настроек компоновщика (`ListSettings`) генерируется автоматически (каноничный полный скелет платформы — filter+order+conditionalAppearance+itemsViewMode+itemsUserSettingID, ~93% форм); указывать ничего не нужно.
|
||||
|
||||
| `listSettings` | object | **Дескриптор формы скелета `<ListSettings>`** — только для НЕ-каноничных (частичных/минимальных) форм. Ordered-карта present top-level элементов: контейнеры `filter`/`order`/`conditionalAppearance` → блок-мета (`"vu"`=viewMode+userSettingID, `"u"`=только userSettingID, `"v"`, `""`); `itemsViewMode`/`itemsUserSettingID` → `true`. Компилятор эмитит ТОЛЬКО указанные части (контент берёт из `filter`/`order`/`conditionalAppearance`). Нет ключа → полный каноничный скелет. Декомпилятор пишет дескриптор только для отклонений от канона |
|
||||
|
||||
#### parameters — параметры схемы дин-списка
|
||||
|
||||
|
||||
Reference in New Issue
Block a user