mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-13 06:53:21 +03:00
fix(mxl-decompile): свести порты — пробелы, порядок и свойства значения ячейки
Расхождение JSON между портами было 26 макетов из 40, стало 5. Расхождение собранного XML — 20 из 40, стало 7. Причин оказалось четыре, и три из них дефекты, а не просто разнобой. 1. ps1 грузил XML с PreserveWhitespace = $false, и текст ячейки из одних пробелов схлопывался в пустой. Молчаливая потеря данных в каноничном порте, 25 макетов пилота. 2. Стили обнаруживались обходом хэш-таблицы строк, а её порядок в PowerShell НЕ определён. Платформа же кладёт записи палитры в порядке документа, так что порядок обхода — часть верности вывода, а не деталь. Обход теперь по возрастанию номера строки. ([ordered] тут не годится: с целочисленными ключами он индексируется по позиции, а не по ключу.) 3. Именованные области сортировались нестабильным Sort-Object (-Stable появился только в PowerShell 6.2), поэтому области с одинаковыми границами получали произвольный порядок. Добавлен явный ключ исходного порядка — в оба порта, чтобы совпадение было по построению, а не по совпадению. 4. containsValue / valueType / controlType протекали в styles сквозным пробросом неизвестных тегов. Это свойства ЗНАЧЕНИЯ ячейки, а не оформления, и компилятор таких ключей не знает — в DSL они были чистым шумом. Заодно вложенный элемент больше не читается как скаляр: ps1 брал InnerText и получал склейку поддерева, py брал .text и получал пустоту. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e46db618e3
commit
c11f4837fd
@@ -1,4 +1,4 @@
|
||||
# mxl-decompile v1.16 — Decompile 1C spreadsheet to JSON
|
||||
# mxl-decompile v1.17 — Decompile 1C spreadsheet to JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -19,7 +19,9 @@ if (-not (Test-Path $TemplatePath)) {
|
||||
}
|
||||
|
||||
$xmlDoc = New-Object System.Xml.XmlDocument
|
||||
$xmlDoc.PreserveWhitespace = $false
|
||||
# PreserveWhitespace = $false схлопывает узел из одних пробелов в пустой, и текст ячейки
|
||||
# вида " " терялся молча (25 макетов пилота). Значащие пробелы в тексте надписи есть.
|
||||
$xmlDoc.PreserveWhitespace = $true
|
||||
$xmlDoc.Load((Resolve-Path $TemplatePath).Path)
|
||||
|
||||
$root = $xmlDoc.DocumentElement
|
||||
@@ -139,6 +141,9 @@ foreach ($fmtNode in $root.SelectNodes("d:format", $ns)) {
|
||||
if ($item -and $item.InnerText) { $fmt.Props[$tag] = $item.InnerText }
|
||||
continue
|
||||
}
|
||||
# Вложенный элемент скаляром не является: InnerText склеил бы всё поддерево вместе
|
||||
# с переводами строк. py-порт брал .text и получал пустоту — отсюда расхождение портов.
|
||||
if ($child.SelectNodes('*').Count -gt 0) { continue }
|
||||
$val = $child.InnerText
|
||||
if ([string]::IsNullOrWhiteSpace($val)) { continue }
|
||||
if ($formatKinds[$tag] -ceq 'color') { $val = ConvertTo-DslColor $child $val }
|
||||
@@ -246,6 +251,10 @@ foreach ($niNode in $root.SelectNodes("d:namedItem", $ns)) {
|
||||
}
|
||||
|
||||
$namedAreas += @{
|
||||
# Порядок в исходнике: Sort-Object в PowerShell 5.1 НЕстабилен (-Stable появился
|
||||
# в 6.2), поэтому области с одинаковыми границами получали произвольный порядок,
|
||||
# и вывод расходился с py-портом от запуска к запуску.
|
||||
Ord = $namedAreas.Count
|
||||
Name = $niNode.SelectSingleNode("d:name", $ns).InnerText
|
||||
Type = $areaNode.SelectSingleNode("d:type", $ns).InnerText
|
||||
BeginRow = & $getCoord 'beginRow'
|
||||
@@ -368,7 +377,11 @@ function Get-DslText {
|
||||
|
||||
# Свойства формата, которые стилем НЕ являются: ширина принадлежит колонке, высота —
|
||||
# строке, вид заполнения выводится из того, чем задано содержимое ячейки.
|
||||
$nonStyleTags = @('width', 'height', 'fillType', 'font')
|
||||
# containsValue/valueType/controlType — свойства ЗНАЧЕНИЯ ячейки, а не оформления: стиль
|
||||
# общий на многие ячейки, а они индивидуальны. Компилятор таких ключей не знает, так что
|
||||
# в DSL они были чистым шумом.
|
||||
$nonStyleTags = @('width', 'height', 'fillType', 'font',
|
||||
'containsValue', 'valueType', 'controlType')
|
||||
$borderTags = @('border', 'leftBorder', 'topBorder', 'rightBorder', 'bottomBorder')
|
||||
|
||||
function ConvertTo-DslLine {
|
||||
@@ -492,7 +505,11 @@ for ($i = 1; $i -lt $rawFonts.Count; $i++) {
|
||||
$styleKeys = [ordered]@{}
|
||||
$formatToStyleKey = @{}
|
||||
|
||||
foreach ($r in $rowData.Values) {
|
||||
# Обход по ВОЗРАСТАНИЮ номера строки: у обычной хэш-таблицы порядок в PowerShell не
|
||||
# определён, и стили обнаруживались в порядке хэшей. Платформа же кладёт записи палитры
|
||||
# в порядке документа, поэтому порядок обхода здесь — часть верности вывода.
|
||||
# ([ordered] с целочисленными ключами не годится: он индексируется по позиции, а не по ключу.)
|
||||
foreach ($r in ($rowData.Keys | Sort-Object { [int]$_ } | ForEach-Object { $rowData[$_] })) {
|
||||
foreach ($cell in $r.Cells) {
|
||||
$fmt = Get-Format $cell.FormatIdx
|
||||
if (-not $fmt) { continue }
|
||||
@@ -520,7 +537,7 @@ function Get-RowStyleFmt {
|
||||
}
|
||||
|
||||
# Строка — тоже владелец формата: её оформление становится именованным стилем.
|
||||
foreach ($rd in $rowData.Values) {
|
||||
foreach ($rd in ($rowData.Keys | Sort-Object { [int]$_ } | ForEach-Object { $rowData[$_] })) {
|
||||
if ($rd.FormatIdx -le 0) { continue }
|
||||
$rf = Get-RowStyleFmt (Get-Format $rd.FormatIdx)
|
||||
if (-not $rf) { continue }
|
||||
@@ -844,7 +861,7 @@ function Test-UniformColumnSet {
|
||||
$blockAreas = @()
|
||||
$overlayAreas = @()
|
||||
$claimed = @{} # строка → занята областью-диапазоном
|
||||
foreach ($a in @($namedAreas | Sort-Object @{ Expression = { $_.BeginRow } }, @{ Expression = { $_.EndRow } })) {
|
||||
foreach ($a in @($namedAreas | Sort-Object @{ Expression = { $_.BeginRow } }, @{ Expression = { $_.EndRow } }, @{ Expression = { $_.Ord } })) {
|
||||
$fitsBlock = ($a.Type -eq 'Rows' -and $a.BeginRow -ge 0 -and $a.EndRow -ge $a.BeginRow)
|
||||
if ($fitsBlock) {
|
||||
for ($r = $a.BeginRow; $r -le $a.EndRow; $r++) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# mxl-decompile v1.16 — Decompile 1C spreadsheet to JSON
|
||||
# mxl-decompile v1.17 — Decompile 1C spreadsheet to JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -308,6 +308,10 @@ def main():
|
||||
if val:
|
||||
fmt["Props"][tag] = val
|
||||
continue
|
||||
# Вложенный элемент скаляром не является: .text дал бы пустоту, а ps1-порт брал
|
||||
# InnerText и получал склейку поддерева — отсюда расхождение портов.
|
||||
if len(child):
|
||||
continue
|
||||
val = (child.text or "").strip()
|
||||
if not val:
|
||||
continue
|
||||
@@ -409,6 +413,9 @@ def main():
|
||||
return int_of(n) if n is not None else -1
|
||||
|
||||
named_areas.append({
|
||||
# Порядок в исходнике — явный ключ сортировки: sorted тут стабилен, а
|
||||
# Sort-Object в ps1 нет, и без него порты расходились.
|
||||
"Ord": len(named_areas),
|
||||
"Name": text_of(find(ni_node, "d:name")) or "",
|
||||
"Type": text_of(find(area_node, "d:type")) or "",
|
||||
"BeginRow": coord("beginRow"),
|
||||
@@ -535,7 +542,11 @@ def main():
|
||||
|
||||
# Свойства формата, которые стилем НЕ являются: ширина принадлежит колонке, высота —
|
||||
# строке, вид заполнения выводится из того, чем задано содержимое ячейки.
|
||||
NON_STYLE_TAGS = ("width", "height", "fillType", "font")
|
||||
# containsValue/valueType/controlType — свойства ЗНАЧЕНИЯ ячейки, а не оформления: стиль
|
||||
# общий на многие ячейки, а они индивидуальны. Компилятор таких ключей не знает, так что
|
||||
# в DSL они были чистым шумом.
|
||||
NON_STYLE_TAGS = ("width", "height", "fillType", "font",
|
||||
"containsValue", "valueType", "controlType")
|
||||
BORDER_TAGS = ("border", "leftBorder", "topBorder", "rightBorder", "bottomBorder")
|
||||
|
||||
def line_to_dsl(idx):
|
||||
@@ -853,7 +864,7 @@ def main():
|
||||
block_areas = []
|
||||
overlay_areas = []
|
||||
claimed = set()
|
||||
for a in sorted(named_areas, key=lambda x: (x["BeginRow"], x["EndRow"])):
|
||||
for a in sorted(named_areas, key=lambda x: (x["BeginRow"], x["EndRow"], x["Ord"])):
|
||||
fits = a["Type"] == "Rows" and a["BeginRow"] >= 0 and a["EndRow"] >= a["BeginRow"]
|
||||
if fits:
|
||||
for r in range(a["BeginRow"], a["EndRow"] + 1):
|
||||
|
||||
Reference in New Issue
Block a user