feat(mxl-compile,mxl-decompile,mxl-validate): ячейки-поля ввода

Тип значения ячейки и элемент управления переживают цикл компиляции и
декомпиляции. Макет стенда с полями ввода собирается из своего же JSON
байт в байт.

DSL: два ключа ячейки — valueType (грамматика типа семьи: примитивы с
квалификаторами, ссылочные типы, категории целиком, составной через " + ")
и control (input/checkbox, синонимы, GUID для неизвестных элементов, none
для формата вовсе без тега). containsValue отдельным ключом не выражается:
он выводится из наличия типа. Текст и шаблон в такой ячейке запрещены,
параметр и расшифровка допустимы.

Умолчания голых типов взяты платформенные (строка без длины безлимитна,
число без параметров без ограничения разрядности), поэтому эмиттер типа
свой, а не копия meta-compile; resolve_type_str скопирован из эталона
семьи и объявлен в реестре дрейфа. Канон типа в ключе дедупликации
палитры развёрнут: иначе разные написания одного типа дали бы две
одинаковые записи формата и сдвинули бы все ссылки ячеек.

mxl-validate: проверка согласованности таких форматов — тип без признака
значения, ячейка с текстом и значением одновременно, посторонний тег
внутри типа, формат значения у строки или колонки, неизвестный GUID
элемента управления.

Попутно сведены два расхождения портов mxl-validate: py молчал там, где
ps1 писал строку об отсутствии шрифтов, и шапка подробного вывода
печаталась в разной форме.

Версии сведены: mxl-compile 1.41 в обоих портах (было 1.40/1.39).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-14 22:21:59 +03:00
co-authored by Claude Opus 5
parent 83bb5b6fd3
commit 7f743b18a9
37 changed files with 2471 additions and 26 deletions
+78
View File
@@ -513,6 +513,84 @@ pictureSizeMode · picHorizontalAlignment · picVerticalAlignment · textPositio
каждой ячейки (`backColor`: 13 899 ячеек повторяют против 96). Исключение — `hidden`: оно
остаётся только у строки (24 026 против 62 856).
### Ячейка-поле ввода: `containsValue` / `valueType` / `controlType`
Ячейка может содержать не текст, а редактируемое значение. Три тега формата описывают это
целиком:
```xml
<format>
<containsValue>true</containsValue>
<valueType>
<v8:Type>xs:decimal</v8:Type>
<v8:NumberQualifiers>
<v8:Digits>15</v8:Digits>
<v8:FractionDigits>3</v8:FractionDigits>
<v8:AllowedSign>Nonnegative</v8:AllowedSign>
</v8:NumberQualifiers>
</valueType>
<controlType>381ed624-9217-4e63-85db-c4c3cb87daae</controlType>
</format>
```
Свойство принадлежит ЯЧЕЙКЕ, хотя и живёт в общей палитре: из 370 197 ссылок на такие записи
(корпус ERP, 5 809 макетов из 10 924) все до одной идут из `<f>` — ни строка, ни колонка, ни
`<defaultFormatIndex>` на них не ссылаются ни разу.
| Наблюдение | Данные корпуса |
|---|---|
| `containsValue` всегда `true` | 63 726 форматов, других значений нет |
| `valueType` присутствует всегда | 0 форматов без него; 12 — с ПУСТЫМ `<valueType/>` (тип не ограничен) |
| текста у такой ячейки не бывает | 0 из 370 197 несут `<tl>` |
| `<parameter>` и `<detailParameter>` — бывают | 3 219 и 2 278 |
| `fillType` у формата со значением недостоверен | 94 062 записи несут `Text` при полном отсутствии текста — след прежнего состояния, как `width` |
**Элемент управления** задаётся GUID; имён в XML нет вовсе. В Конфигураторе это «ЭлементУправления»
со значениями «Поле ввода» и «Поле флажка»:
| GUID | Элемент | Вхождений |
|---|---|---:|
| `381ed624-9217-4e63-85db-c4c3cb87daae` | Поле ввода | 63 629 |
| `35af3d93-d7c7-4a2e-a8eb-bac87a1a3f26` | Поле флажка | 7 |
Умолчание — поле ввода, и оно же стоит у Булево: из 664 булевых форматов флажок выбран в семи.
У 90 форматов (22 макета регламентированной отчётности, явно машинно-сгенерированных) тега
`<controlType>` нет вовсе.
**Структура `<valueType>`** — то же описание типов, что в метаданных: сначала все `<v8:Type>` и
`<v8:TypeSet>` в порядке источника, затем блоки квалификаторов в порядке Number → String → Date.
Голая категория без имени объекта (`CatalogRef`, `AnyRef`) — это `<v8:TypeSet>`, а не `<v8:Type>`.
Ссылочные типы несут **локальное объявление пространства имён на каждом узле**:
```xml
<v8:Type xmlns:d4p1="http://v8.1c.ru/8.1/data/enterprise/current-config">d4p1:CatalogRef.Валюты</v8:Type>
```
Префикс всегда `d4p1` (15 вхождений на корпусе, отклонений нет) — независимо от того, есть ли
в макете цвета web-палитры, которым платформа даёт `d3p1`. Корень `<document>` пространство
current-config не объявляет, поэтому вынести объявление наверх нельзя.
**Продолжение конструкции — на уровне САМОЙ ячейки**, а не палитры:
```xml
<c>
<f>34</f>
<v xsi:type="xs:decimal">0</v>
<control xsi:type="xs:base64Binary">77u/MiwxLDM4MWVkNjI0…</control>
</c>
```
| Тег ячейки | Смысл | Вхождений | Макетов |
|---|---|---:|---:|
| `<v>` | сохранённое значение ячейки; `xsi:type` соответствует объявленному типу (decimal 153 566, string 61 203, dateTime 3 333, boolean 1 012) | 219 114 | 4 578 |
| `<control>` | сериализованные настройки элемента управления (base64; внутри — тот же GUID и структура вида маски/списка выбора) | 26 370 | 1 246 |
Оба тега встречаются ИСКЛЮЧИТЕЛЬНО в ячейках, чей формат несёт `containsValue` — ни одного
вхождения в обычной ячейке. То есть это вторая половина той же конструкции, а не отдельное
свойство. Обрати внимание на совпадение имён: `<control>` у ячейки и `<controlType>` в формате —
разные вещи.
**Ловушка: `width` в формате ЯЧЕЙКИ не описывает ячейку.** Ссылка ячейки на запись палитры не
обновляется при изменении ширины колонки, поэтому там остаётся ширина от прежнего состояния
документа. Проверено на контролируемом стенде: в макете, где ширины колонок поменяли на