refactor(mxl-compile,mxl-decompile): ключ ячейки control → controlType

Тег ячейки <control> и тег формата <controlType> в выгрузке — разные
вещи: первый несёт сериализованные настройки элемента управления, второй
GUID его вида. Ключ DSL описывал второй, а назывался как первый, и при
поддержке настроек отображение стало бы перекрёстным.

Свести их в один ключ нельзя: <controlType> живёт в палитре и разделяется
ячейками с одинаковым оформлением, а настройки принадлежат конкретной
ячейке. Синоним не заводим — он занял бы ровно то имя, которое
освобождается.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-15 11:46:50 +03:00
co-authored by Claude Opus 5
parent 7f743b18a9
commit aaeb752cf1
14 changed files with 40 additions and 40 deletions
+2 -2
View File
@@ -59,7 +59,7 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.ps1" -J
styles: { name: { font, horizontalAlignment, verticalAlignment, textPlacement,
backColor, textColor, border, borderColor, format, hidden } },
areas: [{ name, columnSet, rows: [{ height, hidden, rowStyle, cells: [
{ col, span, rowspan, style, param, detail, text, template, valueType, control }
{ col, span, rowspan, style, param, detail, text, template, valueType, controlType }
]}]}],
namedAreas: [{ name, rows, cols }],
columnSets: { name: { columns, columnWidths, columnStyles } }
@@ -80,7 +80,7 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.ps1" -J
- `col` — 1-based позиция колонки
- `rowspan` — объединение строк вниз (rowStyle учитывает занятые ячейки)
- Содержимое ячейки задаётся одним из ключей: `param` — параметр заполнения, `text` — статический текст, `template` — текст со вставками `[Параметр]`
- `valueType` делает ячейку полем ввода (`"Number(15,3,nonneg)"`, `"String(10)"`, `"CatalogRef.Валюты"`, составной через ` + `); текста в такой ячейке быть не может, а `control: "checkbox"` меняет поле ввода на флажок
- `valueType` делает ячейку полем ввода (`"Number(15,3,nonneg)"`, `"String(10)"`, `"CatalogRef.Валюты"`, составной через ` + `); текста в такой ячейке быть не может, а `controlType: "checkbox"` меняет поле ввода на флажок
Двухуровневая шапка массивами:
```json
@@ -152,8 +152,8 @@
| `{ ... }` | Обычная ячейка **без** `col`; нужна для `style`, `detail`, `template` |
Объект-элемент трактуется по его ключам: если среди них есть ключ ячейки (`span`, `rowspan`,
`style`, `param`, `detail`, `text`, `template`) — объект описывает свойства ячейки. Иначе он
целиком считается её текстом, а его ключи — идентификаторами языков.
`style`, `param`, `detail`, `text`, `template`, `valueType`, `controlType`) — объект описывает
свойства ячейки. Иначе он целиком считается её текстом, а его ключи — идентификаторами языков.
```json
"rows": [
@@ -183,7 +183,7 @@
| `text` | нет | — | Статический текст. Строка или объект `{ ru, en }` — см. ниже |
| `template` | нет | — | Шаблонный текст с `[Параметр]`. Строка или объект, как `text` |
| `valueType` | нет | — | Тип значения: ячейка становится полем ввода (см. ниже) |
| `control` | нет | `input` | Элемент управления поля ввода: `input` или `checkbox`. Только вместе с `valueType` |
| `controlType` | нет | `input` | Элемент управления поля ввода: `input` или `checkbox`. Только вместе с `valueType` |
### Содержимое ячейки
@@ -222,7 +222,7 @@
```json
{ "col": 1, "valueType": "Number(15,3,nonneg)" }
{ "col": 2, "valueType": "String(10)" }
{ "col": 3, "valueType": "Boolean", "control": "checkbox" }
{ "col": 3, "valueType": "Boolean", "controlType": "checkbox" }
{ "col": 4, "valueType": "CatalogRef.Валюты" }
{ "col": 5, "valueType": "Boolean + String + Date + CatalogRef.Валюты" }
{ "col": 6, "valueType": "AnyRef" }
@@ -248,9 +248,9 @@
Пустой тип `"valueType": ""` — «ячейка содержит значение», но тип не ограничен.
`control` нужен редко: умолчание платформы — поле ввода, и оно применяется ко всем типам, включая
`Boolean`. Флажок задаётся явно. Значение `"none"` (тега элемента управления нет вовсе) — форма
раундтрипа, для ручного авторинга не нужна.
`controlType` нужен редко: умолчание платформы — поле ввода, и оно применяется ко всем типам,
включая `Boolean`. Флажок задаётся явно. Значение `"none"` (тега элемента управления нет вовсе) —
форма раундтрипа, для ручного авторинга не нужна.
## `rowStyle` — оформление строки
@@ -848,10 +848,10 @@ function Get-CellValueProps {
param($cell, [string]$where)
$props = @{}
$vt = $cell.valueType
$ctl = $cell.control
$ctl = $cell.controlType
if ($null -eq $vt) {
if ($null -ne $ctl -and "$ctl" -ne '') {
[Console]::Error.WriteLine("Cell 'control' requires 'valueType' ($where)")
[Console]::Error.WriteLine("Cell 'controlType' requires 'valueType' ($where)")
exit 1
}
return $props
@@ -879,7 +879,7 @@ function Get-CellValueProps {
# Неизвестный элемент управления сохраняем как есть — терять его нельзя.
$props['controlType'] = $name
} else {
[Console]::Error.WriteLine("Unknown 'control' value `"$ctl`" ($where). Allowed: input, checkbox, none or a GUID")
[Console]::Error.WriteLine("Unknown 'controlType' value `"$ctl`" ($where). Allowed: input, checkbox, none or a GUID")
exit 1
}
return $props
@@ -1140,7 +1140,7 @@ function Set-CellProp {
function Test-CellObject {
param($el)
$cellKeys = @('col', 'span', 'rowspan', 'style', 'param', 'detail', 'text', 'template',
'valueType', 'control')
'valueType', 'controlType')
foreach ($p in $el.PSObject.Properties) {
if ($cellKeys -contains $p.Name) { return $true }
}
@@ -650,10 +650,10 @@ def cell_value_props(cell, where):
состав палитры разойдётся и все ссылки <f> сдвинутся."""
props = {}
vt = cell.get('valueType')
ctl = cell.get('control')
ctl = cell.get('controlType')
if vt is None:
if ctl is not None and str(ctl) != '':
print(f"Cell 'control' requires 'valueType' ({where})", file=sys.stderr)
print(f"Cell 'controlType' requires 'valueType' ({where})", file=sys.stderr)
sys.exit(1)
return props
# Ячейка, содержащая значение, текста не несёт: платформа этого не допускает, и в корпусе
@@ -678,7 +678,7 @@ def cell_value_props(cell, where):
# Неизвестный элемент управления сохраняем как есть — терять его нельзя.
props['controlType'] = name
else:
print(f'Unknown \'control\' value "{ctl}" ({where}).'
print(f'Unknown \'controlType\' value "{ctl}" ({where}).'
f' Allowed: input, checkbox, none or a GUID', file=sys.stderr)
sys.exit(1)
return props
@@ -1154,7 +1154,7 @@ def main():
ключей есть ключ схемы ячейки, во втором ключи — идентификаторы языков. Пересечений
нет: в корпусе это ru, en, ru1, Русский."""
cell_keys = ('col', 'span', 'rowspan', 'style', 'param', 'detail', 'text', 'template',
'valueType', 'control')
'valueType', 'controlType')
return any(k in el for k in cell_keys)
def expand_shorthand_row(row, area_name, row_idx, open_by_col, max_cols):
@@ -1125,13 +1125,13 @@ foreach ($area in $blocks) {
# Формат без <controlType> вовсе — так пишут машинно-сгенерированные макеты
# регламентированной отчётности; компилятор такое повторит только по
# явному указанию.
$dslCell["control"] = "none"
$dslCell["controlType"] = "none"
} else {
$ctl = "$($cellFmt.Props['controlType'])"
$name = if ($valueControlNames.ContainsKey($ctl.ToLowerInvariant())) { $valueControlNames[$ctl.ToLowerInvariant()] } else { $ctl }
# input — умолчание компилятора, писать его значит шуметь на 63 629
# форматах корпуса.
if ($name -cne 'input') { $dslCell["control"] = $name }
if ($name -cne 'input') { $dslCell["controlType"] = $name }
}
}
@@ -1119,13 +1119,13 @@ def main():
# Формат без <controlType> вовсе — так пишут машинно-сгенерированные
# макеты регламентированной отчётности; компилятор такое повторит
# только по явному указанию.
dsl_cell["control"] = "none"
dsl_cell["controlType"] = "none"
else:
name = VALUE_CONTROL_NAMES.get(ctl.lower(), ctl)
# input — умолчание компилятора, писать его значит шуметь на 63 629
# форматах корпуса.
if name != "input":
dsl_cell["control"] = name
dsl_cell["controlType"] = name
# Content
fill_type = cell_fmt["FillType"] if cell_fmt else ""
+7 -7
View File
@@ -152,8 +152,8 @@
| `{ ... }` | Обычная ячейка **без** `col`; нужна для `style`, `detail`, `template` |
Объект-элемент трактуется по его ключам: если среди них есть ключ ячейки (`span`, `rowspan`,
`style`, `param`, `detail`, `text`, `template`) — объект описывает свойства ячейки. Иначе он
целиком считается её текстом, а его ключи — идентификаторами языков.
`style`, `param`, `detail`, `text`, `template`, `valueType`, `controlType`) — объект описывает
свойства ячейки. Иначе он целиком считается её текстом, а его ключи — идентификаторами языков.
```json
"rows": [
@@ -183,7 +183,7 @@
| `text` | нет | — | Статический текст. Строка или объект `{ ru, en }` — см. ниже |
| `template` | нет | — | Шаблонный текст с `[Параметр]`. Строка или объект, как `text` |
| `valueType` | нет | — | Тип значения: ячейка становится полем ввода (см. ниже) |
| `control` | нет | `input` | Элемент управления поля ввода: `input` или `checkbox`. Только вместе с `valueType` |
| `controlType` | нет | `input` | Элемент управления поля ввода: `input` или `checkbox`. Только вместе с `valueType` |
### Содержимое ячейки
@@ -222,7 +222,7 @@
```json
{ "col": 1, "valueType": "Number(15,3,nonneg)" }
{ "col": 2, "valueType": "String(10)" }
{ "col": 3, "valueType": "Boolean", "control": "checkbox" }
{ "col": 3, "valueType": "Boolean", "controlType": "checkbox" }
{ "col": 4, "valueType": "CatalogRef.Валюты" }
{ "col": 5, "valueType": "Boolean + String + Date + CatalogRef.Валюты" }
{ "col": 6, "valueType": "AnyRef" }
@@ -248,9 +248,9 @@
Пустой тип `"valueType": ""` — «ячейка содержит значение», но тип не ограничен.
`control` нужен редко: умолчание платформы — поле ввода, и оно применяется ко всем типам, включая
`Boolean`. Флажок задаётся явно. Значение `"none"` (тега элемента управления нет вовсе) — форма
раундтрипа, для ручного авторинга не нужна.
`controlType` нужен редко: умолчание платформы — поле ввода, и оно применяется ко всем типам,
включая `Boolean`. Флажок задаётся явно. Значение `"none"` (тега элемента управления нет вовсе) —
форма раундтрипа, для ручного авторинга не нужна.
## `rowStyle` — оформление строки
@@ -5,10 +5,10 @@
"areas": [
{
"name": "Ввод",
"rows": [{ "cells": [{ "col": 1, "valueType": "Boolean", "control": "кнопка" }] }]
"rows": [{ "cells": [{ "col": 1, "valueType": "Boolean", "controlType": "кнопка" }] }]
}
]
},
"params": { "outputPath": "Template.xml" },
"expectError": "Unknown 'control' value \"кнопка\" (area \"Ввод\"). Allowed: input, checkbox, none or a GUID"
"expectError": "Unknown 'controlType' value \"кнопка\" (area \"Ввод\"). Allowed: input, checkbox, none or a GUID"
}
@@ -1,14 +1,14 @@
{
"name": "Ошибка: control без valueType",
"name": "Ошибка: controlType без valueType",
"input": {
"columns": 1,
"areas": [
{
"name": "Ввод",
"rows": [{ "cells": [{ "col": 1, "control": "checkbox" }] }]
"rows": [{ "cells": [{ "col": 1, "controlType": "checkbox" }] }]
}
]
},
"params": { "outputPath": "Template.xml" },
"expectError": "Cell 'control' requires 'valueType' (area \"Ввод\")"
"expectError": "Cell 'controlType' requires 'valueType' (area \"Ввод\")"
}
@@ -13,7 +13,7 @@
]},
{ "cells": [
{ "col": 1, "valueType": "Boolean" },
{ "col": 2, "valueType": "Boolean", "control": "checkbox" }
{ "col": 2, "valueType": "Boolean", "controlType": "checkbox" }
]},
{ "cells": [
{ "col": 1, "valueType": "String(10)" },
@@ -12,7 +12,7 @@
{ "valueType": "Number(15,3,any)" },
{ "valueType": "Строка(10)" },
{ "valueType": "String(10,variable)" },
{ "valueType": "Булево", "control": "Поле Флажка" }
{ "valueType": "Булево", "controlType": "Поле Флажка" }
]
]
}
@@ -9,8 +9,8 @@
"rows": [
{ "cells": [
{ "col": 1, "valueType": "" },
{ "col": 2, "valueType": "Number(15,3)", "control": "none" },
{ "col": 3, "valueType": "Boolean", "control": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" },
{ "col": 2, "valueType": "Number(15,3)", "controlType": "none" },
{ "col": 3, "valueType": "Boolean", "controlType": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" },
{ "col": 4, "valueType": "String(50)", "style": "bordered" }
]},
{ "rowStyle": "bordered", "cells": [
@@ -12,11 +12,11 @@
{ "cells": [
{ "col": 1, "valueType": "Number(15,3,nonneg)" },
{ "col": 2, "valueType": "String(10,fixed)" },
{ "col": 3, "valueType": "Boolean", "control": "checkbox" }
{ "col": 3, "valueType": "Boolean", "controlType": "checkbox" }
]},
{ "cells": [
{ "col": 1, "valueType": "" },
{ "col": 2, "valueType": "Number(10,2)", "control": "none" },
{ "col": 2, "valueType": "Number(10,2)", "controlType": "none" },
{ "col": 3, "valueType": "Boolean + CatalogRef.Валюты + String + DateTime" }
]},
{ "cells": [
@@ -6,7 +6,7 @@
"areas": [
{
"name": "Ввод",
"rows": [[{ "valueType": "Number(15,3,nonneg)" }, { "valueType": "String(10,fixed)" }, { "valueType": "Boolean", "control": "checkbox" }], [{ "valueType": "" }, { "valueType": "Number(10,2)", "control": "none" }, { "valueType": "Boolean + CatalogRef.Валюты + String + DateTime" }], [{ "valueType": "AnyRef" }, { "valueType": "Number(10,2)", "param": "Сумма", "detail": "Расшифровка" }]]
"rows": [[{ "valueType": "Number(15,3,nonneg)" }, { "valueType": "String(10,fixed)" }, { "valueType": "Boolean", "controlType": "checkbox" }], [{ "valueType": "" }, { "valueType": "Number(10,2)", "controlType": "none" }, { "valueType": "Boolean + CatalogRef.Валюты + String + DateTime" }], [{ "valueType": "AnyRef" }, { "valueType": "Number(10,2)", "param": "Сумма", "detail": "Расшифровка" }]]
}
]
}