From 0a8671a1664a89385e2ea6c7a828cdd2607675da Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Wed, 12 Aug 2026 12:21:02 +0300 Subject: [PATCH] =?UTF-8?q?feat(mxl-compile,mxl-decompile):=20=D0=BF=D1=83?= =?UTF-8?q?=D1=81=D1=82=D0=BE=D0=B9=20=D1=82=D0=B5=D0=B3=20=D1=82=D0=B5?= =?UTF-8?q?=D0=BA=D1=81=D1=82=D0=B0=20=D1=8F=D1=87=D0=B5=D0=B9=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit У текста ячейки три состояния, а выражались два: тега нет вовсе, тег с пустым текстом на каждый язык — и третье, , которое мы теряли. Это не редкость: 38 075 ячеек на 1200 макетов, встречается в 57% макетов корпуса. Выражается пустым объектом: "text": {}. Не новый ключ и не новое понятие, а вырожденный случай уже принятой записи «язык → текст» — языков нет вовсе. В позиционной строке двусмысленности не создаёт: {} не несёт ключей ячейки, значит по общему правилу читается как текст, а null там по-прежнему «пропустить колонку». В описании DSL записи нет намеренно. Для авторинга она бесполезна — визуально это тот же пустой текст, что и "", — а документировать две пустые формы рядом значило бы завести развилку, у которой нет правильного ответа. Платформа пишет такой тег самозакрывающимся, поэтому эмиссия отдельной веткой. На пилоте потери в категории row[].cell[].tl упали с 12 488 до 2, заодно row[].cell[].fmt с 41 645 до 30 088; совпадение строк документа 17.6% → 18.5%. Co-Authored-By: Claude Opus 5 (1M context) --- .claude/skills/mxl-compile/scripts/mxl-compile.ps1 | 9 ++++++++- .claude/skills/mxl-compile/scripts/mxl-compile.py | 8 +++++++- .claude/skills/mxl-decompile/scripts/mxl-decompile.ps1 | 10 ++++++++-- .claude/skills/mxl-decompile/scripts/mxl-decompile.py | 10 ++++++++-- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 b/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 index 69f77f78..99b0ec6d 100644 --- a/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 +++ b/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 @@ -1,4 +1,4 @@ -# mxl-compile v1.38 — Compile 1C spreadsheet from JSON +# mxl-compile v1.39 — Compile 1C spreadsheet from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -800,6 +800,13 @@ function Emit-CellText { } else { foreach ($l in $textLanguages) { $pairs += @{ Lang = $l; Text = "$value" } } } + # Пустой объект — отдельное состояние: тег текста есть, языков в нём нет. Платформа + # пишет его самозакрывающимся. Для авторинга бесполезно (визуально это тот же пустой + # текст, что и ""), поэтому в описании DSL записи нет — она нужна раундтрипу. + if ($pairs.Count -eq 0) { + X "`t`t`t`t`t" + return + } X "`t`t`t`t`t" foreach ($p in $pairs) { X "`t`t`t`t`t`t" diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.py b/.claude/skills/mxl-compile/scripts/mxl-compile.py index 94bca504..6960b088 100644 --- a/.claude/skills/mxl-compile/scripts/mxl-compile.py +++ b/.claude/skills/mxl-compile/scripts/mxl-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# mxl-compile v1.37 — Compile 1C spreadsheet from JSON +# mxl-compile v1.38 — Compile 1C spreadsheet from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import hashlib @@ -850,6 +850,12 @@ def main(): pairs = [(str(k), str(v)) for k, v in value.items()] else: pairs = [(lang, str(value)) for lang in text_languages] + # Пустой объект — отдельное состояние: тег текста есть, языков в нём нет. Платформа + # пишет его самозакрывающимся. Для авторинга бесполезно (визуально это тот же пустой + # текст, что и ""), поэтому в описании DSL записи нет — она нужна раундтрипу. + if not pairs: + lines.append('\t\t\t\t\t') + return lines.append('\t\t\t\t\t') for lang, content in pairs: lines.append('\t\t\t\t\t\t') diff --git a/.claude/skills/mxl-decompile/scripts/mxl-decompile.ps1 b/.claude/skills/mxl-decompile/scripts/mxl-decompile.ps1 index 5d370d89..93e27ff2 100644 --- a/.claude/skills/mxl-decompile/scripts/mxl-decompile.ps1 +++ b/.claude/skills/mxl-decompile/scripts/mxl-decompile.ps1 @@ -1,4 +1,4 @@ -# mxl-decompile v1.18 — Decompile 1C spreadsheet to JSON +# mxl-decompile v1.19 — Decompile 1C spreadsheet to JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -314,8 +314,14 @@ foreach ($riNode in $root.SelectNodes("d:rowsItem", $ns)) { # известен набор языков всего макета (Get-DslText). $text = $null $hasText = $false + # Пустой — отдельное состояние: тег текста есть, языков в нём нет. Без + # этого ветвления такая ячейка теряла текст вовсе (1 из 15 ячеек с тегом текста). + $tlNode = $cContent.SelectSingleNode("d:tl", $ns) $items = $cContent.SelectNodes("d:tl/v8:item", $ns) - if ($items -and $items.Count -gt 0) { + if ($tlNode -and (-not $items -or $items.Count -eq 0)) { + $text = [ordered]@{} + $hasText = $true + } elseif ($items -and $items.Count -gt 0) { $byLang = [ordered]@{} foreach ($it in $items) { $langNode = $it.SelectSingleNode("v8:lang", $ns) diff --git a/.claude/skills/mxl-decompile/scripts/mxl-decompile.py b/.claude/skills/mxl-decompile/scripts/mxl-decompile.py index e22d9ed5..1bc80ee6 100644 --- a/.claude/skills/mxl-decompile/scripts/mxl-decompile.py +++ b/.claude/skills/mxl-decompile/scripts/mxl-decompile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# mxl-decompile v1.18 — Decompile 1C spreadsheet to JSON +# mxl-decompile v1.19 — Decompile 1C spreadsheet to JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -483,8 +483,14 @@ def main(): # известен набор языков всего макета (get_dsl_text). text = None has_text = False + # Пустой — отдельное состояние: тег текста есть, языков в нём нет. Без + # этого ветвления такая ячейка теряла текст вовсе (1 из 15 ячеек с тегом текста). + tl_node = find(c_content, "d:tl") items = findall(c_content, "d:tl/v8:item") - if items: + if tl_node is not None and not items: + text = OrderedDict() + has_text = True + elif items: by_lang = OrderedDict() for it in items: lang_node = find(it, "v8:lang")