Files
cc-1c-skills/docs/mxl-dsl-spec.md
T
Nick ShirokovandClaude Opus 5 241a56a29f docs(mxl): актуализировать спецификации после серии находок на стенде
Спецификация XML — дописано то, что вскрыли контролируемые макеты и замеры
по корпусу:

- шрифт-ссылка на СИСТЕМНЫЙ шрифт: префикс sys в корне не объявлен, поэтому
  объявление xmlns дописывается прямо на узел. Плюс правило вывода kind
  из префикса и то, что неиспользуемый шрифт в палитру не попадает;
- новый раздел «Устройство палитр»: порядок документный и НЕ зависит от
  последовательности действий автора (проверено опытом с оформлением снизу
  вверх), формат по умолчанию последний, палитра дедуплицирована по содержимому;
- у текста ячейки ТРИ состояния: тега нет, тег с элементами, пустой <tl/>.
  Третье — 57% макетов корпуса;
- языковые настройки: набор языков не выводится из языков текста, description
  бывает самозакрывающимся, currentLanguage бывает отсутствующим и бывает
  указывающим на необъявленный язык.

Спецификация DSL — из ограничений убрано объявление языков макета: оно больше
не теряется. Добавлено пояснение, почему побайтовое совпадение достижимо не на
любом макете: в долго правленных макетах остаются следы прежних состояний,
которые из итогового документа не выводятся.

В инструкции навыка отражена только форма шрифта-ссылки — остальное из этой
серии либо уже там, либо для авторинга не нужно.

Примеры из справочника скомпилированы и проверены валидатором.

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

