docs(mxl-compile,mxl-decompile): каскад инструкций — файл на задачу

Каскад повторял спецификацию: reference/dsl-spec.md был её копией, а styles
и format-properties — копиями двух других файлов документации. Модель, чтобы
что-то сделать, читала спеку целиком.

Теперь в SKILL.md лежит то, что нужно почти всегда: компактный пример
печатной формы, структура DSL, области, строки, ячейки с короткой формой,
rowStyle и оформление из десяти частых ключей. Остальное — по файлу на
задачу: layout, print, drawings, input-cells, groups, notes,
style-properties, каждый 26-81 строка; читать нужно только свой.

Состав ядра выбран по частоте в обычных макетах (корпус без регламентированной
отчётности, которая перекашивала статистику): шрифт 93%, выравнивание 88/87%,
размещение текста 86%, рамки 57-72%, формат 52%; поля ввода и группы, наоборот,
оказались редкими — 7%.

В mxl-decompile переехало то, что относится к чтению чужого макета, а не
к авторингу: пересборка — полная перегенерация, побайтового совпадения ждать
не всегда стоит, и перечень конструкций, которые цикл не переживают.
This commit is contained in:
Nick Shirokov
2026-08-17 12:51:53 +03:00
parent da76bb6f01
commit 93ced4b239
11 changed files with 469 additions and 651 deletions
+165 -44
View File
@@ -41,59 +41,131 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.ps1" -J
**Если макет создаётся по изображению** (скриншот, скан печатной формы) — сначала вызвать `/img-grid` для наложения сетки, по ней определить границы колонок и пропорции, затем использовать `"Nx"` ширины + `"page"` для автоматического расчёта размеров.
## JSON-схема DSL
## Что читать под задачу
Ниже — компактная структура и ключевые правила, достаточные для типового макета. Подробности читать по необходимости:
Ниже — всё, что нужно для типового макета. Остальное лежит по файлу на задачу, читать нужно
только свой:
| Что нужно | Файл |
| Задача | Файл |
|---|---|
| Полные таблицы полей, развёрнутый пример, ограничения формата | `reference/dsl-spec.md` |
| Шрифты, стили, цвета, рамки, колоночные раскладки и стили колонок | `reference/styles.md` |
| Полный перечень свойств стиля | `reference/format-properties.md` |
| Свойство стиля вне частых: отступ, защита, узор, маска, формат редактирования | `reference/style-properties.md` |
| Область, не описываемая диапазоном строк; свои ширины колонок у части документа | `reference/layout.md` |
| Колонтитулы, ориентация, поля, масштаб | `reference/print.md` |
| Картинка, фигура или надпись поверх сетки; картинка в ячейке | `reference/drawings.md` |
| Ячейки для ввода данных пользователем | `reference/input-cells.md` |
| Сворачиваемые группы строк или колонок | `reference/groups.md` |
| Всплывающая подсказка у ячейки | `reference/notes.md` |
Краткая структура:
## Пример
```
{ columns, page, defaultWidth, columnWidths, columnStyles,
fonts: { name: { face, size, bold, italic, underline, strikeout } | { ref } },
styles: { name: { font, horizontalAlignment, verticalAlignment, textPlacement,
backColor, textColor, border, borderColor, format, hidden } },
areas: [{ name, columnSet, rows: [{ height, hidden, rowStyle, cells: [
{ col, span, rowspan, style, param, detail, text, template, valueType, controlType, value, note }
]}]}],
namedAreas: [{ name, rows, cols }],
rowGroups: [{ rows, name, collapsed, titleLocation }],
columnGroups: [{ cols, name, collapsed, titleLocation }],
header: { left, center, right, font, verticalAlignment, show, startPage }, footer: { … },
printSettings: { pageOrientation, topMargin, …, fitToPage, firstPageNumber },
columnSets: { name: { columns, columnWidths, columnStyles } },
pictures: { name: { ref } | { data } | {} + transparent: false | { x, y } },
drawings: [{ type, begin: { row, col, dy, dx }, end: { … }, picture, pictureSize,
text, name, detail, style, line, sides, id, zOrder }]
```json
{
"columns": 5,
"columnWidths": { "1": 5, "2": 40, "3-5": 12 },
"fonts": { "жирный": { "face": "Arial", "size": 10, "bold": true } },
"styles": {
"шапка": { "font": "жирный", "horizontalAlignment": "Center", "textPlacement": "Wrap", "border": "Solid" },
"клетка": { "border": "Solid" },
"число": { "border": "Solid", "horizontalAlignment": "Right", "format": "ЧЦ=15; ЧДЦ=2" },
"итог": { "font": "жирный", "horizontalAlignment": "Right", "topBorder": "Solid" }
},
"areas": [
{ "name": "Заголовок", "rows": [
{ "height": 20, "cells": [{ "col": 1, "span": 5, "style": "шапка", "param": "ЗаголовокОтчёта" }] },
{}
]},
{ "name": "ШапкаТаблицы", "rows": [
{ "rowStyle": "шапка", "cells": [
{ "col": 1, "text": "№" }, { "col": 2, "text": "Номенклатура" },
{ "col": 3, "text": "Количество" }, { "col": 4, "text": "Цена" }, { "col": 5, "text": "Сумма" }
]}
]},
{ "name": "Строка", "rows": [
{ "rowStyle": "клетка", "cells": [
{ "col": 1, "param": "НомерСтроки" },
{ "col": 2, "param": "Товар", "detail": "Номенклатура" },
{ "col": 3, "style": "число", "param": "Количество" },
{ "col": 4, "style": "число", "param": "Цена" },
{ "col": 5, "style": "число", "param": "Сумма" }
]}
]},
{ "name": "Итого", "rows": [
[null, null, null, { "style": "итог", "text": "Итого:" }, { "style": "итог", "param": "Всего" }]
]}
]
}
```
Ключевые правила:
- `page` — формат страницы (`"A4-landscape"`, `"A4-portrait"` или число). Автоматически вычисляет `defaultWidth` из суммы пропорций `"Nx"`
- `name` у области в `areas` необязателен: область без имени — просто кусок сетки, именованной она не станет
- `namedAreas` — области, которые не описываются диапазоном подряд идущих строк: полоса колонок, прямоугольник, ячейка. Тип не указывается, он следует из того, какие оси заданы
- `columnSet` у области — ссылка на раскладку из `columnSets`, когда группе строк нужны свои ширины колонок; без него действует документная раскладка
- Ключ стиля — имя свойства как в выгрузке; `columnStyles` вешает стиль на колонку так же, как `style` на ячейку
- Рамка — `border` (все стороны) или `leftBorder`/`topBorder`/`rightBorder`/`bottomBorder`; значение `"Solid"` либо `{ style, width }`
- `rowStyle` — стиль строки: ложится и на строку, и на все её колонки, заполняя пустоты (рамки по всей ширине)
- `height` и `hidden` — собственные свойства строки, у ячейки таких нет
- `empty` в строке — шорткат для N подряд пустых строк (`{ "empty": 3 }` = три `{}`)
- Строку можно писать массивом ячеек — позиция из порядка, `col` не нужен: `"текст"`, `"{Имя}"` — параметр, `">"` — продолжить ячейку слева, `"|"` — сверху, `null` — пропуск колонки
- `col` — 1-based позиция колонки
- `rowspan` — объединение строк вниз (rowStyle учитывает занятые ячейки)
- Содержимое ячейки задаётся одним из ключей: `param` — параметр заполнения, `text` — статический текст, `template` — текст со вставками `[Параметр]`
- `rowGroups`/`columnGroups` — группы строк и колонок (сворачиваются кнопкой на полях): плоский список диапазонов, вложенность выражена вхождением одного в другой
- `header`/`footer` — колонтитулы: три слота (`left`/`center`/`right`), общий шрифт и вертикальное выравнивание; текст может нести поля `[&НомерСтраницы]`, `[&Дата]`
- `note` — всплывающая подсказка у ячейки: строка, объект языков или `{ text, style, autoSize, box }`
- `drawings` — рисунки поверх сетки (картинка, фигура, надпись): положение задают два якоря «ячейка + смещение в точках», картинка берётся по имени из `pictures`
- `valueType` делает ячейку полем ввода (`"Number(15,3,nonneg)"`, `"String(10)"`, `"CatalogRef.Валюты"`, составной через ` + `); текста в такой ячейке быть не может, значение задаётся ключом `value`
Область «Итого» записана короткой формой: позиция берётся из порядка, `col` не нужен.
## Структура DSL
```
{ columns, page, defaultWidth, columnWidths, columnStyles, textLanguages,
fonts: { имя: { face, size, bold, italic, underline, strikeout } | { ref } },
styles: { имя: { font, horizontalAlignment, verticalAlignment, textPlacement,
border, leftBorder, topBorder, rightBorder, bottomBorder,
borderColor, backColor, textColor, format } },
areas: [{ name, columnSet, rows: [
{ height, hidden, rowStyle, empty, cells: [
{ col, span, rowspan, style, param, detail, text, template, note,
valueType, controlType, value, pictureParameter } ] } ] }],
namedAreas, columnSets, rowGroups, columnGroups, header, footer, printSettings,
pictures, drawings
}
```
Верхний уровень: `columns` обязателен, остальное по необходимости.
| Ключ | Описание |
|---|---|
| `columns` | Количество колонок раскладки по умолчанию |
| `page` | Формат страницы: `"A4-landscape"` (780), `"A4-portrait"` (540) или число. Сам вычисляет `defaultWidth` из суммы пропорций `"Nx"` |
| `defaultWidth` | Ширина колонок по умолчанию (10) |
| `columnWidths` | Ширины: ключи 1-based (`"1"`, `"3-14"`, `"5,7,9"`), значение — число или `"2x"` (доля от `defaultWidth`) |
| `columnStyles` | Стиль на колонку целиком: те же ключи диапазонов, значение — имя стиля |
| `textLanguages` | Языки, на которые разворачивается текст, заданный строкой (по умолчанию `["ru"]`) |
| `areas` | Области — диапазоны подряд идущих строк, в порядке документа |
## Области, строки, ячейки
**Область** (`areas[]`) — диапазон подряд идущих строк: `name` (необязательно; с именем область
доступна как `Макет.ПолучитьОбласть("Имя")`) и `rows`. Область без имени — просто кусок сетки.
**Строка** (`rows[]`): `height`, `hidden`, `rowStyle`, `cells`. Пустая строка — `{}`,
а `{ "empty": 3 }` заменяет три подряд. `height` и `hidden` — свойства самой строки, у ячейки
таких нет.
**Ячейка** (`cells[]`):
| Ключ | Описание |
|---|---|
| `col` | Позиция колонки, 1-based |
| `span` / `rowspan` | Объединение вправо / вниз |
| `style` | Имя стиля; перекрывает `rowStyle` для этой ячейки |
| `param` | Параметр заполнения — `Область.Параметры.Имя = …` |
| `text` | Статический текст: строка или объект «язык → текст» |
| `template` | Текст со вставками `[Параметр]` |
| `detail` | Параметр расшифровки; ставится и без `param` |
Содержимое задаётся ровно одним ключом из `param` / `text` / `template`; ячейка без них —
пустая (нужна, например, ради рамки). Пустая строка `"text": ""` — это тоже текст, а не
отсутствие текста.
### Короткая форма: строка массивом
Позиция берётся из порядка, `col` не нужен:
| Элемент | Значение |
|---|---|
| `"текст"` | Статический текст |
| `{ "ru": "…", "en": "…" }` | Тот же текст на нескольких языках |
| `"{Имя}"` | Параметр заполнения |
| `">"` | Продолжение ячейки слева — увеличивает её `span` |
| `"|"` | Продолжение ячейки сверху — увеличивает её `rowspan` |
| `null` | Пропуск колонки |
| `{ … }` | Обычная ячейка без `col` — когда нужны `style`, `detail`, `template` |
Двухуровневая шапка массивами:
```json
"rows": [
["Вид", "Остаток", ">", "Итог"],
@@ -101,3 +173,52 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.ps1" -J
["{Вид}", "{Нач}", "{Кон}", "{Итог}"]
]
```
Здесь «Вид» и «Итог» объединены по вертикали, «Остаток» — по горизонтали на две колонки.
Короткой формой не задать `height` и `rowStyle` — это свойства строки.
### `rowStyle` — оформление строки
Стиль ложится на ВСЮ ширину строки: колонки без явных ячеек получают его тоже — так выходят
сплошные рамки в табличной части. Он же становится оформлением самой строки. Ячейки с `rowspan`
из предыдущих строк при этом пропускаются.
## Оформление
Ячейка, строка и колонка ссылаются на один и тот же именованный стиль: ячейка — ключом `style`,
строка — `rowStyle`, колонка — через `columnStyles`.
**Шрифт** (`fonts.<имя>`): `face` (Arial), `size` (10), `bold`, `italic`, `underline`,
`strikeout`. Либо ссылка вместо описания: `{ "ref": "style:TextFont" }`,
`{ "ref": "sys:DefaultGUIFont" }`. Шрифт `"default"` берётся, когда стиль не указал свой.
**Частые ключи стиля** — имя ключа совпадает с именем свойства в выгрузке, значения перечислений
регистр не различают:
| Ключ | Значение |
|---|---|
| `font` | Имя из `fonts` |
| `horizontalAlignment` | `Left`, `Center`, `Right`, `Justify`, `Auto` |
| `verticalAlignment` | `Top`, `Center`, `Bottom` |
| `textPlacement` | Длинный текст: `Wrap` (перенос), `Cut` (обрезать), `Block`, `Auto` |
| `border` | Рамка со всех сторон |
| `leftBorder`, `topBorder`, `rightBorder`, `bottomBorder` | Отдельная сторона |
| `borderColor` | Цвет рамки |
| `backColor`, `textColor` | Цвет фона и текста |
| `format` | Формат данных 1С: `"ЧЦ=15; ЧДЦ=2"`, `"ДФ=dd.MM.yyyy"` |
**Рамка**: `"Solid"` (ширина 1) либо `{ "style": "Solid", "width": 2 }`. Стили линии: `None`,
`Solid`, `Dotted`, `Dashed`, `DashDotted`, `DashDottedDotted`, `ThinDashed`, `LargeDashed`,
`ThickDashed`, `Double`. Стороны можно задавать по отдельности всегда: совпавшие четыре
компилятор свернёт сам.
**Цвет** — нотация платформы: `#RRGGBB`, `style:ИмяСтиля` (элемент стиля конфигурации),
`web:Имя`, `win:Имя`. Несуществующее имя платформа отвергнет при загрузке.
```json
"styles": {
"шапка": { "font": "жирный", "horizontalAlignment": "Center", "backColor": "#EBEBEB" },
"рамка": { "border": { "style": "Solid", "width": 2 } },
"снизу": { "bottomBorder": "Dotted" }
}
```
@@ -0,0 +1,49 @@
# Рисунки и картинки
Рисунок — объект поверх сетки ячеек: картинка, фигура или надпись. Его положение задают два
якоря: ячейка плюс смещение в точках от её левого верхнего угла.
```json
"pictures": {
"знак": { "ref": "v8ui:Стоп48" },
"логотип": { "data": "iVBORw0KGgo...", "transparent": { "x": 24, "y": 29 } }
},
"drawings": [
{ "type": "Picture", "picture": "логотип", "name": "Логотип",
"begin": { "row": 1, "col": 1 },
"end": { "row": 3, "col": 2, "dy": 34, "dx": 115 },
"pictureSize": "Proportionally", "detail": "ПараметрРасшифровки" },
{ "type": "Rectangle", "style": "заливка",
"line": { "style": "Dashed", "width": 2 },
"sides": { "left": true, "top": true, "right": false, "bottom": false },
"begin": { "row": 5, "col": 1 }, "end": { "row": 6, "col": 3 } },
{ "type": "Text", "text": { "ru": "Подпись", "en": "Signature" },
"begin": { "row": 8, "col": 1 }, "end": { "row": 8, "col": 3, "dy": 12 } }
]
```
| Поле | Обяз. | По умолч. | Описание |
|------|:-----:|-----------|----------|
| `type` | нет | `Picture` | `Picture`, `Rectangle`, `Ellipse`, `Line`, `Text`, `Chart`, `GanttChart` |
| `begin` / `end` | да | — | Якоря: `row`, `col` (1-based) и смещения `dy`, `dx` в точках |
| `picture` | нет | — | Имя записи из `pictures` |
| `pictureSize` | нет | `Stretch` | Как картинка заполняет прямоугольник: `Stretch`, `AutoSize`, `Proportionally`, `RealSize` |
| `text` | нет | — | Надпись: строка или объект «язык → текст» |
| `name` | нет | — | Имя рисунка, по которому к нему обращаются из кода |
| `detail` | нет | — | Параметр расшифровки |
| `style` | нет | — | Именованный стиль: заливка, шрифт, выравнивание надписи |
| `line` | нет | — | Линия рисунка (она же его рамка) — как `border` у ячейки |
| `sides` | нет | — | Какие стороны рамки видны: `left`, `top`, `right`, `bottom` |
| `id` | нет | номер по порядку | Идентификатор рисунка |
| `zOrder` | нет | номер по порядку | Порядок перекрытия: чем больше, тем выше |
Порядок в списке `drawings` — порядок в документе; кто кого перекрывает, задаёт `zOrder`.
Запись в `pictures` — либо ссылка (`ref`), либо сами данные в base64 (`data`). Ссылкой
задаются и предопределённая картинка платформы, и общая картинка конфигурации — пишутся они
одинаково, префиксом `v8ui:`. Пустая запись `{}` — картинка не задана, такое в макетах встречается.
Прозрачность задаётся ключом `transparent` в одной из двух форм: `false` — прозрачного фона
нет; `{ "x": …, "y": … }` — прозрачным считается цвет пикселя с этими координатами внутри
картинки (по флажку «прозрачный фон» Конфигуратор берёт её правый нижний пиксель).
Одну запись `pictures` могут использовать несколько рисунков — данные в макете не дублируются.
@@ -1,455 +0,0 @@
# Спецификация MXL DSL — JSON-формат описания табличного документа
Компактный JSON-формат для описания макетов табличных документов 1С (SpreadsheetDocument). Используется навыком `/mxl-compile` (JSON → XML).
Оформление — шрифты, стили, цвета, рамки, колоночные раскладки — в `styles.md`;
полный перечень свойств стиля — в `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` | нет | — | Оформление колонок: те же ключи, значение — имя стиля (см. `styles.md`) |
| `textLanguages` | нет | `["ru"]` | Языки, на которых пишется текст, заданный строкой (см. ниже) |
| `fonts` | нет | — | Именованные шрифты (если не задано, создаётся Arial 10) |
| `styles` | нет | `{}` | Именованные стили (см. `styles.md`) |
| `areas` | да | — | Массив областей — диапазонов подряд идущих строк (порядок = порядок в документе); имя необязательно |
| `namedAreas` | нет | — | Именованные области, заданные координатами (см. ниже) |
| `columnSets` | нет | — | Дополнительные колоночные раскладки (см. `styles.md`) |
| `rowGroups` | нет | — | Группы строк (см. ниже) |
| `columnGroups` | нет | — | Группы колонок (см. ниже) |
| `header` / `footer` | нет | — | Верхний и нижний колонтитулы (см. ниже) |
| `printSettings` | нет | — | Параметры печати (см. ниже) |
| `pictures` | нет | — | Палитра картинок: ссылки на библиотеку платформы или данные (см. ниже) |
| `drawings` | нет | — | Рисунки: картинки, фигуры, надписи (см. ниже) |
## Области (`areas[]`)
| Поле | Обяз. | Описание |
|------|:-----:|----------|
| `name` | нет | Имя области для `Макет.ПолучитьОбласть("Имя")` |
| `columnSet` | нет | Ссылка на раскладку из `columnSets` |
| `rows` | да | Массив строк |
Макет собирается из областей — диапазонов подряд идущих строк. Имя делает область именованной: она доступна в коде как `Макет.ПолучитьОбласть("Имя")` и занимает строки своего диапазона. **Область без имени** — просто кусок сетки: так описываются строки, не принадлежащие ни одной именованной области.
## Именованные области координатами (`namedAreas[]`)
Для областей, которые диапазоном подряд идущих строк не описываются: полоса колонок, прямоугольник, ячейка, а также пересекающиеся с другими.
| Поле | Обяз. | Описание |
|------|:-----:|----------|
| `name` | да | Имя области |
| `rows` | \* | Строки: число или диапазон `"N-M"`, 1-based |
| `cols` | \* | Колонки: число или диапазон `"N-M"`, 1-based |
| `columnSet` | нет | Колоночная раскладка области. Без ключа выводится из накрытых строк, `""` — привязки нет |
\* Обязательна хотя бы одна из осей.
**Тип области не указывается** — он следует из того, какие оси заданы, как в `ТабличныйДокумент.Область()`: только строки → полоса строк, только колонки → полоса колонок, обе оси → прямоугольник, одиночные значения по обеим осям → одна ячейка.
```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`, `valueType`, `controlType`, `value`,
`note`) — объект
описывает
свойства ячейки. Иначе он целиком считается её текстом, а его ключи — идентификаторами языков.
```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` |
| `valueType` | нет | — | Тип значения: ячейка становится полем ввода (см. ниже) |
| `controlType` | нет | `input` | Элемент управления поля ввода: `input` или `checkbox`. Только вместе с `valueType` |
| `value` | нет | — | Значение в поле ввода. Только вместе с `valueType` |
| `note` | нет | — | Примечание к ячейке (см. ниже) |
### Содержимое ячейки
Задаётся ровно одним из ключей, объявлять способ заполнения отдельно не нужно:
- `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": ""` даёт пустую надпись, а не ячейку без текста.
## Ячейка-поле ввода
Ячейка может не показывать текст, а принимать значение от пользователя — так делают макеты для
ввода данных. Достаточно задать тип значения:
```json
{ "col": 1, "valueType": "Number(15,3,nonneg)" }
{ "col": 2, "valueType": "String(10)" }
{ "col": 3, "valueType": "Boolean", "controlType": "checkbox" }
{ "col": 4, "valueType": "CatalogRef.Валюты" }
{ "col": 5, "valueType": "Boolean + String + Date + CatalogRef.Валюты" }
{ "col": 6, "valueType": "AnyRef" }
```
Грамматика типа:
| Запись | Значение |
|---|---|
| `Boolean` | булево |
| `String`, `String(10)`, `String(10,fixed)` | строка; без длины — неограниченная, `fixed` — фиксированной длины |
| `Number`, `Number(15,3)`, `Number(15,3,nonneg)` | число; без параметров — без ограничения разрядности, `nonneg` — неотрицательное |
| `Date`, `DateTime`, `Time` | дата, дата со временем, время |
| `CatalogRef.Валюты`, `DocumentRef.Реализация`, `EnumRef.Статусы`, `DefinedType.Сумма` | ссылочный тип |
| `CatalogRef`, `DocumentRef`, `AnyRef` | категория целиком: любая ссылка этого вида |
| `A + B` | составной тип; повтор одного примитива недопустим |
Русские имена принимаются наравне с английскими: `Число(15,3)`, `Строка(10)`,
`СправочникСсылка.Валюты`.
`text` и `template` в такой ячейке недопустимы — платформа не показывает текст там, где вводится
значение. `param` и `detail` допустимы: они описывают заполнение и расшифровку, а не содержимое.
Пустой тип `"valueType": ""` — «ячейка содержит значение», но тип не ограничен.
Значение поля ввода задаётся ключом `value`. Его тип — тип литерала JSON: строка, число,
`true`/`false`; к объявленному типу ячейки значение не приводится. Пустая строка означает
пустое значение объявленного типа. Дата пишется строкой `ГГГГ-ММ-ДДTчч:мм:сс` и читается
как дата у ячейки, объявленной датой; у ссылочного и составного типа значение — строка.
```json
{ "col": 1, "valueType": "Number(15,3)", "value": 12.5 }
{ "col": 2, "valueType": "String(10)", "value": "5" }
{ "col": 3, "valueType": "Boolean", "value": true }
{ "col": 4, "valueType": "DateTime", "value": "" }
```
`controlType` нужен редко: умолчание платформы — поле ввода, и оно подходит всем типам, включая
`Boolean`. Флажок задаётся явно.
## Примечание к ячейке
Всплывающая подсказка, которую платформа показывает при наведении. Задаётся ключом `note`
строкой, объектом «язык → текст» или полной формой:
```json
{ "col": 1, "text": "Итого", "note": "Сумма без НДС" }
{ "col": 2, "note": { "ru": "на дату документа", "en": "as of the document date" } }
{ "col": 3, "note": { "text": "не более 20%", "style": "жёлтая-подсказка" } }
{ "col": 4, "note": { "text": "…", "autoSize": false,
"box": { "top": 58, "left": -175, "bottom": 362, "right": 478 } } }
```
Объект трактуется по ключам — так же, как текст ячейки в короткой форме строки: есть ключ
примечания (`text`, `style`, `box`, `autoSize`) → это описание примечания, иначе ключи
считаются идентификаторами языков.
| Поле | По умолч. | Описание |
|------|-----------|----------|
| `text` | — | Текст подсказки: строка или объект «язык → текст» |
| `style` | стиль подсказки | Имя стиля из `styles`; без него — оформление, которое даёт Конфигуратор |
| `autoSize` | `true` | Подгонять ли размер окошка под текст |
| `box` | — | Смещения окошка: `top`, `left` — положение, `bottom`, `right` — размер. Без ключа окошко встаёт стандартно |
Координаты ячейки в примечании не задаются. `autoSize` и `box` независимы: при автоподгоне
размера положение окошка всё равно хранится.
## Колонтитулы
У верхнего и нижнего колонтитула по три слота — `left`, `center`, `right` — и общие настройки:
```json
"header": {
"font": "мелкий",
"verticalAlignment": "Bottom",
"startPage": 2,
"left": "Слева\nвторая строка",
"center": "Стр. [&НомерСтраницы] из [&СтраницВсего]",
"right": { "ru": "Справа", "en": "Right" }
},
"footer": {
"show": false,
"center": { "formatted": "<b>Итог</> <colorstyle -16>красным</>" }
}
```
| Поле | По умолч. | Описание |
|------|-----------|----------|
| `left`, `center`, `right` | — | Текст слота: строка, объект «язык → текст» или `{ "formatted": … }` |
| `font` | — | Имя шрифта из `fonts` — на весь колонтитул |
| `verticalAlignment` | — | Положение текста по вертикали: `Top`, `Center`, `Bottom` |
| `show` | `true` | Выводить ли колонтитул |
| `startPage` | `1` | Страница, с которой колонтитул печатается |
Текст может быть многострочным (`\n`) и содержать поля `[&НомерСтраницы]`, `[&СтраницВсего]`,
`[&Дата]`, `[&Время]` — платформа подставляет их при печати. `{ "formatted": … }` — форматированная
строка: разметка живёт прямо в тексте (`<b>жирный</>`, `<fontsize 12>`, `<colorstyle -16>`).
## Параметры печати
Плоский объект; имя ключа совпадает с именем свойства в выгрузке:
```json
"printSettings": {
"pageOrientation": "Landscape",
"topMargin": 500, "leftMargin": 500, "bottomMargin": 500, "rightMargin": 500,
"headerSize": 1000, "footerSize": 1000,
"fitToPage": true, "firstPageNumber": 7
}
```
Допустимые ключи: `pageOrientation`, `scale`, `collate`, `copies`, `perPage`, `topMargin`,
`leftMargin`, `bottomMargin`, `rightMargin`, `headerSize`, `footerSize`, `fitToPage`,
`blackAndWhite`, `printerName`, `paper`, `paperSource`, `pageWidth`, `pageHeight`, `duplexType`,
`pagePlacementAlternation`, `firstPageNumber`. Незнакомый ключ — ошибка. Порядок в объекте не
важен: компилятор пишет свойства в том порядке, что и платформа.
## Группы строк и колонок
Диапазон строк или колонок, который сворачивается кнопкой на полях. Задаются плоским списком;
вложенность выражена вхождением одного диапазона в другой:
```json
"rowGroups": [
{ "rows": "2-4" },
{ "rows": 3 },
{ "rows": 5, "name": "Итоговая", "collapsed": true, "titleLocation": "begin" }
],
"columnGroups": [
{ "cols": "2-3", "name": { "ru": "Показатели", "en": "Values" } },
{ "cols": 3 }
]
```
| Поле | Обяз. | По умолч. | Описание |
|------|:-----:|-----------|----------|
| `rows` / `cols` | да | — | Диапазон 1-based: число или `"N-M"` |
| `name` | нет | — | Имя группы: строка или объект «язык → текст» |
| `collapsed` | нет | `false` | Свёрнута ли группа при открытии |
| `titleLocation` | нет | `auto` | Расположение заголовка: `begin`, `end`, `auto` |
Диапазоны либо вложены, либо не пересекаются: частичное пересечение — ошибка. Порядок в списке
не важен, число уровней вложенности считается само.
## Рисунки и картинки
Рисунок — объект поверх сетки ячеек: картинка, фигура или надпись. Его положение задают два
якоря: ячейка плюс смещение в точках от её левого верхнего угла.
```json
"pictures": {
"знак": { "ref": "v8ui:Стоп48" },
"логотип": { "data": "iVBORw0KGgo...", "transparent": { "x": 24, "y": 29 } }
},
"drawings": [
{ "type": "Picture", "picture": "логотип", "name": "Логотип",
"begin": { "row": 1, "col": 1 },
"end": { "row": 3, "col": 2, "dy": 34, "dx": 115 },
"pictureSize": "Proportionally", "detail": "ПараметрРасшифровки" },
{ "type": "Rectangle", "style": "заливка",
"line": { "style": "Dashed", "width": 2 },
"sides": { "left": true, "top": true, "right": false, "bottom": false },
"begin": { "row": 5, "col": 1 }, "end": { "row": 6, "col": 3 } },
{ "type": "Text", "text": { "ru": "Подпись", "en": "Signature" },
"begin": { "row": 8, "col": 1 }, "end": { "row": 8, "col": 3, "dy": 12 } }
]
```
| Поле | Обяз. | По умолч. | Описание |
|------|:-----:|-----------|----------|
| `type` | нет | `Picture` | `Picture`, `Rectangle`, `Ellipse`, `Line`, `Text`, `Chart`, `GanttChart` |
| `begin` / `end` | да | — | Якоря: `row`, `col` (1-based) и смещения `dy`, `dx` в точках |
| `picture` | нет | — | Имя записи из `pictures` |
| `pictureSize` | нет | `Stretch` | Как картинка заполняет прямоугольник: `Stretch`, `AutoSize`, `Proportionally`, `RealSize` |
| `text` | нет | — | Надпись: строка или объект «язык → текст» |
| `name` | нет | — | Имя рисунка, по которому к нему обращаются из кода |
| `detail` | нет | — | Параметр расшифровки |
| `style` | нет | — | Именованный стиль: заливка, шрифт, выравнивание надписи |
| `line` | нет | — | Линия рисунка (она же его рамка) — как `border` у ячейки |
| `sides` | нет | — | Какие стороны рамки видны: `left`, `top`, `right`, `bottom` |
| `id` | нет | номер по порядку | Идентификатор рисунка |
| `zOrder` | нет | номер по порядку | Порядок перекрытия: чем больше, тем выше |
Порядок в списке `drawings` — порядок в документе; кто кого перекрывает, задаёт `zOrder`.
Запись в `pictures` — либо ссылка (`ref`), либо сами данные в base64 (`data`). Ссылкой
задаются и предопределённая картинка платформы, и общая картинка конфигурации — пишутся они
одинаково, префиксом `v8ui:`. Пустая запись `{}` — картинка не задана, такое в макетах встречается.
Прозрачность задаётся ключом `transparent` в одной из двух форм: `false` — прозрачного фона
нет; `{ "x": …, "y": … }` — прозрачным считается цвет пикселя с этими координатами внутри
картинки (по флажку «прозрачный фон» Конфигуратор берёт её правый нижний пиксель).
Одну запись `pictures` могут использовать несколько рисунков — данные в макете не дублируются.
## `rowStyle` — оформление строки
Стиль применяется ко ВСЕЙ ширине строки: позиции без явных ячеек получают тот же стиль. Так в табличных строках получаются сплошные рамки. Он же становится оформлением самой строки — именно так платформа хранит строку, оформленную целиком.
Стиль конкретной ячейки (`style`) перекрывает `rowStyle` для этой ячейки.
Если в предыдущих строках той же области есть ячейки с `rowspan`, их колонки при автозаполнении пропускаются.
## Ограничения
DSL описывает не все конструкции табличного документа. Перечисленное ниже **теряется при
round-trip** (`/mxl-decompile``/mxl-compile`): в JSON оно не попадает, в сгенерированный
XML не возвращается.
- объединения, не привязанные к ячейке (по всей высоте или ширине документа);
- настройки диаграмм (`Chart`, `GanttChart`) — сам рисунок сохраняется, его содержимое нет;
- область печати.
Пересборка макета из DSL — это полная перегенерация, а не точечная правка XML, поэтому
diff после round-trip обычно шире фактической доработки.
Отдельно про побайтовое совпадение. В макетах, которые долго правили в Конфигураторе,
встречаются следы прежних состояний: формат ячейки может нести ширину колонки, которая с тех
пор изменилась. Такие значения не описывают итоговый документ и из него не выводятся, поэтому
собранный XML совпадёт с исходным не всегда — при полностью сохранённом содержании.
@@ -0,0 +1,26 @@
# Группы строк и колонок
Диапазон строк или колонок, который сворачивается кнопкой на полях. Задаются плоским списком;
вложенность выражена вхождением одного диапазона в другой:
```json
"rowGroups": [
{ "rows": "2-4" },
{ "rows": 3 },
{ "rows": 5, "name": "Итоговая", "collapsed": true, "titleLocation": "begin" }
],
"columnGroups": [
{ "cols": "2-3", "name": { "ru": "Показатели", "en": "Values" } },
{ "cols": 3 }
]
```
| Поле | Обяз. | По умолч. | Описание |
|------|:-----:|-----------|----------|
| `rows` / `cols` | да | — | Диапазон 1-based: число или `"N-M"` |
| `name` | нет | — | Имя группы: строка или объект «язык → текст» |
| `collapsed` | нет | `false` | Свёрнута ли группа при открытии |
| `titleLocation` | нет | `auto` | Расположение заголовка: `begin`, `end`, `auto` |
Диапазоны либо вложены, либо не пересекаются: частичное пересечение — ошибка. Порядок в списке
не важен, число уровней вложенности считается само.
@@ -0,0 +1,48 @@
# Ячейки-поля ввода
Ячейка может не показывать текст, а принимать значение от пользователя — так делают макеты для
ввода данных. Достаточно задать тип значения:
```json
{ "col": 1, "valueType": "Number(15,3,nonneg)" }
{ "col": 2, "valueType": "String(10)" }
{ "col": 3, "valueType": "Boolean", "controlType": "checkbox" }
{ "col": 4, "valueType": "CatalogRef.Валюты" }
{ "col": 5, "valueType": "Boolean + String + Date + CatalogRef.Валюты" }
{ "col": 6, "valueType": "AnyRef" }
```
Грамматика типа:
| Запись | Значение |
|---|---|
| `Boolean` | булево |
| `String`, `String(10)`, `String(10,fixed)` | строка; без длины — неограниченная, `fixed` — фиксированной длины |
| `Number`, `Number(15,3)`, `Number(15,3,nonneg)` | число; без параметров — без ограничения разрядности, `nonneg` — неотрицательное |
| `Date`, `DateTime`, `Time` | дата, дата со временем, время |
| `CatalogRef.Валюты`, `DocumentRef.Реализация`, `EnumRef.Статусы`, `DefinedType.Сумма` | ссылочный тип |
| `CatalogRef`, `DocumentRef`, `AnyRef` | категория целиком: любая ссылка этого вида |
| `A + B` | составной тип; повтор одного примитива недопустим |
Русские имена принимаются наравне с английскими: `Число(15,3)`, `Строка(10)`,
`СправочникСсылка.Валюты`.
`text` и `template` в такой ячейке недопустимы — платформа не показывает текст там, где вводится
значение. `param` и `detail` допустимы: они описывают заполнение и расшифровку, а не содержимое.
Пустой тип `"valueType": ""` — «ячейка содержит значение», но тип не ограничен.
Значение поля ввода задаётся ключом `value`. Его тип — тип литерала JSON: строка, число,
`true`/`false`; к объявленному типу ячейки значение не приводится. Пустая строка означает
пустое значение объявленного типа. Дата пишется строкой `ГГГГ-ММ-ДДTчч:мм:сс` и читается
как дата у ячейки, объявленной датой; у ссылочного и составного типа значение — строка.
```json
{ "col": 1, "valueType": "Number(15,3)", "value": 12.5 }
{ "col": 2, "valueType": "String(10)", "value": "5" }
{ "col": 3, "valueType": "Boolean", "value": true }
{ "col": 4, "valueType": "DateTime", "value": "" }
```
`controlType` нужен редко: умолчание платформы — поле ввода, и оно подходит всем типам, включая
`Boolean`. Флажок задаётся явно.
@@ -0,0 +1,73 @@
# Разметка: области координатами и колоночные раскладки
Читать, когда область не описывается диапазоном подряд идущих строк или когда части документа нужны разные ширины колонок.
## Именованные области координатами (`namedAreas[]`)
Для областей, которые диапазоном подряд идущих строк не описываются: полоса колонок, прямоугольник, ячейка, а также пересекающиеся с другими.
| Поле | Обяз. | Описание |
|------|:-----:|----------|
| `name` | да | Имя области |
| `rows` | \* | Строки: число или диапазон `"N-M"`, 1-based |
| `cols` | \* | Колонки: число или диапазон `"N-M"`, 1-based |
| `columnSet` | нет | Колоночная раскладка области. Без ключа выводится из накрытых строк, `""` — привязки нет |
\* Обязательна хотя бы одна из осей.
**Тип области не указывается** — он следует из того, какие оси заданы, как в `ТабличныйДокумент.Область()`: только строки → полоса строк, только колонки → полоса колонок, обе оси → прямоугольник, одиночные значения по обеим осям → одна ячейка.
```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` — ширины. Ключ словаря — имя раскладки;
в макетах, полученных декомпиляцией, это идентификатор из исходного файла, при описании
с нуля — любая строка.
Все строки области получают раскладку области, поэтому одна область не может смешивать
раскладки. Позиции колонок (`col`, `span`) проверяются по ширине раскладки СВОЕЙ области,
а не документной.
Ссылка на необъявленную раскладку → ненулевой код выхода и сообщение в stderr.
## Стиль колонки (`columnStyles`)
Колонка несёт то же оформление, что ячейка и строка. Ключи — та же грамматика диапазонов,
что у `columnWidths`; значение — имя стиля.
```json
"columnWidths": { "1": 30, "2-3": 15 },
"columnStyles": { "1": "по-центру", "4": "скрытая" }
```
Внутри `columnSets` работает тот же ключ. Ширина и стиль независимы: колонка может иметь
только ширину, только стиль или и то, и другое.
@@ -0,0 +1,26 @@
# Примечания к ячейкам
Всплывающая подсказка, которую платформа показывает при наведении. Задаётся ключом `note`
строкой, объектом «язык → текст» или полной формой:
```json
{ "col": 1, "text": "Итого", "note": "Сумма без НДС" }
{ "col": 2, "note": { "ru": "на дату документа", "en": "as of the document date" } }
{ "col": 3, "note": { "text": "не более 20%", "style": "жёлтая-подсказка" } }
{ "col": 4, "note": { "text": "…", "autoSize": false,
"box": { "top": 58, "left": -175, "bottom": 362, "right": 478 } } }
```
Объект трактуется по ключам — так же, как текст ячейки в короткой форме строки: есть ключ
примечания (`text`, `style`, `box`, `autoSize`) → это описание примечания, иначе ключи
считаются идентификаторами языков.
| Поле | По умолч. | Описание |
|------|-----------|----------|
| `text` | — | Текст подсказки: строка или объект «язык → текст» |
| `style` | стиль подсказки | Имя стиля из `styles`; без него — оформление, которое даёт Конфигуратор |
| `autoSize` | `true` | Подгонять ли размер окошка под текст |
| `box` | — | Смещения окошка: `top`, `left` — положение, `bottom`, `right` — размер. Без ключа окошко встаёт стандартно |
Координаты ячейки в примечании не задаются. `autoSize` и `box` независимы: при автоподгоне
размера положение окошка всё равно хранится.
@@ -0,0 +1,53 @@
# Печать: колонтитулы и параметры страницы
Читать, когда макет готовят к печати: повторяющиеся надписи сверху и снизу, ориентация, поля, масштаб.
## Колонтитулы
У верхнего и нижнего колонтитула по три слота — `left`, `center`, `right` — и общие настройки:
```json
"header": {
"font": "мелкий",
"verticalAlignment": "Bottom",
"startPage": 2,
"left": "Слева\nвторая строка",
"center": "Стр. [&НомерСтраницы] из [&СтраницВсего]",
"right": { "ru": "Справа", "en": "Right" }
},
"footer": {
"show": false,
"center": { "formatted": "<b>Итог</> <colorstyle -16>красным</>" }
}
```
| Поле | По умолч. | Описание |
|------|-----------|----------|
| `left`, `center`, `right` | — | Текст слота: строка, объект «язык → текст» или `{ "formatted": … }` |
| `font` | — | Имя шрифта из `fonts` — на весь колонтитул |
| `verticalAlignment` | — | Положение текста по вертикали: `Top`, `Center`, `Bottom` |
| `show` | `true` | Выводить ли колонтитул |
| `startPage` | `1` | Страница, с которой колонтитул печатается |
Текст может быть многострочным (`\n`) и содержать поля `[&НомерСтраницы]`, `[&СтраницВсего]`,
`[&Дата]`, `[&Время]` — платформа подставляет их при печати. `{ "formatted": … }` — форматированная
строка: разметка живёт прямо в тексте (`<b>жирный</>`, `<fontsize 12>`, `<colorstyle -16>`).
## Параметры печати
Плоский объект; имя ключа совпадает с именем свойства в выгрузке:
```json
"printSettings": {
"pageOrientation": "Landscape",
"topMargin": 500, "leftMargin": 500, "bottomMargin": 500, "rightMargin": 500,
"headerSize": 1000, "footerSize": 1000,
"fitToPage": true, "firstPageNumber": 7
}
```
Допустимые ключи: `pageOrientation`, `scale`, `collate`, `copies`, `perPage`, `topMargin`,
`leftMargin`, `bottomMargin`, `rightMargin`, `headerSize`, `footerSize`, `fitToPage`,
`blackAndWhite`, `printerName`, `paper`, `paperSource`, `pageWidth`, `pageHeight`, `duplexType`,
`pagePlacementAlternation`, `firstPageNumber`. Незнакомый ключ — ошибка. Порядок в объекте не
важен: компилятор пишет свойства в том порядке, что и платформа.
@@ -1,7 +1,8 @@
# Полный список свойств стиля
# Свойства стиля: полный перечень
Имя ключа совпадает с именем свойства в выгрузке — исключений нет. Частые свойства
с примерами — в `styles.md`, здесь полный перечень.
Читать, когда нужного свойства нет среди частых, описанных в SKILL.md: отступы, защита, узор, маска, формат редактирования, поведение при выводе.
Имя ключа совпадает с именем свойства в выгрузке — исключений нет.
Тип значения:
@@ -57,6 +58,9 @@
## Картинка в ячейке
Ключи ниже задают картинку внутри ячейки; сама палитра картинок и рисунки поверх сетки —
в `reference/drawings.md`.
| Ключ | Тип | Значение |
|------|-----|----------|
| `picIndex` | число | Номер картинки |
@@ -74,4 +78,4 @@
- `containsValue`, `valueType`, `controlType` — свойства конкретной ячейки, а не общего
оформления: задаются ключами ячейки `valueType` и `controlType`;
- линия рисунка и её стороны — свойства рисунка: задаются его ключами `line` и `sides`
(у ячейки такого свойства нет вовсе) (см. `dsl-spec.md`).
(`reference/drawings.md`); у ячейки такого свойства нет вовсе.
@@ -1,147 +0,0 @@
# Оформление: шрифты, стили, колонки
Оформление в табличном документе — одна сущность на всех: ячейка, строка и колонка ссылаются
на один и тот же именованный стиль. Ячейка — ключом `style`, строка — `rowStyle`, колонка —
через `columnStyles`.
## Шрифты (`fonts.<name>`)
| Поле | По умолч. | Описание |
|------|-----------|----------|
| `face` | `"Arial"` | Имя шрифта |
| `size` | `10` | Размер (бывает дробным: `8.3`) |
| `bold` | `false` | Жирный |
| `italic` | `false` | Курсив |
| `underline` | `false` | Подчёркнутый |
| `strikeout` | `false` | Зачёркнутый |
Шрифт `"default"` используется, когда стиль не указывает шрифт явно. Если не определён,
создаётся автоматически (Arial 10).
Вместо собственного описания шрифт может быть **ссылкой** — на элемент стиля конфигурации
или на системный шрифт. Тогда у него единственное поле:
```json
"fonts": {
"основной": { "ref": "style:TextFont" },
"системный": { "ref": "sys:DefaultGUIFont" }
}
```
Это та же запись, что у шрифта в описании формы.
## Стили (`styles.<name>`)
Ключ стиля — имя свойства так, как оно называется в выгрузке. Ниже частые; полный список
из 44 свойств — в `format-properties.md`.
| Поле | Описание |
|------|----------|
| `font` | Ссылка на имя из `fonts` |
| `horizontalAlignment` | `Left`, `Center`, `Right`, `Justify`, `Auto` |
| `verticalAlignment` | `Top`, `Center`, `Bottom` |
| `textPlacement` | Что делать с длинным текстом: `Wrap` (перенос), `Cut` (обрезать), `Block`, `Auto` |
| `backColor` | Цвет фона (см. «Цвет») |
| `textColor` | Цвет текста |
| `border`, `leftBorder`, `topBorder`, `rightBorder`, `bottomBorder` | Рамка (см. «Рамка») |
| `borderColor` | Цвет рамки |
| `format` | Формат данных 1С: `"ЧЦ=15; ЧДЦ=2"`, `"ДФ=dd.MM.yyyy"` |
| `hidden` | Скрыть |
| `protection` | Защита от редактирования |
| `indent` | Отступ |
| `textOrientation` | Поворот текста, в десятых долях градуса (`900` = 90°) |
Значения перечислений регистр не различают: `"center"` и `"Center"` равнозначны.
```json
"styles": {
"шапка": {
"font": "жирный",
"horizontalAlignment": "Center",
"verticalAlignment": "Center",
"textPlacement": "Wrap",
"backColor": "#EBEBEB"
},
"итог": { "font": "жирный", "topBorder": "Solid", "horizontalAlignment": "Right" }
}
```
## Цвет
Строка в одной из четырёх форм — это нотация самой платформы:
| Форма | Значение |
|-------|----------|
| `#RRGGBB` | RGB-hex, напр. `#FFFFC0` |
| `style:ИмяСтиля` | Элемент стиля конфигурации или платформы, напр. `style:FormBackColor` |
| `web:Имя` | Цвет из web-палитры, напр. `web:Gainsboro`, `web:FireBrick` |
| `win:Имя` | Системный цвет Windows, напр. `win:ButtonText` |
Имя должно существовать в своей палитре — несуществующее платформа отвергнет при загрузке.
## Рамка
Пять ключей: `border` — все четыре стороны сразу, `leftBorder` / `topBorder` / `rightBorder` /
`bottomBorder` — по отдельности. Значение одинаковое у всех:
| Запись | Значение |
|--------|----------|
| `"Solid"` | Стиль линии, ширина 1 |
| `{ "style": "Solid", "width": 2 }` | Стиль и ширина |
Стили линии: `None`, `Solid`, `Dotted`, `Dashed`, `DashDotted`, `DashDottedDotted`,
`ThinDashed`, `LargeDashed`, `ThickDashed`, `Double`. Конфигуратор предлагает разные наборы
в разных местах — у рамки ячейки одни, у линии рисунка другие, — но палитра одна на документ.
Задавать стороны по отдельности можно всегда: если все четыре совпали, компилятор сам свернёт
их в один `border` — так это хранит платформа.
```json
"рамка-снизу": { "bottomBorder": "Dotted" },
"рамка-вокруг": { "border": { "style": "Solid", "width": 2 } }
```
## Колоночные раскладки (`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` — ширины. Ключ словаря — имя раскладки;
в макетах, полученных декомпиляцией, это идентификатор из исходного файла, при описании
с нуля — любая строка.
Все строки области получают раскладку области, поэтому одна область не может смешивать
раскладки. Позиции колонок (`col`, `span`) проверяются по ширине раскладки СВОЕЙ области,
а не документной.
Ссылка на необъявленную раскладку → ненулевой код выхода и сообщение в stderr.
## Стиль колонки (`columnStyles`)
Колонка несёт то же оформление, что ячейка и строка. Ключи — та же грамматика диапазонов,
что у `columnWidths`; значение — имя стиля.
```json
"columnWidths": { "1": 30, "2-3": 15 },
"columnStyles": { "1": "по-центру", "4": "скрытая" }
```
Внутри `columnSets` работает тот же ключ. Ширина и стиль независимы: колонка может иметь
только ширину, только стиль или и то, и другое.
+21 -1
View File
@@ -41,4 +41,24 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-decompile.ps1"
3. Вызвать `/mxl-compile` для генерации нового Template.xml
4. Вызвать `/mxl-validate` для проверки
Формат JSON на выходе — тот же DSL, что принимает `/mxl-compile`; его полное описание живёт в навыке `/mxl-compile`.
Формат JSON на выходе — тот же DSL, что принимает `/mxl-compile`; его описание живёт в навыке `/mxl-compile`.
## Что нужно знать о пересборке
Правка через DSL — это полная перегенерация макета, а не точечное изменение XML. Поэтому
diff после цикла «декомпиляция → компиляция» обычно шире фактической доработки, даже когда
содержание сохранено целиком.
Побайтового совпадения с исходником ждать не всегда стоит. В макетах, которые долго правили
в Конфигураторе, остаются следы прежних состояний: например, формат ячейки несёт ширину
колонки, которая с тех пор изменилась. Из итогового документа такие значения не выводятся,
и в пересобранный файл они не возвращаются.
Не переживают цикл вовсе (в JSON не попадают, в XML не возвращаются):
- объединения, не привязанные к ячейке — по всей высоте или ширине документа;
- настройки диаграмм (`Chart`, `GanttChart`) — сам рисунок сохраняется, его содержимое нет;
- область печати.
Если задача — сохранить чужой макет как есть и поправить в нём малое, сверяйте результат
`/mxl-info` или diff-ом: перечисленное выше нужно вернуть руками.