Инкремент A кампании mxl-roundtrip. Блочная форма DSL не выражала больше половины корпуса: у 34% макетов ERP есть строки вне именованных областей, у 21% нет ни одной области типа Rows. Декомпилятор такие строки терял, а на макетах целиком из Rectangle отдавал areas: [] — компилятор отвечал "Required field 'areas' is missing". На пилоте из 40 макетов это 10 отказов из 26. Что сделано: - имя у блока стало необязательным. Блок без имени — просто кусок сетки; именованную область он не создаёт. Отдельный «плоский режим» не нужен: макет без выразимых блоков это один безымянный блок; - namedAreas — именованные области координатами, для всего, что блоком не ложится (не-Rows и пересекающиеся). Тип области НЕ указывается: он выводится из заданных осей, ровно как в ТабличныйДокумент.Область() — только строки дают полосу строк, только колонки полосу колонок, обе оси прямоугольник. Так нельзя написать противоречие вроде type: Rows с колоночными координатами; - диапазон записывается уже существующей грамматикой DSL (как ключи columnWidths): число или "N-M". Список через запятую запрещён — область непрерывна, платформа разрывную не хранит; - прощающим вводом принимается платформенный адрес "R1C1:R2C2" и правило «0 значит 1»; в документацию не вынесено; - декомпилятор перестал пропускать области не-Rows (там стоял безусловный continue) и режет сетку на блоки детерминированно: непересекающиеся Rows задают границы, дыры становятся безымянными блоками, остальное уходит в namedAreas. Отдельно: именованные элементы теперь эмитятся отсортированными по имени. Платформа хранит их именно так — на выборке 541 макета с несколькими элементами иного порядка нет ни разу. Сортировка ординальная и регистронезависимая; Sort-Object по умолчанию сортирует по текущей культуре и на кириллице дал бы другой порядок. Отсюда дрейф 13 снэпшотов — чистая перестановка, диффы симметричны, число элементов не изменилось. На пилоте отказы areas: [] закрыты полностью (10 → 0), цикл переживают 24 макета вместо 14. Оставшиеся 16 отказов — колоночные раскладки, это инкремент B. Правка на ps1, зазеркалена в py; вывод портов и в компиляции, и в декомпиляции совпадает байт в байт. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
13 KiB
Спецификация MXL DSL — JSON-формат описания табличного документа
Компактный JSON-формат для описания макетов табличных документов 1С (SpreadsheetDocument). Используется навыками /mxl-compile (JSON → XML) и /mxl-decompile (XML → JSON).
Пример
{
"columns": 10,
"defaultWidth": 30,
"columnWidths": { "1": 15, "2-8": 40, "9-10": 50 },
"fonts": {
"default": { "face": "Arial", "size": 10 },
"bold": { "face": "Arial", "size": 10, "bold": true },
"header": { "face": "Arial", "size": 14, "bold": true }
},
"styles": {
"default": {},
"header": { "font": "header", "align": "center" },
"label": { "font": "bold" },
"bordered": { "border": "all" },
"bordered-right": { "border": "all", "align": "right" },
"total-right": { "font": "bold", "border": "top", "align": "right" }
},
"areas": [
{
"name": "Заголовок",
"rows": [
{ "height": 20, "cells": [
{ "col": 1, "span": 10, "style": "header", "param": "ТекстЗаголовка" }
]}
]
},
{
"name": "ШапкаТаблицы",
"rows": [
{ "rowStyle": "bordered", "cells": [
{ "col": 1, "text": "№" },
{ "col": 2, "span": 6, "text": "Наименование" },
{ "col": 9, "text": "Кол-во" },
{ "col": 10, "text": "Сумма" }
]}
]
},
{
"name": "Строка",
"rows": [
{ "rowStyle": "bordered", "cells": [
{ "col": 1, "param": "НомерСтроки" },
{ "col": 2, "span": 6, "param": "Товар", "detail": "Номенклатура" },
{ "col": 9, "style": "bordered-right", "param": "Количество" },
{ "col": 10, "style": "bordered-right", "param": "Сумма" }
]}
]
},
{
"name": "Итого",
"rows": [
{ "cells": [
{ "col": 8, "span": 2, "style": "total-right", "text": "Итого:" },
{ "col": 10, "style": "total-right", "param": "Всего" }
]}
]
}
]
}
Верхний уровень
| Поле | Обяз. | По умолч. | Описание |
|---|---|---|---|
columns |
да | — | Количество колонок |
page |
нет | — | Формат страницы: "A4-landscape" (780), "A4-portrait" (540) или число. Автоматически вычисляет defaultWidth из суммы пропорций "Nx" |
defaultWidth |
нет | 10 | Ширина колонок по умолчанию. Игнорируется если задан page и все колонки используют "Nx" |
columnWidths |
нет | {} |
Ширины колонок. Ключи 1-based: "1", "3-14", "5,7,9". Значения: число (абсолют) или "Nx" (множитель от defaultWidth, напр. "2x", "0.5x") |
fonts |
нет | — | Именованные шрифты (если не задано, создаётся Arial 10) |
styles |
нет | {} |
Именованные стили |
areas |
да | — | Массив блоков строк (порядок = порядок в документе); имя у блока необязательно |
namedAreas |
нет | — | Именованные области, заданные координатами (см. ниже) |
Шрифты (fonts.<name>)
| Поле | По умолч. | Описание |
|---|---|---|
face |
"Arial" |
Имя шрифта |
size |
10 |
Размер |
bold |
false |
Жирный |
italic |
false |
Курсив |
underline |
false |
Подчёркнутый |
strikeout |
false |
Зачёркнутый |
Шрифт "default" используется когда стиль не указывает шрифт явно. Если не определён, создаётся автоматически (Arial 10).
Стили (styles.<name>)
| Поле | По умолч. | Описание |
|---|---|---|
font |
"default" |
Ссылка на имя шрифта |
align |
— | left, center, right |
valign |
— | top, center |
border |
— | Стороны рамки: all, top, bottom, left, right, none. Через запятую: "top,bottom" |
borderWidth |
"thin" |
Толщина рамки: thin (1px) или thick (2px) |
wrap |
false |
Перенос текста |
format |
— | Формат данных 1С: "ЧЦ=15; ЧДЦ=2", "ДФ=dd.MM.yyyy" и т.д. |
Области (areas[])
| Поле | Обяз. | Описание |
|---|---|---|
name |
нет | Имя области для Макет.ПолучитьОбласть("Имя") |
rows |
да | Массив строк |
Макет собирается из блоков строк, идущих подряд. Имя на блоке — сокращение: компилятор разворачивает его в именованную область типа «строки» на диапазон блока. Блок без имени — просто кусок сетки: так описываются строки, не принадлежащие ни одной именованной области.
Именованные области координатами (namedAreas[])
Для областей, которые блоком не выражаются: не привязанных к диапазону строк (полоса колонок, прямоугольник, ячейка) и пересекающихся с другими.
| Поле | Обяз. | Описание |
|---|---|---|
name |
да | Имя области |
rows |
* | Строки: число или диапазон "N-M", 1-based |
cols |
* | Колонки: число или диапазон "N-M", 1-based |
* Обязательна хотя бы одна из осей.
Тип области не указывается — он следует из того, какие оси заданы, как в ТабличныйДокумент.Область(): только строки → полоса строк, только колонки → полоса колонок, обе оси → прямоугольник, одиночные значения по обеим осям → одна ячейка.
"namedAreas": [
{ "name": "ОбластьПечатиПоВысоте", "rows": "1-48" },
{ "name": "ОбластьПечатиПоШирине", "cols": "1-35" },
{ "name": "HZY", "rows": 9, "cols": "16-17" }
]
Диапазон — та же грамматика, что у columnWidths, но только число или "N-M": список через запятую запрещён, область непрерывна.
Ошибки (stderr, код возврата 1):
| Условие | Сообщение |
|---|---|
нет name |
namedAreas: 'name' is required: … |
| не задана ни одна ось | namedAreas: at least one of 'rows'/'cols' is required: … |
| список через запятую | namedAreas: 'cols' must be a single number or range, got list "…": … |
| диапазон задом наперёд | namedAreas: 'rows' range is reversed "…": … |
Порядок именованных элементов в выходном XML — по имени: так их хранит платформа, компилятор сортирует сам.
Строки (rows[])
| Поле | По умолч. | Описание |
|---|---|---|
height |
— | Высота строки (если не задана, используется авто) |
rowStyle |
— | Стиль для ВСЕХ колонок (заполняет пустоты рамками) |
cells |
[] |
Массив ячеек |
empty |
— | Количество подряд идущих пустых строк (заменяет N отдельных {}) |
Строка без cells и rowStyle → пустая строка. { "empty": 3 } эквивалентно трём {}.
Короткая форма: строка массивом
Вместо объекта строка может быть массивом ячеек — позиция определяется порядком, col не указывается.
| Элемент | Значение |
|---|---|
"текст" |
Статический текст (text) |
"{Имя}" |
Параметр (param) |
">" |
Продолжение ячейки слева — увеличивает её span |
| `" | "` |
null |
Пустая колонка: позиция занята, ячейка не создаётся |
{ ... } |
Обычная ячейка без col; нужна для style, detail, template |
"rows": [
["Вид", "Остаток", ">", "Итог"],
["|", "начало", "конец", "|"],
["{Вид}", "{Нач}", "{Кон}", "{Итог}"]
]
Здесь «Вид» и «Итог» объединены по вертикали на две строки, «Остаток» — по горизонтали на две колонки.
Ограничения короткой формы:
- не задать
heightиrowStyle— это свойства строки, а не ячейки; - не выразить текст, совпадающий с
">","|"или с шаблоном"{...}"; "|"продолжает ячейку из предыдущей строки, только если её позиция известна явно (colзадан или строка записана массивом).
Ошибки короткой формы (stderr, код возврата 1):
| Условие | Сообщение |
|---|---|
">" без ячейки слева |
Row shorthand: '>' has no cell to the left: area "…", row N, cell M |
| `" | "` без ячейки сверху |
объектный элемент с col |
Row shorthand: cell object must not carry 'col': area "…", row N, cell M |
элементов больше columns |
Row exceeds 'columns' (K): area "…", row N |
Ячейки (cells[])
| Поле | Обяз. | По умолч. | Описание |
|---|---|---|---|
col |
да | — | Позиция колонки (1-based). В короткой форме строки не указывается — позиция берётся из порядка |
span |
нет | 1 |
Объединение по горизонтали (количество колонок) |
rowspan |
нет | 1 |
Объединение по вертикали (количество строк) |
style |
нет | rowStyle | Стиль ячейки (переопределяет rowStyle) |
param |
нет | — | Параметр заполнения |
detail |
нет | — | Параметр расшифровки (только с param) |
text |
нет | — | Статический текст |
template |
нет | — | Шаблонный текст с [Параметр] |
Тип заполнения
Определяется автоматически по содержимому ячейки:
param→ fillType=Parametertemplate→ fillType=Templatetext→ fillType=Text- ничего → без fillType (пустая ячейка или рамка)
rowStyle — автозаполнение
Когда задан rowStyle, компилятор создаёт ячейки для ВСЕХ колонок строки. Позиции без явных ячеек заполняются пустыми ячейками с указанным стилем. Это обеспечивает сплошные рамки в табличных строках.
Если в предыдущих строках той же области есть ячейки с rowspan, их колонки при автозаполнении пропускаются.
Ограничения
Текущая версия не поддерживает:
- Множественные наборы колонок (
columnsID) - Области типа Columns / Rectangle
- Рисунки (штрихкоды, картинки)
- Фон ячеек