242 lines
16 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).
Оформление — шрифты, стили, цвета, рамки, колоночные раскладки — в `mxl-dsl-styles.md`;
полный перечень свойств стиля — в `mxl-dsl-format-properties.md`.
## Пример
```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", "horizontalAlignment": "Center" },
"label": { "font": "bold" },
"bordered": { "border": "Solid" },
"bordered-right": { "border": "Solid", "horizontalAlignment": "Right" },
"total-right": { "font": "bold", "topBorder": "Solid", "horizontalAlignment": "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"`) |
| `columnStyles` | нет | — | Оформление колонок: те же ключи, значение — имя стиля (см. `mxl-dsl-styles.md`) |
| `textLanguages` | нет | `["ru"]` | Языки, на которых пишется текст, заданный строкой (см. ниже) |
| `fonts` | нет | — | Именованные шрифты (если не задано, создаётся Arial 10) |
| `styles` | нет | `{}` | Именованные стили (см. `mxl-dsl-styles.md`) |
| `areas` | да | — | Массив областей — диапазонов подряд идущих строк (порядок = порядок в документе); имя необязательно |
| `namedAreas` | нет | — | Именованные области, заданные координатами (см. ниже) |
| `columnSets` | нет | — | Дополнительные колоночные раскладки (см. `mxl-dsl-styles.md`) |
## Области (`areas[]`)
| Поле | Обяз. | Описание |
|------|:-----:|----------|
| `name` | нет | Имя области для `Макет.ПолучитьОбласть("Имя")` |
| `columnSet` | нет | Ссылка на раскладку из `columnSets` |
| `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.
## Строки (`rows[]`)
| Поле | По умолч. | Описание |
|------|-----------|----------|
| `height` | — | Высота строки (если не задана, используется авто) |
| `hidden` | `false` | Скрыть строку |
| `rowStyle` | — | Стиль строки: ложится и на саму строку, и на ВСЕ её колонки (заполняет пустоты рамками) |
| `cells` | `[]` | Массив ячеек |
| `empty` | — | Количество подряд идущих пустых строк (заменяет N отдельных `{}`) |
Строка без `cells` и `rowStyle` → пустая строка. `{ "empty": 3 }` эквивалентно трём `{}`.
`height` и `hidden` — собственные свойства строки: у ячейки таких нет, и в её оформление они
не попадают. Всё остальное оформление строки задаётся через `rowStyle`.
### Короткая форма: строка массивом
Вместо объекта строка может быть массивом ячеек — позиция определяется порядком, `col` не указывается.
| Элемент | Значение |
|---------|----------|
| `"текст"` | Статический текст (`text`) |
| `{ "ru": "…", "en": "…" }` | Тот же текст на нескольких языках |
| `"{Имя}"` | Параметр (`param`) |
| `">"` | Продолжение ячейки слева — увеличивает её `span` |
| `"|"` | Продолжение ячейки сверху — увеличивает её `rowspan` |
| `null` | Пустая колонка: позиция занята, ячейка не создаётся |
| `{ ... }` | Обычная ячейка **без** `col`; нужна для `style`, `detail`, `template` |
Объект-элемент трактуется по его ключам: если среди них есть ключ ячейки (`span`, `rowspan`,
`style`, `param`, `detail`, `text`, `template`) — объект описывает свойства ячейки. Иначе он
целиком считается её текстом, а его ключи — идентификаторами языков.
```json
"rows": [
["Вид", "Остаток", ">", "Итог"],
["|", "начало", "конец", "|"],
["{Вид}", "{Нач}", "{Кон}", "{Итог}"]
]
```
Здесь «Вид» и «Итог» объединены по вертикали на две строки, «Остаток» — по горизонтали на две колонки.
Ограничения короткой формы:
- не задать `height` и `rowStyle` — это свойства строки, а не ячейки;
- не выразить текст, совпадающий с `">"`, `"|"` или с шаблоном `"{...}"`.
Маркеру нужно, что продолжать: `">"` требует ячейку слева в той же строке, `"|"` — ячейку сверху. Объектный элемент не должен нести `col`: позиция уже задана порядком. Число элементов не может превышать `columns`. Нарушение любого из этих правил → ненулевой код выхода и сообщение в stderr.
## Ячейки (`cells[]`)
| Поле | Обяз. | По умолч. | Описание |
|------|:-----:|-----------|----------|
| `col` | да | — | Позиция колонки (1-based). В короткой форме строки не указывается — позиция берётся из порядка |
| `span` | нет | `1` | Объединение по горизонтали (количество колонок) |
| `rowspan` | нет | `1` | Объединение по вертикали (количество строк) |
| `style` | нет | rowStyle | Стиль ячейки (переопределяет rowStyle) |
| `param` | нет | — | Параметр заполнения |
| `detail` | нет | — | Параметр расшифровки (только с `param`) |
| `text` | нет | — | Статический текст. Строка или объект `{ ru, en }` — см. ниже |
| `template` | нет | — | Шаблонный текст с `[Параметр]`. Строка или объект, как `text` |
### Содержимое ячейки
Задаётся ровно одним из ключей, объявлять способ заполнения отдельно не нужно:
- `param` — параметр заполнения;
- `template` — текст со вставками `[Параметр]`;
- `text` — статический текст;
- ничего — пустая ячейка (нужна, например, ради рамки).
### Текст на нескольких языках
`text` и `template` принимают строку или объект «язык → текст». Объект даёт по надписи на каждый язык, в порядке ключей. Строка означает один и тот же текст на всех языках макета — по умолчанию только русский.
```json
{ "col": 1, "text": "Наименование" }
{ "col": 2, "text": { "ru": "Поставщик", "en": "Supplier" } }
```
Набор языков задаётся документным ключом `textLanguages`:
```json
{ "columns": 3, "textLanguages": ["ru", "en"], "areas": [] }
```
С таким объявлением `"Наименование"` из примера выше даст надпись и под `ru`, и под `en`.
Ключ ни на что в конфигурации не смотрит — это просто список языков, на которые разворачивается строка.
Пустая строка — это текст: ячейка с `"text": ""` даёт пустую надпись, а не ячейку без текста.
## `rowStyle` — оформление строки
Стиль применяется ко ВСЕЙ ширине строки: позиции без явных ячеек получают тот же стиль. Так в табличных строках получаются сплошные рамки. Он же становится оформлением самой строки — именно так платформа хранит строку, оформленную целиком.
Стиль конкретной ячейки (`style`) перекрывает `rowStyle` для этой ячейки.
Если в предыдущих строках той же области есть ячейки с `rowspan`, их колонки при автозаполнении пропускаются.
## Ограничения
DSL описывает не все конструкции табличного документа. Перечисленное ниже **теряется при
round-trip** (`/mxl-decompile``/mxl-compile`): в JSON оно не попадает, в сгенерированный
XML не возвращается.
- ячейки-поля ввода (`containsValue` / `valueType` / `controlType`);
- объединения, не привязанные к ячейке (по всей высоте или ширине документа);
- рисунки и картинки, в том числе штрихкоды, и примечания к ячейкам;
- группировки строк и колонок;
- колонтитулы, параметры печати, область печати.
Пересборка макета из DSL — это полная перегенерация, а не точечная правка XML, поэтому
diff после round-trip обычно шире фактической доработки.
Отдельно про побайтовое совпадение. В макетах, которые долго правили в Конфигураторе,
встречаются следы прежних состояний: формат ячейки может нести ширину колонки, которая с тех
пор изменилась. Такие значения не описывают итоговый документ и из него не выводятся, поэтому
собранный XML совпадёт с исходным не всегда — при полностью сохранённом содержании.