feat(skd-decompile): компактный JSON-сериализатор + расширенный shorthand totalFields

Заменил ConvertTo-Json (PS5.1) на собственный ConvertTo-CompactJson:
- 2-пробельный indent (вместо 4 + выравнивание keys по длине)
- Массивы примитивов (string/number/bool/null) — inline `[a, b, c]`
- Массивы с объектами/nested arrays — multi-line как раньше
- Кириллица в UTF-8 (без \uXXXX-escapes)
- Корректный escape строк (\\", \\, \n, \r, \t, \uXXXX для control chars)

Build-TotalField: shorthand "name: expr" для любого однострочного
expression. Раньше object form применялась когда expression не Func(arg).
Теперь — только когда есть group или expression многострочный.
Compile принимает любой shorthand вида "dataPath: expression" (Parse-
TotalShorthand делает split по первому ":").

Save-UserStyles тоже использует новый сериализатор.

Все 16 декомпиляционных snapshot'ов обновлены (косметика — JSON
структурно тот же, тесты round-trip проходят).

На реальном отчёте (целевой корпус): 405 → 264 строк (-35%).
v0.18 → v0.19.
This commit is contained in:
Nick Shirokov
2026-05-21 20:50:34 +03:00
parent e0ee927156
commit 55b80fdc08
18 changed files with 604 additions and 648 deletions
@@ -1,87 +1,65 @@
{
"dataSets": [
{
"name": "Тест",
"query": "ВЫБРАТЬ * ИЗ Справочник.Номенклатура",
"fields": [
"Организация: CatalogRef.Организации @dimension",
"Номенклатура: CatalogRef.Номенклатура @dimension",
"Сумма: decimal(15,2)",
"Количество: decimal(15,3)",
"Статус: string"
]
}
],
"parameters": [
"Период: StandardPeriod = LastMonth @autoDates",
"Активные: boolean = true"
],
"templates": [
{
"name": "Шапка",
"style": "header",
"rows": [
[
"Орг",
"Сум"
]
]
}
],
"groupTemplates": [
{
"groupName": "ДанныеОтчета",
"templateType": "GroupHeader",
"template": "Шапка"
}
],
"settingsVariants": [
{
"name": "Основной",
"title": "Основной вариант",
"settings": {
"selection": [
"Организация",
{
"folder": "Объёмы",
"items": [
"Сумма",
"Количество"
]
}
],
"filter": [
"Организация = _ @off @user",
{
"group": "Or",
"items": [
"Статус = Активен",
"Сумма > 1000"
]
}
],
"order": [
"Сумма desc"
],
"conditionalAppearance": [
{
"filter": [
"Сумма > 10000"
],
"appearance": {
"ЦветТекста": "style:НегативныйТекстЦвет"
},
"presentation": "Большие суммы",
"viewMode": "Normal",
"userSettingID": "auto"
}
],
"outputParameters": {
"Заголовок": "Сводка по организациям"
},
"dataParameters": "auto",
"structure": "Организация > Номенклатура > details"
}
}
]
"dataSets": [
{
"name": "Тест",
"query": "ВЫБРАТЬ * ИЗ Справочник.Номенклатура",
"fields": ["Организация: CatalogRef.Организации @dimension", "Номенклатура: CatalogRef.Номенклатура @dimension", "Сумма: decimal(15,2)", "Количество: decimal(15,3)", "Статус: string"]
}
],
"parameters": ["Период: StandardPeriod = LastMonth @autoDates", "Активные: boolean = true"],
"templates": [
{
"name": "Шапка",
"style": "header",
"rows": [
["Орг", "Сум"]
]
}
],
"groupTemplates": [
{
"groupName": "ДанныеОтчета",
"templateType": "GroupHeader",
"template": "Шапка"
}
],
"settingsVariants": [
{
"name": "Основной",
"title": "Основной вариант",
"settings": {
"selection": [
"Организация",
{
"folder": "Объёмы",
"items": ["Сумма", "Количество"]
}
],
"filter": [
"Организация = _ @off @user",
{
"group": "Or",
"items": ["Статус = Активен", "Сумма > 1000"]
}
],
"order": ["Сумма desc"],
"conditionalAppearance": [
{
"filter": ["Сумма > 10000"],
"appearance": {
"ЦветТекста": "style:НегативныйТекстЦвет"
},
"presentation": "Большие суммы",
"viewMode": "Normal",
"userSettingID": "auto"
}
],
"outputParameters": {
"Заголовок": "Сводка по организациям"
},
"dataParameters": "auto",
"structure": "Организация > Номенклатура > details"
}
}
]
}