mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-13 15:03:20 +03:00
fix(mxl-decompile): абсолютный OutputPath + общий сериализатор декомпиляторов
Безусловная склейка OutputPath с текущим каталогом давала "C:\cwd\C:\out.json" и роняла запись сообщением про формат пути — навык не умел писать по абсолютному пути вообще. Py-порт этот случай обрабатывал, ps1 нет. Приведено к общей идиоме репозитория; кейс на абсолютный путь падает без правки и проходит с ней. Кейс заодно вскрыл, что порты пишут РАЗНЫЙ JSON: ps1 отдавал стиль ConvertTo-Json из PS 5.1 (выравнивание ключей, \uXXXX вместо кириллицы), py — json.dumps(indent=2). Один и тот же макет давал 4708 байт против 1744. Не всплывало потому, что ни один кейс не снимал сам JSON — все проверяли только stdout. mxl-decompile был единственным декомпилятором мимо общего сериализатора: у form/meta/skd-decompile для этого свой ConvertTo-CompactJson. Перенесён вариант skd-decompile как самый полный, py дополнительно переведён на newline='' — как у соседей. Теперь порты совпадают байт в байт, а decompile→compile даёт исходный XML байт в байт. Семья заведена в check-inline-drift.mjs (4 функции, 3 варианта): раньше шесть копий жили вообще без гарда. В form-decompile переименована локальная переменная в string-literal — копии различались только ею. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f33436adff
commit
ccbbecbcf2
@@ -1,4 +1,4 @@
|
||||
# form-decompile v0.148 — Decompile 1C managed Form.xml to JSON DSL (draft)
|
||||
# form-decompile v0.149 — Decompile 1C managed Form.xml to JSON DSL (draft)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
|
||||
param(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# form-decompile v0.148 — Decompile 1C managed Form.xml to JSON DSL (draft)
|
||||
# form-decompile v0.149 — Decompile 1C managed Form.xml to JSON DSL (draft)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
|
||||
#
|
||||
@@ -103,29 +103,29 @@ def _attr(node, name, ns_uri=None):
|
||||
def convert_string_to_json_literal(s):
|
||||
if s is None:
|
||||
return 'null'
|
||||
sb = ['"']
|
||||
out = ['"']
|
||||
for ch in s:
|
||||
code = ord(ch)
|
||||
if code == 0x22:
|
||||
sb.append('\\"')
|
||||
out.append('\\"')
|
||||
elif code == 0x5C:
|
||||
sb.append('\\\\')
|
||||
out.append('\\\\')
|
||||
elif code == 0x08:
|
||||
sb.append('\\b')
|
||||
out.append('\\b')
|
||||
elif code == 0x09:
|
||||
sb.append('\\t')
|
||||
out.append('\\t')
|
||||
elif code == 0x0A:
|
||||
sb.append('\\n')
|
||||
out.append('\\n')
|
||||
elif code == 0x0C:
|
||||
sb.append('\\f')
|
||||
out.append('\\f')
|
||||
elif code == 0x0D:
|
||||
sb.append('\\r')
|
||||
out.append('\\r')
|
||||
elif code < 0x20:
|
||||
sb.append('\\u%04x' % code)
|
||||
out.append('\\u%04x' % code)
|
||||
else:
|
||||
sb.append(ch)
|
||||
sb.append('"')
|
||||
return ''.join(sb)
|
||||
out.append(ch)
|
||||
out.append('"')
|
||||
return ''.join(out)
|
||||
|
||||
|
||||
def _num_to_str(obj):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# mxl-decompile v1.1 — Decompile 1C spreadsheet to JSON
|
||||
# mxl-decompile v1.2 — Decompile 1C spreadsheet to JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -618,22 +618,146 @@ $result["fonts"] = $fontsOut
|
||||
$result["styles"] = $styleDefs
|
||||
$result["areas"] = [array]$dslAreas
|
||||
|
||||
# --- 16. Convert to JSON and fix Unicode ---
|
||||
# --- 16. Convert to JSON ---
|
||||
|
||||
$json = $result | ConvertTo-Json -Depth 10
|
||||
# Custom JSON serializer — компактный, 2-пробельный indent, массивы примитивов inline.
|
||||
# В отличие от ConvertTo-Json (PS5.1):
|
||||
# - не выравнивает ключи объекта по самому длинному
|
||||
# - не разворачивает массивы примитивов на отдельные строки
|
||||
# - кириллица в UTF-8 (без \uXXXX-escapes)
|
||||
function Convert-StringToJsonLiteral {
|
||||
param([string]$s)
|
||||
if ($null -eq $s) { return 'null' }
|
||||
$sb = New-Object System.Text.StringBuilder
|
||||
[void]$sb.Append('"')
|
||||
foreach ($ch in $s.ToCharArray()) {
|
||||
$code = [int]$ch
|
||||
if ($code -eq 0x22) { [void]$sb.Append('\"') }
|
||||
elseif ($code -eq 0x5C) { [void]$sb.Append('\\') }
|
||||
elseif ($code -eq 0x08) { [void]$sb.Append('\b') }
|
||||
elseif ($code -eq 0x09) { [void]$sb.Append('\t') }
|
||||
elseif ($code -eq 0x0A) { [void]$sb.Append('\n') }
|
||||
elseif ($code -eq 0x0C) { [void]$sb.Append('\f') }
|
||||
elseif ($code -eq 0x0D) { [void]$sb.Append('\r') }
|
||||
elseif ($code -lt 0x20) { [void]$sb.AppendFormat('\u{0:x4}', $code) }
|
||||
else { [void]$sb.Append($ch) }
|
||||
}
|
||||
[void]$sb.Append('"')
|
||||
return $sb.ToString()
|
||||
}
|
||||
|
||||
# PS 5.1 escapes non-ASCII as \uXXXX — unescape back to UTF-8
|
||||
$json = [regex]::Replace($json, '\\u([0-9A-Fa-f]{4})', {
|
||||
param($m)
|
||||
[char][int]("0x" + $m.Groups[1].Value)
|
||||
})
|
||||
# Попробовать сериализовать значение полностью inline (одна строка).
|
||||
# Возвращает строку либо $null, если содержимое не помещается.
|
||||
function Try-InlineJson {
|
||||
param($obj)
|
||||
if ($null -eq $obj) { return 'null' }
|
||||
if ($obj -is [bool]) { if ($obj) { return 'true' } else { return 'false' } }
|
||||
if ($obj -is [string]) { return (Convert-StringToJsonLiteral $obj) }
|
||||
if ($obj -is [int] -or $obj -is [long]) { return "$obj" }
|
||||
if ($obj -is [double] -or $obj -is [single] -or $obj -is [decimal]) {
|
||||
return ([System.Convert]::ToString($obj, [System.Globalization.CultureInfo]::InvariantCulture))
|
||||
}
|
||||
if ($obj -is [System.Collections.IDictionary]) {
|
||||
if ($obj.Count -eq 0) { return '{}' }
|
||||
$parts = @()
|
||||
foreach ($k in $obj.Keys) {
|
||||
$v = Try-InlineJson $obj[$k]
|
||||
if ($null -eq $v) { return $null }
|
||||
$parts += "$(Convert-StringToJsonLiteral "$k"): $v"
|
||||
}
|
||||
return '{ ' + ($parts -join ', ') + ' }'
|
||||
}
|
||||
if ($obj -is [System.Management.Automation.PSCustomObject]) {
|
||||
$props = @($obj.PSObject.Properties)
|
||||
if ($props.Count -eq 0) { return '{}' }
|
||||
$parts = @()
|
||||
foreach ($p in $props) {
|
||||
$v = Try-InlineJson $p.Value
|
||||
if ($null -eq $v) { return $null }
|
||||
$parts += "$(Convert-StringToJsonLiteral "$($p.Name)"): $v"
|
||||
}
|
||||
return '{ ' + ($parts -join ', ') + ' }'
|
||||
}
|
||||
if ($obj -is [array] -or $obj -is [System.Collections.IList]) {
|
||||
$items = @($obj)
|
||||
if ($items.Count -eq 0) { return '[]' }
|
||||
$parts = @()
|
||||
foreach ($it in $items) {
|
||||
$v = Try-InlineJson $it
|
||||
if ($null -eq $v) { return $null }
|
||||
$parts += $v
|
||||
}
|
||||
return '[' + ($parts -join ', ') + ']'
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
function ConvertTo-CompactJson {
|
||||
param($obj, [int]$depth = 0, [string]$indentUnit = ' ', [int]$lineLimit = 400)
|
||||
$indent = $indentUnit * $depth
|
||||
$childIndent = $indentUnit * ($depth + 1)
|
||||
|
||||
if ($null -eq $obj) { return 'null' }
|
||||
if ($obj -is [bool]) { if ($obj) { return 'true' } else { return 'false' } }
|
||||
if ($obj -is [string]) { return (Convert-StringToJsonLiteral $obj) }
|
||||
if ($obj -is [int] -or $obj -is [long]) { return "$obj" }
|
||||
if ($obj -is [double] -or $obj -is [single] -or $obj -is [decimal]) {
|
||||
return ([System.Convert]::ToString($obj, [System.Globalization.CultureInfo]::InvariantCulture))
|
||||
}
|
||||
|
||||
# Try inline для объектов и массивов с объектами — если помещается в lineLimit с учётом текущего indent.
|
||||
$isContainer = ($obj -is [System.Collections.IDictionary]) -or ($obj -is [System.Management.Automation.PSCustomObject]) -or ($obj -is [array]) -or ($obj -is [System.Collections.IList])
|
||||
if ($isContainer) {
|
||||
$inlineAttempt = Try-InlineJson $obj
|
||||
if ($null -ne $inlineAttempt -and ($indent.Length + $inlineAttempt.Length) -le $lineLimit) {
|
||||
return $inlineAttempt
|
||||
}
|
||||
}
|
||||
|
||||
# Hashtable / OrderedDictionary — объект multi-line
|
||||
if ($obj -is [System.Collections.IDictionary]) {
|
||||
$keys = @($obj.Keys)
|
||||
if ($keys.Count -eq 0) { return '{}' }
|
||||
$parts = @()
|
||||
foreach ($k in $keys) {
|
||||
$val = ConvertTo-CompactJson -obj $obj[$k] -depth ($depth + 1) -indentUnit $indentUnit -lineLimit $lineLimit
|
||||
$parts += "$childIndent$(Convert-StringToJsonLiteral "$k"): $val"
|
||||
}
|
||||
return "{`n" + ($parts -join ",`n") + "`n$indent}"
|
||||
}
|
||||
if ($obj -is [System.Management.Automation.PSCustomObject]) {
|
||||
$props = @($obj.PSObject.Properties)
|
||||
if ($props.Count -eq 0) { return '{}' }
|
||||
$parts = @()
|
||||
foreach ($p in $props) {
|
||||
$val = ConvertTo-CompactJson -obj $p.Value -depth ($depth + 1) -indentUnit $indentUnit -lineLimit $lineLimit
|
||||
$parts += "$childIndent$(Convert-StringToJsonLiteral "$($p.Name)"): $val"
|
||||
}
|
||||
return "{`n" + ($parts -join ",`n") + "`n$indent}"
|
||||
}
|
||||
# Array / IList multi-line
|
||||
if ($obj -is [array] -or $obj -is [System.Collections.IList]) {
|
||||
$items = @($obj)
|
||||
if ($items.Count -eq 0) { return '[]' }
|
||||
$parts = @($items | ForEach-Object { "$childIndent$(ConvertTo-CompactJson -obj $_ -depth ($depth + 1) -indentUnit $indentUnit -lineLimit $lineLimit)" })
|
||||
return "[`n" + ($parts -join ",`n") + "`n$indent]"
|
||||
}
|
||||
# Fallback
|
||||
return (Convert-StringToJsonLiteral "$obj")
|
||||
}
|
||||
|
||||
$json = ConvertTo-CompactJson $result
|
||||
|
||||
# --- 17. Output ---
|
||||
|
||||
if ($OutputPath) {
|
||||
# Путь принимаем и относительным, и абсолютным: безусловная склейка с текущим каталогом
|
||||
# давала "C:\cwd\C:\out.json" и роняла WriteAllText сообщением про формат пути.
|
||||
$outAbs = if ([System.IO.Path]::IsPathRooted($OutputPath)) { $OutputPath }
|
||||
else { Join-Path (Get-Location).Path $OutputPath }
|
||||
$enc = New-Object System.Text.UTF8Encoding($false)
|
||||
[System.IO.File]::WriteAllText(
|
||||
(Join-Path (Get-Location) $OutputPath),
|
||||
$outAbs,
|
||||
$json,
|
||||
$enc
|
||||
)
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
# mxl-decompile v1.1 — Decompile 1C spreadsheet to JSON
|
||||
# mxl-decompile v1.2 — Decompile 1C spreadsheet to JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from collections import OrderedDict
|
||||
@@ -63,6 +62,122 @@ def int_of(node, default=0):
|
||||
return default
|
||||
|
||||
|
||||
# Custom JSON serializer — компактный, 2-пробельный indent, массивы примитивов inline.
|
||||
# В отличие от ConvertTo-Json (PS5.1):
|
||||
# - не выравнивает ключи объекта по самому длинному
|
||||
# - не разворачивает массивы примитивов на отдельные строки
|
||||
# - кириллица в UTF-8 (без \uXXXX-escapes)
|
||||
def convert_string_to_json_literal(s):
|
||||
if s is None:
|
||||
return 'null'
|
||||
out = ['"']
|
||||
for ch in s:
|
||||
code = ord(ch)
|
||||
if code == 0x22:
|
||||
out.append('\\"')
|
||||
elif code == 0x5C:
|
||||
out.append('\\\\')
|
||||
elif code == 0x08:
|
||||
out.append('\\b')
|
||||
elif code == 0x09:
|
||||
out.append('\\t')
|
||||
elif code == 0x0A:
|
||||
out.append('\\n')
|
||||
elif code == 0x0C:
|
||||
out.append('\\f')
|
||||
elif code == 0x0D:
|
||||
out.append('\\r')
|
||||
elif code < 0x20:
|
||||
out.append('\\u%04x' % code)
|
||||
else:
|
||||
out.append(ch)
|
||||
out.append('"')
|
||||
return ''.join(out)
|
||||
|
||||
|
||||
def _fmt_number(v):
|
||||
if isinstance(v, bool):
|
||||
return 'true' if v else 'false'
|
||||
if isinstance(v, int):
|
||||
return str(v)
|
||||
if isinstance(v, float):
|
||||
# Invariant culture: '.' decimal sep
|
||||
if v == int(v):
|
||||
# Preserve float-ness: PS [double] 5.0 → "5"
|
||||
# Match PS ToString invariant: 5.0 → "5"
|
||||
return str(int(v))
|
||||
return repr(v)
|
||||
return str(v)
|
||||
|
||||
|
||||
def try_inline_json(obj):
|
||||
if obj is None:
|
||||
return 'null'
|
||||
if isinstance(obj, bool):
|
||||
return 'true' if obj else 'false'
|
||||
if isinstance(obj, str):
|
||||
return convert_string_to_json_literal(obj)
|
||||
if isinstance(obj, (int, float)):
|
||||
return _fmt_number(obj)
|
||||
if isinstance(obj, dict):
|
||||
if len(obj) == 0:
|
||||
return '{}'
|
||||
parts = []
|
||||
for k, v in obj.items():
|
||||
vs = try_inline_json(v)
|
||||
if vs is None:
|
||||
return None
|
||||
parts.append(convert_string_to_json_literal(str(k)) + ': ' + vs)
|
||||
return '{ ' + ', '.join(parts) + ' }'
|
||||
if isinstance(obj, (list, tuple)):
|
||||
if len(obj) == 0:
|
||||
return '[]'
|
||||
parts = []
|
||||
for it in obj:
|
||||
vs = try_inline_json(it)
|
||||
if vs is None:
|
||||
return None
|
||||
parts.append(vs)
|
||||
return '[' + ', '.join(parts) + ']'
|
||||
return None
|
||||
|
||||
|
||||
def convert_to_compact_json(obj, depth=0, indent_unit=' ', line_limit=400):
|
||||
indent = indent_unit * depth
|
||||
child_indent = indent_unit * (depth + 1)
|
||||
|
||||
if obj is None:
|
||||
return 'null'
|
||||
if isinstance(obj, bool):
|
||||
return 'true' if obj else 'false'
|
||||
if isinstance(obj, str):
|
||||
return convert_string_to_json_literal(obj)
|
||||
if isinstance(obj, (int, float)):
|
||||
return _fmt_number(obj)
|
||||
|
||||
# Try inline для объектов и массивов с объектами — если помещается в lineLimit с учётом текущего indent.
|
||||
is_container = isinstance(obj, (dict, list, tuple))
|
||||
if is_container:
|
||||
inline_attempt = try_inline_json(obj)
|
||||
if inline_attempt is not None and (len(indent) + len(inline_attempt)) <= line_limit:
|
||||
return inline_attempt
|
||||
|
||||
if isinstance(obj, dict):
|
||||
if len(obj) == 0:
|
||||
return '{}'
|
||||
parts = []
|
||||
for k, v in obj.items():
|
||||
val = convert_to_compact_json(v, depth + 1, indent_unit, line_limit)
|
||||
parts.append(child_indent + convert_string_to_json_literal(str(k)) + ': ' + val)
|
||||
return "{\n" + ",\n".join(parts) + "\n" + indent + "}"
|
||||
if isinstance(obj, (list, tuple)):
|
||||
if len(obj) == 0:
|
||||
return '[]'
|
||||
parts = [child_indent + convert_to_compact_json(it, depth + 1, indent_unit, line_limit) for it in obj]
|
||||
return "[\n" + ",\n".join(parts) + "\n" + indent + "]"
|
||||
return convert_string_to_json_literal(str(obj))
|
||||
|
||||
|
||||
# --- Main ---
|
||||
|
||||
def main():
|
||||
@@ -707,13 +822,13 @@ def main():
|
||||
|
||||
# --- 16. Convert to JSON ---
|
||||
|
||||
json_str = json.dumps(result, ensure_ascii=False, indent=2)
|
||||
json_str = convert_to_compact_json(result)
|
||||
|
||||
# --- 17. Output ---
|
||||
|
||||
if output_path:
|
||||
abs_path = os.path.join(os.getcwd(), output_path) if not os.path.isabs(output_path) else output_path
|
||||
with open(abs_path, "w", encoding="utf-8") as fh:
|
||||
with open(abs_path, "w", encoding="utf-8", newline="") as fh:
|
||||
fh.write(json_str)
|
||||
print(f"[OK] Decompiled: {output_path}")
|
||||
else:
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "OutputPath принимается и абсолютным",
|
||||
"preRun": [
|
||||
{
|
||||
"script": "mxl-compile/scripts/mxl-compile",
|
||||
"input": { "columns": 2, "areas": [{ "name": "Test", "rows": [{ "cells": [{ "col": 1, "text": "A" }, { "col": 2, "text": "B" }] }] }] },
|
||||
"args": { "-JsonPath": "{inputFile}", "-OutputPath": "Template.xml" },
|
||||
"cwd": "{workDir}"
|
||||
}
|
||||
],
|
||||
"params": { "templatePath": "Template.xml" },
|
||||
"args_extra": ["-OutputPath", "{workDir}/back.json"],
|
||||
"expect": {
|
||||
"files": ["back.json"],
|
||||
"stdoutContains": "[OK] Decompiled:"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document xmlns="http://v8.1c.ru/8.2/data/spreadsheet" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<languageSettings>
|
||||
<currentLanguage>ru</currentLanguage>
|
||||
<defaultLanguage>ru</defaultLanguage>
|
||||
<languageInfo>
|
||||
<id>ru</id>
|
||||
<code>Русский</code>
|
||||
<description>Русский</description>
|
||||
</languageInfo>
|
||||
</languageSettings>
|
||||
<columns>
|
||||
<size>2</size>
|
||||
</columns>
|
||||
<rowsItem>
|
||||
<index>0</index>
|
||||
<row>
|
||||
<c>
|
||||
<i>0</i>
|
||||
<c>
|
||||
<f>2</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>A</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
<c>
|
||||
<i>1</i>
|
||||
<c>
|
||||
<f>2</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>B</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>1</defaultFormatIndex>
|
||||
<height>1</height>
|
||||
<vgRows>1</vgRows>
|
||||
<namedItem xsi:type="NamedItemCells">
|
||||
<name>Test</name>
|
||||
<area>
|
||||
<type>Rows</type>
|
||||
<beginRow>0</beginRow>
|
||||
<endRow>0</endRow>
|
||||
<beginColumn>-1</beginColumn>
|
||||
<endColumn>-1</endColumn>
|
||||
</area>
|
||||
</namedItem>
|
||||
<font faceName="Arial" height="10" bold="false" italic="false" underline="false" strikeout="false" kind="Absolute" scale="100"/>
|
||||
<format>
|
||||
<width>10</width>
|
||||
</format>
|
||||
<format>
|
||||
<font>0</font>
|
||||
<fillType>Text</fillType>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1 @@
|
||||
{ "columns": 2, "defaultWidth": 10, "fonts": { "default": { "face": "Arial", "size": 10 } }, "styles": {}, "areas": [{ "name": "Test", "rows": [{ "cells": [{ "col": 1, "style": "default", "text": "A" }, { "col": 2, "style": "default", "text": "B" }] }] }] }
|
||||
@@ -319,6 +319,43 @@ const FAMILIES = [
|
||||
],
|
||||
},
|
||||
|
||||
// ─── Компактный JSON декомпиляторов ─────────────────────────────────────
|
||||
// Штатные сериализаторы не годятся: ConvertTo-Json (PS5.1) выравнивает ключи по самому
|
||||
// длинному и эскейпит кириллицу в \uXXXX, json.dumps даёт иную раскладку inline/multiline.
|
||||
// Поэтому у декомпиляторов свой сериализатор — и он обязан совпадать в портах байт в байт,
|
||||
// иначе один и тот же макет даёт разный DSL на разных рантаймах.
|
||||
{
|
||||
name: 'decompile json: string literal',
|
||||
py: 'convert_string_to_json_literal', ps1: 'Convert-StringToJsonLiteral',
|
||||
variants: [
|
||||
{ id: 'base', authority: 'skd-decompile', consumers: ['form-decompile', 'mxl-decompile'] }],
|
||||
},
|
||||
{
|
||||
name: 'decompile json: try inline',
|
||||
py: 'try_inline_json', ps1: 'Try-InlineJson',
|
||||
variants: [
|
||||
{ id: 'base', authority: 'skd-decompile', consumers: ['mxl-decompile'] },
|
||||
{ id: 'no-pscustomobject', authority: 'form-decompile', consumers: [],
|
||||
why: 'form-decompile строит дерево на ordered-хэштейблах и ветку PSCustomObject не проходит' }],
|
||||
},
|
||||
{
|
||||
// Только в PY: в ps1 числа печатает [System.Convert]::ToString с InvariantCulture прямо
|
||||
// в теле сериализатора, отдельной функции там нет — ps1: null.
|
||||
name: 'decompile json: number', py: '_fmt_number', ps1: null,
|
||||
variants: [
|
||||
{ id: 'base', authority: 'skd-decompile', consumers: ['mxl-decompile'] }],
|
||||
},
|
||||
{
|
||||
name: 'decompile json: compact',
|
||||
py: 'convert_to_compact_json', ps1: 'ConvertTo-CompactJson',
|
||||
variants: [
|
||||
{ id: 'base', authority: 'skd-decompile', consumers: ['mxl-decompile'] },
|
||||
{ id: 'line-limit-120', authority: 'form-decompile', consumers: [],
|
||||
why: 'у форм строки DSL длиннее, порог inline снижен со 400 до 120' },
|
||||
{ id: 'legacy', authority: 'meta-decompile', consumers: [],
|
||||
why: 'ранний вариант со своим Quote-Json и без inline-попытки; сведение меняет вывод meta-decompile' }],
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
// ─── Семьи, разъехавшиеся целиком ───────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user