From 934462f4d22f20b8584ee502842a89e2b463fdc7 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Fri, 12 Jun 2026 21:45:49 +0300 Subject: [PATCH] =?UTF-8?q?fix(form-compile):=20Save=20Field=20=E2=80=94?= =?UTF-8?q?=20=D0=BD=D0=B5=20=D0=BF=D1=80=D0=B5=D1=84=D0=B8=D0=BA=D1=81?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20=D1=81=D1=81=D1=8B=D0=BB=D0=BA?= =?UTF-8?q?=D1=83=20=D0=B2=D0=B8=D0=B4=D0=B0=20N/M=20=D0=B1=D0=B5=D0=B7=20?= =?UTF-8?q?=D0=B4=D0=B2=D0=BE=D0=B5=D1=82=D0=BE=D1=87=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Поле вида N/M (ссылка на элемент/колонку, напр. 5/0, 5/1) без двоеточия получало лишний префикс имени реквизита (ДатаОкончанияПериода.5/0) — условие «оставить как есть» ловило только N/M: с двоеточием (^\d+/\d+:). Форма ОтражениеДокументовВМеждународномУчете. Фикс: ^\d+/\d+: → ^\d+/\d+ (bare N/M тоже как есть). Корпус 8.3.24: N/M bare 10, N/M: 746 (уже обрабатывался). Декомпилятор симметричен (strip префикса имя. иначе как есть) — не менялся. Форма → match. Снэпшоты не затронуты (N/M в кейсах не встречается), регресс 43/43 (ps1+py). Валидация раундтрипом shipped-формы (грузится в 1С; N/M — платформенная ссылка, эмитим verbatim). Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/skills/form-compile/scripts/form-compile.ps1 | 4 ++-- .claude/skills/form-compile/scripts/form-compile.py | 4 ++-- docs/form-dsl-spec.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index 8550cf5b..e140c855 100644 --- a/.claude/skills/form-compile/scripts/form-compile.ps1 +++ b/.claude/skills/form-compile/scripts/form-compile.ps1 @@ -1,4 +1,4 @@ -# form-compile v1.144 — Compile 1C managed form from JSON or object metadata +# form-compile v1.145 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -5533,7 +5533,7 @@ function Emit-Attributes { foreach ($e in @($attr.save)) { $fld = "$e" if ([string]::IsNullOrEmpty($fld)) { continue } - if ($fld -ne $attrName -and $fld -notmatch '\.' -and $fld -notmatch '^\d+/\d+:') { $fld = "$attrName.$fld" } + if ($fld -ne $attrName -and $fld -notmatch '\.' -and $fld -notmatch '^\d+/\d+') { $fld = "$attrName.$fld" } if (-not $saveFields.Contains($fld)) { [void]$saveFields.Add($fld) } } } diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 9b768a6a..0b8121df 100644 --- a/.claude/skills/form-compile/scripts/form-compile.py +++ b/.claude/skills/form-compile/scripts/form-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-compile v1.144 — Compile 1C managed form from JSON or object metadata +# form-compile v1.145 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -5296,7 +5296,7 @@ def emit_attributes(lines, attrs, indent, conditional_appearance=None): fld = str(e) if not fld: continue - if fld != attr_name and '.' not in fld and not re.match(r'^\d+/\d+:', fld): + if fld != attr_name and '.' not in fld and not re.match(r'^\d+/\d+', fld): fld = f'{attr_name}.{fld}' if fld not in save_fields: save_fields.append(fld) diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md index 66e7ea38..ed6bd6f6 100644 --- a/docs/form-dsl-spec.md +++ b/docs/form-dsl-spec.md @@ -851,7 +851,7 @@ Forgiving-синонимы типа: XML-имя (`SpreadSheetDocumentField`) и | `useAlways` | array | Поля, всегда читаемые (`Имя.Поле…`). Массив коротких имён полей (forgiving: с/без префикса `Имя.`). **Маркер `~`** (query-поля дин-списка): `~Остановлен` → `~Список.Остановлен` (префикс ставится ПОСЛЕ `~`; полная форма `~Список.Остановлен` тоже принимается verbatim). **Две формы**: этот массив на реквизите ИЛИ `useAlways: true` на колонке (`columns[*]`) — компилятор сливает. Для дин-списка — только массив (колонки не эмитятся, но формируют ``) | | `valueType` | string | Тип значений у реквизита типа `ValueList` (``). Грамматика — как у `type`, включая составной `A \| B`. **Три состояния**: нет ключа → нет ``; `""` → пустой `` (список без ограничения типа); тип → с типом. Forgiving-синонимы: `typeDescription` (≈1С «ОписаниеТипов» / XML), `описаниеТипов`, `типЗначений`. Пример: `"valueType": "CatalogRef.Контрагенты"` | | `savedData` | bool | Сохраняемые данные (``). **`false`** → суппресс авто-вывода компилятора (main-реквизит объектного типа Catalog/Document/ChartOf*/ExchangePlan/BusinessProcess/Task Object + RecordManager → `SavedData=true`). Нет ключа → авто-вывод | -| `save` | bool/string/array | Сохранение значения в пользовательских настройках (`…`). `true` → `имя`; строка/массив строк → под-поля с авто-префиксом `имя.` (путь с точкой / UUID `1/0:…` / совпадающее с именем — берётся как есть). Нет ключа или `false` → не эмитится. Пример периода: `["Период","EndDate","StartDate","Variant"]` | +| `save` | bool/string/array | Сохранение значения в пользовательских настройках (`…`). `true` → `имя`; строка/массив строк → под-поля с авто-префиксом `имя.` (путь с точкой / ссылка вида `N/M` или `N/M:…` / совпадающее с именем — берётся как есть). Нет ключа или `false` → не эмитится. Пример периода: `["Период","EndDate","StartDate","Variant"]` | | `fillCheck` | bool/string | Проверка заполнения реквизита (``). `true` → `ShowError` (единственное значение в схеме); строка → verbatim. Синоним `fillChecking`. (`` в схеме нет — был багом) | | `columns` | array | Колонки для ValueTable/ValueTree (`{ name, type, title?, functionalOptions?, view?, edit?, useAlways? }`). `view`/`edit` — ролевой доступ колонки (``/`` xr-флаг, тот же формат `bool \| {common, roles}`, что у реквизита, §4.1c; редкое) | | `additionalColumns` | array | Доп. колонки табличных частей объекта: `[{ table: "Объект.ТабЧасть", columns: [] }]`. У главного реквизита-объекта; `` — та же грамматика, что у `columns`. Эмитятся в `` после прямых колонок |