Files
cc-1c-skills/docs/mxl-dsl-spec.md
T
Nick ShirokovandClaude Opus 5 26b38e2ee3 docs(mxl): колоночные раскладки в описании DSL
Инкремент B изменил DSL, а документация осталась от предыдущей версии.

Добавлены columnSets в карту структуры и в таблицу верхнего уровня, раздел про
колоночные раскладки со ссылкой columnSet у области, оговорка что columns: 0 —
допустимая величина (все строки живут в именованных раскладках) и что позиции
колонок проверяются по ширине раскладки своей области.

Из ограничений убран пункт про несколько наборов колонок: теперь поддержаны.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 19:21:36 +03:00

252 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Спецификация MXL DSL — JSON-формат описания табличного документа
Компактный JSON-формат для описания макетов табличных документов 1С (SpreadsheetDocument). Используется навыками `/mxl-compile` (JSON → XML) и `/mxl-decompile` (XML → JSON).
## Пример
```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` | да | — | Количество колонок в раскладке по умолчанию. `0` допустимо: значит, все строки живут в раскладках из `columnSets` |
| `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` | нет | — | Именованные области, заданные координатами (см. ниже) |
| `columnSets` | нет | — | Дополнительные колоночные раскладки: своя ширина колонок у группы строк (см. ниже) |
## Шрифты (`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 |
\* Обязательна хотя бы одна из осей.
**Тип области не указывается** — он следует из того, какие оси заданы, как в `ТабличныйДокумент.Область()`: только строки → полоса строк, только колонки → полоса колонок, обе оси → прямоугольник, одиночные значения по обеим осям → одна ячейка.
```json
"namedAreas": [
{ "name": "ОбластьПечатиПоВысоте", "rows": "1-48" },
{ "name": "ОбластьПечатиПоШирине", "cols": "1-35" },
{ "name": "HZY", "rows": 9, "cols": "16-17" }
]
```
Диапазон — та же грамматика, что у `columnWidths`, но **только** число или `"N-M"`: список через запятую запрещён, область непрерывна. Имя обязательно, и хотя бы одна ось должна быть задана; нарушение любого из этих правил → ненулевой код выхода и сообщение в stderr.
## Колоночные раскладки (`columnSets`)
Группа строк может иметь собственные ширины колонок — в 1С это «индивидуальная ширина колонок». Документные `columns` и `columnWidths` описывают раскладку по умолчанию; дополнительные объявляются в `columnSets`, а область ссылается на нужную ключом `columnSet` — так же, как ячейка ссылается на `styles` через `style`.
```json
{
"columns": 52,
"columnWidths": { "1": 8 },
"columnSets": {
"таблица": { "columns": 52, "columnWidths": { "1": 7, "2-52": 24 } }
},
"areas": [
{ "name": "Шапка", "rows": [ ... ] },
{ "name": "ТабличнаяЧасть", "columnSet": "таблица", "rows": [ ... ] }
]
}
```
Раскладка описывается той же парой полей, что и документная: `columns` — количество колонок (у раскладок оно обычно разное), `columnWidths` — ширины. Ключ словаря — имя раскладки; в макетах, полученных через `/mxl-decompile`, это идентификатор из исходного файла, при описании с нуля — любая строка.
Все строки области получают раскладку области, поэтому одна область не может смешивать раскладки. Позиции колонок (`col`, `span`) проверяются по ширине раскладки СВОЕЙ области, а не документной.
Ссылка на необъявленную раскладку → ненулевой код выхода и сообщение в stderr.
## Строки (`rows[]`)
| Поле | По умолч. | Описание |
|------|-----------|----------|
| `height` | — | Высота строки (если не задана, используется авто) |
| `rowStyle` | — | Стиль для ВСЕХ колонок (заполняет пустоты рамками) |
| `cells` | `[]` | Массив ячеек |
| `empty` | — | Количество подряд идущих пустых строк (заменяет N отдельных `{}`) |
Строка без `cells` и `rowStyle` → пустая строка. `{ "empty": 3 }` эквивалентно трём `{}`.
### Короткая форма: строка массивом
Вместо объекта строка может быть массивом ячеек — позиция определяется порядком, `col` не указывается.
| Элемент | Значение |
|---------|----------|
| `"текст"` | Статический текст (`text`) |
| `"{Имя}"` | Параметр (`param`) |
| `">"` | Продолжение ячейки слева — увеличивает её `span` |
| `"|"` | Продолжение ячейки сверху — увеличивает её `rowspan` |
| `null` | Пустая колонка: позиция занята, ячейка не создаётся |
| `{ ... }` | Обычная ячейка **без** `col`; нужна для `style`, `detail`, `template` |
```json
"rows": [
["Вид", "Остаток", ">", "Итог"],
["|", "начало", "конец", "|"],
["{Вид}", "{Нач}", "{Кон}", "{Итог}"]
]
```
Здесь «Вид» и «Итог» объединены по вертикали на две строки, «Остаток» — по горизонтали на две колонки.
Ограничения короткой формы:
- не задать `height` и `rowStyle` — это свойства строки, а не ячейки;
- не выразить текст, совпадающий с `">"`, `"|"` или с шаблоном `"{...}"`.
Маркеру нужно, что продолжать: `">"` требует ячейку слева в той же строке, `"|"` — ячейку сверху. Объектный элемент не должен нести `col`: позиция уже задана порядком. Число элементов не может превышать `columns`. Нарушение любого из этих правил → ненулевой код выхода и сообщение в stderr.
## Ячейки (`cells[]`)
| Поле | Обяз. | По умолч. | Описание |
|------|:-----:|-----------|----------|
| `col` | да | — | Позиция колонки (1-based). В короткой форме строки не указывается — позиция берётся из порядка |
| `span` | нет | `1` | Объединение по горизонтали (количество колонок) |
| `rowspan` | нет | `1` | Объединение по вертикали (количество строк) |
| `style` | нет | rowStyle | Стиль ячейки (переопределяет rowStyle) |
| `param` | нет | — | Параметр заполнения |
| `detail` | нет | — | Параметр расшифровки (только с `param`) |
| `text` | нет | — | Статический текст |
| `template` | нет | — | Шаблонный текст с `[Параметр]` |
### Содержимое ячейки
Задаётся ровно одним из ключей, объявлять способ заполнения отдельно не нужно:
- `param` — параметр заполнения;
- `template` — текст со вставками `[Параметр]`;
- `text` — статический текст;
- ничего — пустая ячейка (нужна, например, ради рамки).
## `rowStyle` — автозаполнение
Стиль применяется ко ВСЕЙ ширине строки: позиции без явных ячеек получают тот же стиль. Так в табличных строках получаются сплошные рамки.
Если в предыдущих строках той же области есть ячейки с `rowspan`, их колонки при автозаполнении пропускаются.
## Ограничения
DSL описывает не все конструкции табличного документа. Перечисленное ниже **теряется при
round-trip** (`/mxl-decompile``/mxl-compile`): в JSON оно не попадает, в сгенерированный
XML не возвращается.
- ячейки-поля ввода (`containsValue` / `valueType` / `controlType`);
- объединения, не привязанные к ячейке (по всей высоте или ширине документа);
- рисунки и картинки, в том числе штрихкоды;
- цвет текста, цвет фона ячейки, скрытые строки и колонки, отступ;
- рамка с разным стилем у разных сторон; стили линий кроме сплошной;
- группировки строк и колонок;
- колонтитулы, параметры печати, область печати;
- многоязычные надписи: при разборе берётся первый вариант текста, при генерации язык
всегда `ru`, остальные теряются.
Пересборка макета из DSL — это полная перегенерация, а не точечная правка XML, поэтому
diff после round-trip обычно шире фактической доработки.