fix(mxl-compile,mxl-decompile): висячие ссылки на стиль и культурная сортировка

Два дефекта, найденных при сведении портов.

Стиль, на который ссылалась только дополнительная колоночная раскладка,
отсекался как неиспользуемый: проверка смотрела в result, а columnSets
попадает туда ПОЗЖЕ неё. Ссылка оставалась висячей — 5 макетов пилота
из 40 указывали на стиль, которого в styles нет. Берём стили из самих
раскладок.

Именованные элементы платформа хранит отсортированными по имени ординально.
ps1 сортировал их Sort-Object -CaseSensitive, а он всё равно сравнивает по
текущей культуре — комментарий рядом сам об этом предупреждал. На кириллице
порядок расходился с py-портом (4800 строк разницы на одном макете).
Сортируем по ключу из кодов символов: в нём только 0-9A-F, культура его
переупорядочить не может.

Порты сошлись: JSON декомпиляторов совпадает на всех 40 макетах пилота
(было 26 расхождений), собранный XML — на 39 из 40 (было 20 расхождений).
Остаток — один макет, где расходятся компиляторы: ps1 подставляет
faceName="Arial" height="10" там, где py пишет пустой шрифт.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-08-12 12:03:53 +03:00
co-authored by Claude Opus 5
parent c11f4837fd
commit 6619a4e7ad
3 changed files with 23 additions and 11 deletions
@@ -1,4 +1,4 @@
# 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
param(
[Parameter(Mandatory)]
@@ -1576,8 +1576,14 @@ foreach ($m in $merges) {
# с несколькими элементами иного порядка нет ни разу. Сортировка регистронезависимая и
# ординальная — Sort-Object брать нельзя, он сортирует по текущей культуре и на кириллице
# даст другой порядок. NB: имён с «ё» в выборке не встретилось, этот случай не проверен.
$sortedNamedItems = @($namedItems | Sort-Object -Property @{ Expression = { $_.Name.ToLowerInvariant() } } `
-CaseSensitive)
# Sort-Object сортирует по текущей культуре даже с -CaseSensitive, поэтому сортируем по
# ключу из кодов символов: в нём только 0-9A-F, и культурные правила его переупорядочить
# не могут. Прежний вариант давал на кириллице не тот порядок, что py-порт.
function Get-OrdinalKey {
param([string]$name)
return (($name.ToLowerInvariant().ToCharArray() | ForEach-Object { '{0:X4}' -f [int]$_ }) -join '')
}
$sortedNamedItems = @($namedItems | Sort-Object -Property @{ Expression = { Get-OrdinalKey $_.Name } })
foreach ($ni in $sortedNamedItems) {
# Тип области выводится из указанных осей, как в ТабличныйДокумент.Область():
# нет колонок → полоса строк, нет строк → полоса колонок, обе → прямоугольник.
@@ -1,4 +1,4 @@
# mxl-decompile v1.17 — Decompile 1C spreadsheet to JSON
# mxl-decompile v1.18 — Decompile 1C spreadsheet to JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -1176,7 +1176,10 @@ foreach ($a in $dslAreas) {
if ($cellList) { foreach ($c in $cellList) { if ($c -isnot [string] -and $c.style) { $usedStyles[$c.style] = $true } } }
}
}
# Стиль бывает не только у ячейки и строки: колонка — третий владелец формата.
# Стиль бывает не только у ячейки и строки: колонка — третий владелец формата. Берём стили
# ИЗ САМИХ РАСКЛАДОК, а не из $result: columnSets попадает в результат ПОЗЖЕ этой проверки,
# и стиль, на который ссылается только дополнительная раскладка, был бы отсечён, а ссылка
# на него осталась бы висячей.
foreach ($cs in $columnSets) {
foreach ($name in (Get-ColumnStyles $cs).Values) {
if ($name) { $usedStyles[$name] = $true }
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# mxl-decompile v1.17 — Decompile 1C spreadsheet to JSON
# mxl-decompile v1.18 — Decompile 1C spreadsheet to JSON
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -1184,11 +1184,14 @@ def main():
for c in cell_list:
if isinstance(c, dict) and "style" in c:
used_styles.add(c["style"])
# Стиль бывает не только у ячейки и строки: колонка — третий владелец формата.
for src in [result.get("columnStyles")] + [
(cs or {}).get("columnStyles") for cs in (result.get("columnSets") or {}).values()]:
for name in (src or {}).values():
used_styles.add(name)
# Стиль бывает не только у ячейки и строки: колонка — третий владелец формата. Берём
# стили ИЗ САМИХ РАСКЛАДОК, а не из result: columnSets попадает в результат ПОЗЖЕ этой
# проверки, поэтому стиль, на который ссылается только дополнительная раскладка,
# отсекался, а ссылка на него оставалась висячей (5 макетов пилота из 40).
for cs in column_sets:
for name in column_styles_of(cs).values():
if name:
used_styles.add(name)
to_remove = [s for s in style_defs if s not in used_styles]
for s in to_remove:
del style_defs[s]