feat(mxl-compile,mxl-decompile,mxl-validate): примечания к ячейкам

Ключ ячейки note описывает всплывающую подсказку: строкой, объектом
языков или полной формой с оформлением, признаком авторазмера и
геометрией окошка.

Из четырнадцати тегов, которые платформа пишет в примечание, настоящей
информации несут пять. drawingType, pictureSize и id — константы на всём
корпусе. Якорь конца это координаты самой ячейки (1087 примечаний из
1087), якорь начала — 1/1 (1085 из 1087, три исключения в одном макете
берёт раундтрип-ключ anchor). Остаётся текст, стиль, autoSize и четыре
смещения, причём autoSize описывает не наличие геометрии, а пересчёт
размера: при true координаты всё равно записаны и осмысленны.

Стиль примечания — обычная запись палитры; без своего стиля пишем тот,
что даёт Конфигуратор (926 примечаний корпуса из 1087). Формат
примечания добавлен в сбор именованных стилей декомпилятора и в перечень
владельцев формата: иначе стиль подсказки вырезался как неиспользуемый и
ссылка оставалась висячей.

mxl-validate: индекс формата примечания проверяется наравне с ячейкой,
строкой и колонкой.

Стенд СПримечанием собирается байт в байт обоими портами и добавлен в
платформенные фикстуры.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-15 14:47:23 +03:00
co-authored by Claude Opus 5
parent faa8ab7659
commit 4005f36cce
17 changed files with 1071 additions and 14 deletions
@@ -0,0 +1,23 @@
{
"name": "Примечания к ячейкам: короткая и полная формы",
"input": {
"columns": 4,
"textLanguages": ["ru"],
"styles": { "жёлтая-подсказка": { "verticalAlignment": "Top", "backColor": "#FFFAD9" } },
"areas": [
{
"name": "Примечания",
"rows": [
{ "cells": [
{ "col": 1, "text": "Итого", "note": "Сумма без НДС" },
{ "col": 2, "text": "Курс", "note": { "ru": "на дату документа", "en": "as of the document date" } },
{ "col": 3, "param": "Скидка", "note": { "text": "не более 20%", "style": "жёлтая-подсказка" } },
{ "col": 4, "note": { "text": "сдвинуто и растянуто", "autoSize": false,
"box": { "top": 58, "left": -175, "bottom": 362, "right": 478 } } }
]}
]
}
]
},
"params": { "outputPath": "Template.xml" }
}
@@ -0,0 +1,154 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://v8.1c.ru/8.2/data/spreadsheet" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<languageSettings>
<currentLanguage>ru</currentLanguage>
<defaultLanguage>ru</defaultLanguage>
<languageInfo>
<id>ru</id>
<code>Русский</code>
<description>Русский</description>
</languageInfo>
<languageInfo>
<id>en</id>
<code>Английский</code>
<description>Английский</description>
</languageInfo>
</languageSettings>
<columns>
<size>3</size>
</columns>
<rowsItem>
<index>0</index>
<row>
<c>
<c>
<f>0</f>
<tl>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>текст</v8:content>
</v8:item>
</tl>
<note>
<drawingType>Comment</drawingType>
<id>0</id>
<formatIndex>1</formatIndex>
<text>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>тест</v8:content>
</v8:item>
<v8:item>
<v8:lang>en</v8:lang>
<v8:content>test</v8:content>
</v8:item>
</text>
<beginRow>1</beginRow>
<beginRowOffset>-19</beginRowOffset>
<endRow>0</endRow>
<endRowOffset>50</endRowOffset>
<beginColumn>1</beginColumn>
<beginColumnOffset>19</beginColumnOffset>
<endColumn>0</endColumn>
<endColumnOffset>82</endColumnOffset>
<autoSize>true</autoSize>
<pictureSize>Stretch</pictureSize>
</note>
</c>
</c>
</row>
</rowsItem>
<rowsItem>
<index>1</index>
<row>
<c>
<c>
<f>0</f>
<tl>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Изменен размер</v8:content>
</v8:item>
</tl>
<note>
<drawingType>Comment</drawingType>
<id>0</id>
<formatIndex>1</formatIndex>
<text>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Изменен размер</v8:content>
</v8:item>
</text>
<beginRow>1</beginRow>
<beginRowOffset>-19</beginRowOffset>
<endRow>1</endRow>
<endRowOffset>362</endRowOffset>
<beginColumn>1</beginColumn>
<beginColumnOffset>19</beginColumnOffset>
<endColumn>0</endColumn>
<endColumnOffset>478</endColumnOffset>
<autoSize>false</autoSize>
<pictureSize>Stretch</pictureSize>
</note>
</c>
</c>
<c>
<i>2</i>
<c>
<f>0</f>
<tl/>
</c>
</c>
</row>
</rowsItem>
<rowsItem>
<index>2</index>
<row>
<c>
<c>
<f>0</f>
<tl>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Сдивнут</v8:content>
</v8:item>
</tl>
<note>
<drawingType>Comment</drawingType>
<id>0</id>
<formatIndex>1</formatIndex>
<text>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Сдвинут</v8:content>
</v8:item>
</text>
<beginRow>1</beginRow>
<beginRowOffset>58</beginRowOffset>
<endRow>2</endRow>
<endRowOffset>50</endRowOffset>
<beginColumn>1</beginColumn>
<beginColumnOffset>-175</beginColumnOffset>
<endColumn>0</endColumn>
<endColumnOffset>144</endColumnOffset>
<autoSize>true</autoSize>
<pictureSize>Stretch</pictureSize>
</note>
</c>
</c>
</row>
</rowsItem>
<templateMode>true</templateMode>
<defaultFormatIndex>2</defaultFormatIndex>
<height>3</height>
<vgRows>3</vgRows>
<format>
<verticalAlignment>Top</verticalAlignment>
<textColor>style:ToolTipTextColor</textColor>
<backColor>style:ToolTipBackColor</backColor>
</format>
<format>
<width>72</width>
</format>
</document>
@@ -0,0 +1,25 @@
{
"name": "Раундтрип макета ПЛАТФОРМЫ байт в байт: СПримечанием",
"setup": "fixture:platform-roundtrip",
"preRun": [
{
"script": "mxl-decompile/scripts/mxl-decompile",
"args": {
"-TemplatePath": "СПримечанием.xml",
"-OutputPath": "back.json"
},
"cwd": "{workDir}"
}
],
"params": {
"outputPath": "out.xml"
},
"noSnapshot": "эталон — файл платформы, сверяется expect.filesEqual",
"expect": {
"filesEqual": {
"actual": "out.xml",
"expected": "СПримечанием.xml"
}
},
"inputFrom": "back.json"
}
@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://v8.1c.ru/8.2/data/spreadsheet" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<languageSettings>
<currentLanguage>ru</currentLanguage>
<defaultLanguage>ru</defaultLanguage>
<languageInfo>
<id>ru</id>
<code>Русский</code>
<description>Русский</description>
</languageInfo>
</languageSettings>
<columns>
<size>4</size>
</columns>
<rowsItem>
<index>0</index>
<row>
<c>
<c>
<f>0</f>
<tl>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Итого</v8:content>
</v8:item>
</tl>
<note>
<drawingType>Comment</drawingType>
<id>0</id>
<formatIndex>1</formatIndex>
<text>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Сумма без НДС</v8:content>
</v8:item>
</text>
<beginRow>1</beginRow>
<beginRowOffset>-21</beginRowOffset>
<endRow>0</endRow>
<endRowOffset>51</endRowOffset>
<beginColumn>1</beginColumn>
<beginColumnOffset>21</beginColumnOffset>
<endColumn>0</endColumn>
<endColumnOffset>408</endColumnOffset>
<autoSize>true</autoSize>
<pictureSize>Stretch</pictureSize>
</note>
</c>
</c>
<c>
<c>
<f>0</f>
<tl>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Курс</v8:content>
</v8:item>
</tl>
<note>
<drawingType>Comment</drawingType>
<id>0</id>
<formatIndex>1</formatIndex>
<text>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>на дату документа</v8:content>
</v8:item>
<v8:item>
<v8:lang>en</v8:lang>
<v8:content>as of the document date</v8:content>
</v8:item>
</text>
<beginRow>1</beginRow>
<beginRowOffset>-21</beginRowOffset>
<endRow>0</endRow>
<endRowOffset>51</endRowOffset>
<beginColumn>1</beginColumn>
<beginColumnOffset>21</beginColumnOffset>
<endColumn>1</endColumn>
<endColumnOffset>408</endColumnOffset>
<autoSize>true</autoSize>
<pictureSize>Stretch</pictureSize>
</note>
</c>
</c>
<c>
<c>
<f>2</f>
<parameter>Скидка</parameter>
<note>
<drawingType>Comment</drawingType>
<id>0</id>
<formatIndex>3</formatIndex>
<text>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>не более 20%</v8:content>
</v8:item>
</text>
<beginRow>1</beginRow>
<beginRowOffset>-21</beginRowOffset>
<endRow>0</endRow>
<endRowOffset>51</endRowOffset>
<beginColumn>1</beginColumn>
<beginColumnOffset>21</beginColumnOffset>
<endColumn>2</endColumn>
<endColumnOffset>408</endColumnOffset>
<autoSize>true</autoSize>
<pictureSize>Stretch</pictureSize>
</note>
</c>
</c>
<c>
<c>
<f>0</f>
<note>
<drawingType>Comment</drawingType>
<id>0</id>
<formatIndex>1</formatIndex>
<text>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>сдвинуто и растянуто</v8:content>
</v8:item>
</text>
<beginRow>1</beginRow>
<beginRowOffset>58</beginRowOffset>
<endRow>0</endRow>
<endRowOffset>362</endRowOffset>
<beginColumn>1</beginColumn>
<beginColumnOffset>-175</beginColumnOffset>
<endColumn>3</endColumn>
<endColumnOffset>478</endColumnOffset>
<autoSize>false</autoSize>
<pictureSize>Stretch</pictureSize>
</note>
</c>
</c>
</row>
</rowsItem>
<templateMode>true</templateMode>
<defaultFormatIndex>4</defaultFormatIndex>
<height>1</height>
<vgRows>1</vgRows>
<namedItem xsi:type="NamedItemCells">
<name>Примечания</name>
<area>
<type>Rows</type>
<beginRow>0</beginRow>
<endRow>0</endRow>
<beginColumn>-1</beginColumn>
<endColumn>-1</endColumn>
</area>
</namedItem>
<format>
<verticalAlignment>Top</verticalAlignment>
<textColor>style:ToolTipTextColor</textColor>
<backColor>style:ToolTipBackColor</backColor>
</format>
<format>
<fillType>Parameter</fillType>
</format>
<format>
<verticalAlignment>Top</verticalAlignment>
<backColor>#FFFAD9</backColor>
</format>
<format>
<width>10</width>
</format>
</document>
@@ -0,0 +1,36 @@
{
"name": "Roundtrip — примечания к ячейкам",
"preRun": [
{
"script": "mxl-compile/scripts/mxl-compile",
"input": {
"columns": 4,
"textLanguages": ["ru"],
"styles": { "жёлтая-подсказка": { "verticalAlignment": "Top", "backColor": "#FFFAD9" } },
"areas": [
{
"name": "Примечания",
"rows": [
{ "cells": [
{ "col": 1, "text": "Итого", "note": "Сумма без НДС" },
{ "col": 2, "text": "Курс", "note": { "ru": "на дату", "en": "as of date" } },
{ "col": 3, "param": "Скидка", "note": { "text": "не более 20%", "style": "жёлтая-подсказка" } },
{ "col": 4, "note": { "text": "сдвинуто", "autoSize": false,
"box": { "top": 58, "left": -175, "bottom": 362, "right": 478 },
"anchor": { "row": 4, "col": 1 } } }
]}
]
}
]
},
"args": { "-JsonPath": "{inputFile}", "-OutputPath": "Template.xml" },
"cwd": "{workDir}"
}
],
"params": { "templatePath": "Template.xml" },
"args_extra": ["-OutputPath", "{workDir}/back.json"],
"expect": {
"files": ["back.json"],
"stdoutContains": "[OK] Decompiled:"
}
}
@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://v8.1c.ru/8.2/data/spreadsheet" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<languageSettings>
<currentLanguage>ru</currentLanguage>
<defaultLanguage>ru</defaultLanguage>
<languageInfo>
<id>ru</id>
<code>Русский</code>
<description>Русский</description>
</languageInfo>
</languageSettings>
<columns>
<size>4</size>
</columns>
<rowsItem>
<index>0</index>
<row>
<c>
<c>
<f>0</f>
<tl>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Итого</v8:content>
</v8:item>
</tl>
<note>
<drawingType>Comment</drawingType>
<id>0</id>
<formatIndex>1</formatIndex>
<text>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Сумма без НДС</v8:content>
</v8:item>
</text>
<beginRow>1</beginRow>
<beginRowOffset>-21</beginRowOffset>
<endRow>0</endRow>
<endRowOffset>51</endRowOffset>
<beginColumn>1</beginColumn>
<beginColumnOffset>21</beginColumnOffset>
<endColumn>0</endColumn>
<endColumnOffset>408</endColumnOffset>
<autoSize>true</autoSize>
<pictureSize>Stretch</pictureSize>
</note>
</c>
</c>
<c>
<c>
<f>0</f>
<tl>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Курс</v8:content>
</v8:item>
</tl>
<note>
<drawingType>Comment</drawingType>
<id>0</id>
<formatIndex>1</formatIndex>
<text>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>на дату</v8:content>
</v8:item>
<v8:item>
<v8:lang>en</v8:lang>
<v8:content>as of date</v8:content>
</v8:item>
</text>
<beginRow>1</beginRow>
<beginRowOffset>-21</beginRowOffset>
<endRow>0</endRow>
<endRowOffset>51</endRowOffset>
<beginColumn>1</beginColumn>
<beginColumnOffset>21</beginColumnOffset>
<endColumn>1</endColumn>
<endColumnOffset>408</endColumnOffset>
<autoSize>true</autoSize>
<pictureSize>Stretch</pictureSize>
</note>
</c>
</c>
<c>
<c>
<f>2</f>
<parameter>Скидка</parameter>
<note>
<drawingType>Comment</drawingType>
<id>0</id>
<formatIndex>3</formatIndex>
<text>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>не более 20%</v8:content>
</v8:item>
</text>
<beginRow>1</beginRow>
<beginRowOffset>-21</beginRowOffset>
<endRow>0</endRow>
<endRowOffset>51</endRowOffset>
<beginColumn>1</beginColumn>
<beginColumnOffset>21</beginColumnOffset>
<endColumn>2</endColumn>
<endColumnOffset>408</endColumnOffset>
<autoSize>true</autoSize>
<pictureSize>Stretch</pictureSize>
</note>
</c>
</c>
<c>
<c>
<f>0</f>
<note>
<drawingType>Comment</drawingType>
<id>0</id>
<formatIndex>1</formatIndex>
<text>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>сдвинуто</v8:content>
</v8:item>
</text>
<beginRow>4</beginRow>
<beginRowOffset>58</beginRowOffset>
<endRow>0</endRow>
<endRowOffset>362</endRowOffset>
<beginColumn>1</beginColumn>
<beginColumnOffset>-175</beginColumnOffset>
<endColumn>3</endColumn>
<endColumnOffset>478</endColumnOffset>
<autoSize>false</autoSize>
<pictureSize>Stretch</pictureSize>
</note>
</c>
</c>
</row>
</rowsItem>
<templateMode>true</templateMode>
<defaultFormatIndex>4</defaultFormatIndex>
<height>1</height>
<vgRows>1</vgRows>
<namedItem xsi:type="NamedItemCells">
<name>Примечания</name>
<area>
<type>Rows</type>
<beginRow>0</beginRow>
<endRow>0</endRow>
<beginColumn>-1</beginColumn>
<endColumn>-1</endColumn>
</area>
</namedItem>
<format>
<verticalAlignment>Top</verticalAlignment>
<textColor>style:ToolTipTextColor</textColor>
<backColor>style:ToolTipBackColor</backColor>
</format>
<format>
<fillType>Parameter</fillType>
</format>
<format>
<verticalAlignment>Top</verticalAlignment>
<backColor>#FFFAD9</backColor>
</format>
<format>
<width>10</width>
</format>
</document>
@@ -0,0 +1,19 @@
{
"columns": 4,
"defaultWidth": 10,
"fonts": {},
"styles": { "vtop-bg": { "verticalAlignment": "Top", "backColor": "#FFFAD9" } },
"areas": [
{
"name": "Примечания",
"rows": [
[
{ "text": "Итого", "note": { "text": "Сумма без НДС", "box": { "top": -21, "left": 21, "bottom": 51, "right": 408 } } },
{ "text": "Курс", "note": { "text": { "ru": "на дату", "en": "as of date" }, "box": { "top": -21, "left": 21, "bottom": 51, "right": 408 } } },
{ "param": "Скидка", "note": { "text": "не более 20%", "style": "vtop-bg", "box": { "top": -21, "left": 21, "bottom": 51, "right": 408 } } },
{ "note": { "text": "сдвинуто", "autoSize": false, "box": { "top": 58, "left": -175, "bottom": 362, "right": 478 }, "anchor": { "row": 4, "col": 1 } } }
]
]
}
]
}