Компилятор выводил <Title formatted="…"> из hyperlink (formatted = hyperlink),
но это неверно: атрибут formatted НЕЗАВИСИМ. По корпусу acc+erp:
- 9080 label'ов: hyperlink есть, formatted=false (компилятор давал true);
- 6545: formatted=true без hyperlink (компилятор давал false).
Итого ~15625 расхождений.
Введён отдельный ключ formatted (bool, выводится при true):
- декомпилятор: захват атрибута <Title formatted> у LabelDecoration (независимо
от <Hyperlink>);
- компилятор Emit-Label: formatted из ключа, не из hyperlink.
Декомпилятор (ps1) + компилятор (ps1+py) + spec (label.formatted). Снэпшот
events обновлён: label с hyperlink:true теперь даёт formatted="false" (фиксирует
развязку) — сертифицирован в 1С 8.3.24. Регресс ps+py 33/33.
Остаток <Title formatted> в раундтрипе принадлежит ExtendedTooltip-с-контентом
и PictureDecoration — отдельные кластеры (в BACKLOG).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Два дефекта вокруг текста <v8:content>, оба вскрылись на формах с подсказками.
1. ToolTip элемента (484 LOST в корпусе). <ToolTip> — прямой мультиязычный
текст подсказки на элементе (UsualGroup 42150, Popup, Page, InputField,
и почти все типы). Декомпилятор пропускал (как companion), компилятор не
эмитил. Введён общий ключ tooltip (string|{ru,en}), как title:
- декомпилятор: захват в Add-CommonProps;
- компилятор: эмиссия в Emit-Title (сразу после Title) — покрывает все
эмиттеры, зовущие Emit-Title.
Попутно выяснилось, что Emit-Pages/Emit-CommandBar вовсе не звали Emit-Title
(теряли и Title, и ToolTip), а Emit-Label эмитит Title по-своему — во все три
добавлена обработка title/tooltip.
2. Экранирование кавычек. Esc-Xml экранировал " → " в тексте элемента,
но 1С в <v8:content> пишет " литерально (экранирует только & < >).
Это ломало раундтрип любого текста с кавычками. Убрано экранирование " .
Декомпилятор (ps1) + компилятор (ps1+py) + spec (§4.1 tooltip). Покрытие:
input-fields (input+tooltip), pages (pages/page tooltip, page с кавычкой в
тексте — проверяет литеральность) — сертифицировано в 1С 8.3.24. Раундтрип
БанковскиеСчета/Wildberries/АдреснаяКнига: ToolTip и " остаток = 0.
Регресс ps+py 33/33.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
TitleLocation обрабатывался только у input (passthrough), check/radio
(smart-default) и calendar. У LabelField (7362 в корпусе), PictureField (2479)
и Table (381) тег молча терялся — ни декомпилятор, ни компилятор его не знали.
Профиль доли элементов с тегом: Table 2.9%, LabelField 15.8%, PictureField
80.5% (но 20% без тега). Платформа НЕ всегда эмитит → выбран passthrough
(эмитим при наличии ключа, как у input/calendar), не smart-default. Корректно
и консистентно; переиспользован существующий ключ titleLocation + Map-TitleLoc.
Декомпилятор (ps1): захват titleLocation в трёх ветках. Компилятор (ps1+py):
эмиссия в Emit-LabelField/Emit-Table/Emit-PictureField в позиции по схеме.
spec §4.1: titleLocation вынесен в общие свойства с пометкой охвата.
Тест-покрытие добавлено в input-fields (labelField=left), picture-field
(picField=none), table (table=top) — снэпшоты сертифицированы в 1С 8.3.24.
Раундтрип 60 форм с TitleLocation на label/pic/table/radio: остатка нет.
Регресс ps+py 33/33.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CalendarField терял специфичные свойства при раундтрипе: декомпилятор их не
читал, компилятор не эмитил. Пробел DSL (класс 3). CalendarField — длинный
хвост (18 форм на 17033, 0.1%), но элемент маленький и ограниченный → решено
покрыть целиком, убрав класс молчаливых потерь.
Добавлены ключи (passthrough, эмитятся только при наличии): selectionMode,
showCurrentDate, widthInMonths, heightInMonths, showMonthsPanel. Плюс
подключён общий titleLocation (раньше у календаря не обрабатывался).
Порядок тегов выверен по корпусу (18 форм): DataPath > Title > TitleLocation
> [layout] > SelectionMode > ShowCurrentDate > WidthInMonths > HeightInMonths
> ShowMonthsPanel > companions > Events.
Декомпилятор (ps1) + компилятор (ps1+py) + spec. Новый тест-кейс calendar
(два календаря: со скалярами+событием и с months-panel), сертифицирован
в 1С 8.3.24. Регресс ps+py 33/33.
Tooltip-свойства календаря (ToolTip/ToolTipRepresentation) намеренно оставлены
будущему общему tooltip-кластеру. Раундтрип календарных форм: ПериодКомандировки
→ match; остаточный TitleLocation на radio/table — отдельная находка (BACKLOG).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Несогласованность DSL: события ФОРМЫ описывались интуитивной мапой
events:{Событие:Обработчик}, а события ЭЛЕМЕНТА — двумя сущностями
on:[...] + handlers:{...}. Два способа для одного понятия путали модель.
Унифицировано на единую мапу events:{Событие:ИмяОбработчика} на форме И
элементах (как form-level). Декомпилятор эмитит только её, с явными именами
обработчиков (прозрачно, консистентно с form-level).
Компилятор (ps1+py):
- Emit-Events читает events-мапу (основной формат); значение null/"" →
имя по конвенции ИмяЭлемента+суффикс (прощающий fallback).
- legacy on/handlers по-прежнему принимаются ради совместимости (не эмитятся).
- choiceButton: проверка StartChoice через оба формата (Test-ElementEvent).
- events добавлен в whitelist ключей элемента.
Декомпилятор: Get-Events → упорядоченная мапа {Событие:Обработчик} в порядке
документа; убраны on/handlers и инверсия авто-имён.
spec/SKILL.md: events как единственный рекомендованный формат, on/handlers
помечены legacy. В SKILL.md только явные имена (null-сахар — деталь spec,
инструкцию не раздуваем).
Корпус acc_8.3.24: 190 элементов в 114/400 форм теряли Events до фикса (баг
on/handlers разобран отдельным коммитом). Раундтрип 2.17: Events ушли из топа
LOST, match 4→6, 0 compile-fail. Регресс ps+py 32/32, снэпшот events (добавлен
блок Events у поля с переименованным обработчиком) сертифицирован в 1С 8.3.24.
Follow-up: form-edit использует расширенный on с {event,callType} —
унификация отдельным решением (см. BACKLOG).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
"" означает «не выводить тег» (платформа применит своё рантайм-умолчание),
а не «значение = дефолту платформы». Разведение дефолта эмиссии и дефолта рантайма.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
БАГ: Emit-MLText стрингифицировал мультиязычный объект {ru,en} →
<v8:content>@{ru=…; en=…}</v8:content> (мусор). ERP — двуязычная конфигурация,
поэтому это доминирующий пробел раундтрипа (item/content/lang).
- compiler PS1+PY: Emit-MLItems/emit_ml_items — по <v8:item> на язык; все
вызывающие (Title/ToolTip/InputHint/реквизиты/колонки/команды/форма + Emit-Label)
передают сырой объект вместо стрингификации. choice presentation уже был мультиязычен.
- decompiler уже давал {ru,en}; убран мёртвый titleFormatted (компилятор выводит formatted из hyperlink).
- docs/form-dsl-spec: title/tooltip/inputHint принимают объект {ru,en,…}.
- tests: groups (title {ru,en}) сертифицирован в 1С.
Эффект (220 форм 2.17): item 3909→1475, content 3193→737, lang 1861→635. Регресс 32/32 PS1+PY.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
БАГ: у LabelField платформенный тег <Hiperlink> (опечатка 1С), компилятор
эмитил <Hyperlink> — гиперссылка не работала и не роундтрипилась. Проверено
по корпусу: LabelField→Hiperlink во всех версиях формата (2.17 и 2.20).
- compiler PS1+PY: LabelField <Hiperlink>; EditMode (input/check/labelField);
CheckBoxType (check, умный дефолт Auto + suppress как radioButtonType).
- decompiler: editMode, checkBoxType (Auto→опустить), markIncomplete (раньше не ловился),
labelField читает <Hiperlink>.
- docs/form-dsl-spec: editMode, checkBoxType, примечание про Hiperlink.
- tests: input-fields расширен (editMode/checkBoxType/labelField+hyperlink), сертифицирован.
Регресс 32/32 PS1+PY, churn по флажкам обновлён и сертифицирован.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CommandSet встречается на Table (23) и Form (8). Форменный excludedCommands
уже поддержан, табличный — нет.
- compiler PS1+PY: Emit-Table — excludedCommands → <CommandSet>; заодно
viewStatusLocation/searchControlLocation (из того же блока свойств таблицы).
- decompiler: Table — CommandSet→excludedCommands, searchStringLocation
(раньше не ловился), viewStatusLocation/searchControlLocation.
- docs/form-dsl-spec: excludedCommands + view/searchControl у таблицы.
- tests: table расширен, сертифицирован в 1С.
ExcludedCommand ушёл из топа LOST. Регресс 32/32 PS1+PY, churn нулевой.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Принцип: компилятор не эмитит значение, равное дефолту платформы (который
платформа сама не пишет в XML). Умный дефолт (check→Right, radio→None) —
отдельная вещь, эмитится (он ≠ дефолт платформы Left).
- net ключа titleLocation → умный дефолт; titleLocation: "" → подавить
(дефолт платформы); значение → эмитить с маппингом регистра.
- compiler PS1+PY: Emit-TitleLocation/emit_title_location + Map-TitleLoc
(общий маппинг; у check раньше его не было — сырьё).
- decompiler: Add-TitleLocation (дефолт → опустить, нет тега → "", иначе значение).
- docs/form-dsl-spec: семантика titleLocation у check/radio.
- tests: input-fields расширен (Right-дефолт / ""-подавление / явный Top), сертифицирован.
АварийныйРежим: полный MATCH. Регресс 32/32 PS1+PY, churn нулевой.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Над-генерация заголовков элементов из имени. Различаем:
- нет ключа title → авто-вывод из имени (помощь модели при создании форм);
- title: "" → подавить (<Title> не эмитим);
- непустая строка → как есть.
- compiler PS1+PY: Emit-Title/emit_title + Emit-Label проверяют наличие ключа,
а не truthiness (раньше "" триггерило авто-вывод).
- decompiler: ставит title:"" для авто-выводящих типов (page/popup/label,
непривязанные поля, button без команды), когда <Title> в оригинале отсутствует.
- docs/form-dsl-spec: семантика title.
- tests: pages демонстрирует title:"" (+snapshot, сертифицирован в 1С).
АварийныйРежим: diff 13→1. Регресс 32/32 PS1+PY, churn нулевой.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- compiler PS1+PY: общий Emit-Layout/emit_layout (width/height/stretch/maxWidth/
maxHeight/autoMax*/skipOnInput/groupHorizontalAlign/groupVerticalAlign/
horizontalAlign), вызывается во всех эмиттерах; inline-дубли убраны. Спец-квирки
сохранены (input multiLine→autoMaxWidth, table height→HeightInTableRows).
- PictureDecoration LoadTransparent больше не захардкожен true — управляется
loadTransparent (дефолт false).
- decompiler: Add-Layout (DRY, один вызов на элемент), table HeightInTableRows,
picture loadTransparent.
- docs/form-dsl-spec: блок общих layout-свойств (4.1a), loadTransparent у picture.
- tests: groups расширен layout-свойствами (+snapshot, сертифицирован в 1С).
Churn снапшотов нулевой. АварийныйРежим: LOST полностью закрыт (остаток — над-генерация).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- web-test-guide: раздел про picture-колонки readTable (pic:N/'',
truthy-наличие, именование по тултипу, read/assert-only — не селектор).
- form-dsl-spec: ключи valuesPicture/loadTransparent у picField.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Новый DSL-ключ columnGroup со значением-ориентацией horizontal/vertical/inCell
для элемента <ColumnGroup> внутри columns таблицы. Поддерживает вложение,
showTitle/showInHeader/width, тихие синонимы ColumnGroup и ГруппаКолонок.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>