Files
cc-1c-skills/docs/mxl-dsl-spec.md
T
Nick ShirokovandClaude Opus 5 d002de3a26 docs(mxl): убрать XML-уровень и механику из описания DSL
Продолжение чистки протёкшей реализации.

- «тип заполнения: param → Parameter, text → Text, template → Template» — автор DSL
  ключ fillType не пишет и в выводе mxl-compile его не видит, это имена XML-перечисления.
  Заменено на то, что действительно нужно: содержимое задаётся одним из ключей param /
  text / template, где template — текст со вставками [Параметр]. Раньше синтаксис вставок
  в инструкции не упоминался вовсе, хотя он куда полезнее перечисления. (У mxl-info
  fillType остаётся: там навык объясняет свой собственный вывод.)

- «компилятор создаёт ячейки для ВСЕХ колонок строки» — механика. Оставлен наблюдаемый
  контракт: стиль применяется ко всей ширине строки, оттуда сплошные рамки.

- «заданное имя компилятор разворачивает в именованную область типа строки» — то же самое.
  Теперь сказано, что даёт имя автору: область доступна как ПолучитьОбласть("Имя").

- убран пункт «"|" продолжает ячейку, только если её позиция известна явно». Он ссылался
  на поведение, которого в документации нет (позиция ячеек без col выводится прощающим
  вводом), то есть документированное ограничение опиралось на недокументированную
  механику. Случай закрыт сообщением об ошибке.

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

13 KiB
Raw Blame History

Спецификация 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: позиция уже задана порядком. Число элементов не может превышать 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);
  • несколько наборов колонок (columnsID) — свои ширины у группы строк;
  • объединения, не привязанные к ячейке (по всей высоте или ширине документа);
  • рисунки и картинки, в том числе штрихкоды;
  • цвет текста, цвет фона ячейки, скрытые строки и колонки, отступ;
  • рамка с разным стилем у разных сторон; стили линий кроме сплошной;
  • группировки строк и колонок;
  • колонтитулы, параметры печати, область печати;
  • многоязычные надписи: при разборе берётся первый вариант текста, при генерации язык всегда ru, остальные теряются.

Пересборка макета из DSL — это полная перегенерация, а не точечная правка XML, поэтому diff после round-trip обычно шире фактической доработки.