Раздел ограничений врал в обе стороны. Он обещал потерю областей Columns и Rectangle — они поддержаны предыдущим коммитом; и молчал про то, что теряется на самом деле. Проверено по коду обоих навыков, доли — по корпусу ERP 8.3.24: ячейки-поля ввода (53% макетов), несколько наборов колонок (63%), объединения вне ячеек (16%), рисунки (2%), цвета, скрытые строки, отступ, посторонние стили линий, группировки, колонтитулы и параметры печати. Отдельно записано, что многоязычные надписи не поддерживаются: при разборе берётся первый вариант текста, при генерации язык всегда ru — для двуязычных макетов остальные языки теряются. Заодно убрано то, что описывает реализацию, а не использование: - таблицы с точными текстами сообщений об ошибках и кодом возврата. Модель, вызвавшая навык, видит и текст, и код прямо в выводе; документировать их незачем, а протухают они молча — ровно как протух раздел ограничений. Правила, из-за которых ошибка возникает, остались; сами строки зафиксированы в кейсах через expectError, где расхождение ловится механически. В остальных пяти спеках таких таблиц и не было — там принята одна фраза «ненулевой код выхода и сообщение в stderr»; - фраза про порядок эмиссии именованных элементов: автор DSL на него не влияет. Сам факт (платформа хранит их отсортированными по имени) перенесён в docs/1c-spreadsheet-spec.md, где описывается XML-уровень, вместе с оговоркой, что случай с «ё» не проверен. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
14 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.
Строки (rows[])
| Поле | По умолч. | Описание |
|---|---|---|
height |
— | Высота строки (если не задана, используется авто) |
rowStyle |
— | Стиль для ВСЕХ колонок (заполняет пустоты рамками) |
cells |
[] |
Массив ячеек |
empty |
— | Количество подряд идущих пустых строк (заменяет N отдельных {}) |
Строка без cells и rowStyle → пустая строка. { "empty": 3 } эквивалентно трём {}.
Короткая форма: строка массивом
Вместо объекта строка может быть массивом ячеек — позиция определяется порядком, col не указывается.
| Элемент | Значение |
|---|---|
"текст" |
Статический текст (text) |
"{Имя}" |
Параметр (param) |
">" |
Продолжение ячейки слева — увеличивает её span |
| `" | "` |
null |
Пустая колонка: позиция занята, ячейка не создаётся |
{ ... } |
Обычная ячейка без col; нужна для style, detail, template |
"rows": [
["Вид", "Остаток", ">", "Итог"],
["|", "начало", "конец", "|"],
["{Вид}", "{Нач}", "{Кон}", "{Итог}"]
]
Здесь «Вид» и «Итог» объединены по вертикали на две строки, «Остаток» — по горизонтали на две колонки.
Ограничения короткой формы:
- не задать
heightиrowStyle— это свойства строки, а не ячейки; - не выразить текст, совпадающий с
">","|"или с шаблоном"{...}"; "|"продолжает ячейку из предыдущей строки, только если её позиция известна явно (colзадан или строка записана массивом).
">" без ячейки слева, "|" без ячейки сверху, объектный элемент с col, элементов больше columns → ненулевой код выхода и сообщение в stderr.
Ячейки (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, их колонки при автозаполнении пропускаются.
Ограничения
DSL описывает не все конструкции табличного документа. Перечисленное ниже теряется при
round-trip (/mxl-decompile → /mxl-compile): в JSON оно не попадает, в сгенерированный
XML не возвращается. Доля — по корпусу типовой ERP 8.3.24 (10 924 макета), где измерялась.
| Конструкция | Доля макетов |
|---|---|
Ячейки-поля ввода (containsValue / valueType / controlType) |
53% |
Несколько наборов колонок (columnsID) — свои ширины у группы строк |
63% |
| Объединения, не привязанные к ячейке (по всей высоте или ширине) | 16% |
| Рисунки и картинки (в т.ч. штрихкоды) | 2% |
| Цвет текста, цвет фона ячейки, скрытые строки/колонки, отступ | — |
| Рамка с разным стилем у разных сторон; стили линий кроме сплошной | — |
| Группировки строк и колонок | — |
| Колонтитулы, параметры печати, область печати | — |
Многоязычные надписи не поддерживаются: при разборе берётся первый вариант текста,
при генерации язык всегда ru. Для двуязычных макетов (в ERP это почти весь корпус)
надписи на остальных языках теряются.
Отдельно: пересборка макета из DSL — это полная перегенерация, а не точечная правка XML, поэтому diff после round-trip обычно шире фактической доработки.