mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-13 15:03:20 +03:00
feat(mxl-compile,mxl-decompile): многоязычный текст элементом строки-массива
В позиционной записи строки элемент — это значение содержимого ячейки, а значение
текста по общей конвенции бывает строкой либо объектом «язык → текст». Значит
объект {ru, en} там законен так же, как строка, и новой формы это не заводит.
Раньше ячейка с многоязычным текстом не считалась «простой», поэтому строка
двуязычного макета оставалась объектной:
{ "cells": [{ "text": { "ru": "Пусто", "en": "Empty" } }, { … }] }
[{ "ru": "Пусто", "en": "Empty" }, { … }]
Объект-элемент читается как ячейка, если несёт хоть один её ключ, и как текст
в противном случае: идентификаторы языков с ключами ячейки не пересекаются
(в корпусе это ru, en, ru1, Русский).
Попутно исправлен признак «список позиционный»: он искал элемент-строку, поэтому
строка из одних многоязычных текстов позиционной не признавалась и ключ cells
у неё оставался.
Правка не должна менять скомпилированный XML — и не меняет: пилот из 40 макетов
собрался побайтово так же, JSON при этом изменился у 13. Стенд 7 из 10.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f926acd4f4
commit
b5fef09844
@@ -144,12 +144,16 @@
|
||||
| Элемент | Значение |
|
||||
|---------|----------|
|
||||
| `"текст"` | Статический текст (`text`) |
|
||||
| `{ "ru": "…", "en": "…" }` | Тот же текст на нескольких языках |
|
||||
| `"{Имя}"` | Параметр (`param`) |
|
||||
| `">"` | Продолжение ячейки слева — увеличивает её `span` |
|
||||
| `"|"` | Продолжение ячейки сверху — увеличивает её `rowspan` |
|
||||
| `null` | Пустая колонка: позиция занята, ячейка не создаётся |
|
||||
| `{ ... }` | Обычная ячейка **без** `col`; нужна для `style`, `detail`, `template` |
|
||||
|
||||
Объект-элемент читается как ячейка, если несёт хоть один её ключ (`span`, `rowspan`, `style`,
|
||||
`param`, `detail`, `text`, `template`), и как многоязычный текст в противном случае.
|
||||
|
||||
```json
|
||||
"rows": [
|
||||
["Вид", "Остаток", ">", "Итог"],
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# mxl-compile v1.36 — Compile 1C spreadsheet from JSON
|
||||
# mxl-compile v1.37 — Compile 1C spreadsheet from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -845,6 +845,17 @@ function Set-CellProp {
|
||||
$cell | Add-Member -NotePropertyName $name -NotePropertyValue $value -Force
|
||||
}
|
||||
|
||||
# Ячейка это или многоязычный текст: у ячейки есть хоть один ключ её схемы, у ML-значения
|
||||
# ключи — идентификаторы языков. Пересечений нет: в корпусе это ru, en, ru1, Русский.
|
||||
function Test-CellObject {
|
||||
param($el)
|
||||
$cellKeys = @('col', 'span', 'rowspan', 'style', 'param', 'detail', 'text', 'template')
|
||||
foreach ($p in $el.PSObject.Properties) {
|
||||
if ($cellKeys -contains $p.Name) { return $true }
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
function Expand-ShorthandRow {
|
||||
param($row, [string]$areaName, [int]$rowIdx, $openByCol, [int]$maxCols)
|
||||
|
||||
@@ -897,6 +908,12 @@ function Expand-ShorthandRow {
|
||||
$m = [regex]::Match($el, '^\{(.+)\}$')
|
||||
if ($m.Success) { Set-CellProp $cell 'param' $m.Groups[1].Value }
|
||||
else { Set-CellProp $cell 'text' $el }
|
||||
} elseif (-not (Test-CellObject $el)) {
|
||||
# Объект без единого ключа ячейки — это многоязычный ТЕКСТ: в позиционной записи
|
||||
# элемент и есть значение текста, а значение текста по общей конвенции бывает
|
||||
# строкой либо объектом «язык → текст».
|
||||
$cell = [PSCustomObject]@{ col = $idx; span = 1 }
|
||||
Set-CellProp $cell 'text' $el
|
||||
} else {
|
||||
# Объектный элемент — обычная ячейка mxl, позиция берётся из индекса.
|
||||
if ($el.PSObject.Properties['col']) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# mxl-compile v1.36 — Compile 1C spreadsheet from JSON
|
||||
# mxl-compile v1.37 — Compile 1C spreadsheet from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import hashlib
|
||||
@@ -884,6 +884,13 @@ def main():
|
||||
# "{Имя}" — параметр. Разворачиваем в обычную строку с явными col/span/rowspan,
|
||||
# поэтому весь код ниже про шорткат не знает.
|
||||
|
||||
def is_cell_object(el):
|
||||
"""Ячейка это или многоязычный текст: у ячейки есть хоть один ключ её схемы,
|
||||
у ML-значения ключи — идентификаторы языков. Пересечений нет: в корпусе это
|
||||
ru, en, ru1, Русский."""
|
||||
cell_keys = ('col', 'span', 'rowspan', 'style', 'param', 'detail', 'text', 'template')
|
||||
return any(k in el for k in cell_keys)
|
||||
|
||||
def expand_shorthand_row(row, area_name, row_idx, open_by_col, max_cols):
|
||||
cells = []
|
||||
placed = {} # 1-based col -> ячейка, занимающая колонку в ЭТОЙ строке
|
||||
@@ -933,6 +940,11 @@ def main():
|
||||
cell['param'] = m.group(1)
|
||||
else:
|
||||
cell['text'] = el
|
||||
elif not is_cell_object(el):
|
||||
# Объект без единого ключа ячейки — это многоязычный ТЕКСТ: в позиционной
|
||||
# записи элемент и есть значение текста, а значение текста по общей конвенции
|
||||
# бывает строкой либо объектом «язык → текст».
|
||||
cell = CIDict({'col': idx, 'span': 1, 'text': el})
|
||||
else:
|
||||
# Объектный элемент — обычная ячейка mxl, позиция берётся из индекса.
|
||||
if 'col' in el:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# mxl-decompile v1.15 — Decompile 1C spreadsheet to JSON
|
||||
# mxl-decompile v1.16 — Decompile 1C spreadsheet to JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -631,20 +631,17 @@ function Get-ColumnStyles {
|
||||
return $out
|
||||
}
|
||||
|
||||
# Список признаётся позиционным по тому же правилу, что и в компиляторе: есть элемент-строка
|
||||
# или пропуск. Список из одних объектов таковым не считаем — он читается как обычный.
|
||||
# Список позиционный, если позиция в нём НЕ записана: ни у одного элемента нет col.
|
||||
# Прежняя проверка искала элемент-строку, поэтому строка из одних многоязычных текстов
|
||||
# позиционной не признавалась и оставалась объектной.
|
||||
function Test-PositionalList {
|
||||
param($cells)
|
||||
foreach ($el in $cells) {
|
||||
if ($null -eq $el -or $el -is [string]) { return $true }
|
||||
if ($el -is [System.Collections.IDictionary] -and $el.Contains('col')) { return $false }
|
||||
}
|
||||
return $false
|
||||
return $true
|
||||
}
|
||||
|
||||
# Позиционная запись списка ячеек: позиция берётся из порядка, `col` не пишется.
|
||||
# Применяем, когда первая ячейка стоит в колонке 1 — иначе список начнётся с череды null
|
||||
# и станет длиннее объектного. Ячейка, у которой кроме текста или параметра ничего нет,
|
||||
# пишется строкой; span раскрывается маркерами ">"; всё прочее — объектным элементом без col.
|
||||
# Custom JSON serializer — компактный, 2-пробельный indent, массивы примитивов inline.
|
||||
# В отличие от ConvertTo-Json (PS5.1):
|
||||
# - не выравнивает ключи объекта по самому длинному
|
||||
@@ -771,6 +768,10 @@ function ConvertTo-CompactJson {
|
||||
return (Convert-StringToJsonLiteral "$obj")
|
||||
}
|
||||
|
||||
# Позиционная запись списка ячеек: позиция берётся из порядка, `col` не пишется.
|
||||
# Ячейка, у которой кроме текста или параметра ничего нет, пишется значением; span
|
||||
# раскрывается маркерами ">"; пропуск колонки — null; всё прочее — объектным элементом
|
||||
# без col. Выбираем ту запись, которая КОРОЧЕ.
|
||||
function ConvertTo-PositionalCells {
|
||||
param($cells)
|
||||
# Пропуск колонки — null. Выбираем ту запись, которая КОРОЧЕ: раньше позиционная форма
|
||||
@@ -787,10 +788,12 @@ function ConvertTo-PositionalCells {
|
||||
|
||||
$span = if ($c.Contains("span")) { [int]$c["span"] } else { 1 }
|
||||
$keys = @($c.Keys | Where-Object { $_ -notin @("col", "span") })
|
||||
$plainText = ($keys.Count -eq 1 -and $keys[0] -eq "text" -and $c["text"] -is [string])
|
||||
# Текст — единственное содержимое: пишем значением. Оно бывает строкой либо
|
||||
# объектом «язык → текст», и в позиционной записи элемент И ЕСТЬ это значение.
|
||||
$plainText = ($keys.Count -eq 1 -and $keys[0] -eq "text")
|
||||
$plainParam = ($keys.Count -eq 1 -and $keys[0] -eq "param")
|
||||
|
||||
if ($plainText) { $out += $c["text"] }
|
||||
if ($plainText) { $out += , $c["text"] }
|
||||
elseif ($plainParam) { $out += "{$($c["param"])}" }
|
||||
else {
|
||||
$obj = [ordered]@{}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# mxl-decompile v1.15 — Decompile 1C spreadsheet to JSON
|
||||
# mxl-decompile v1.16 — Decompile 1C spreadsheet to JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -791,7 +791,7 @@ def main():
|
||||
|
||||
def to_positional_cells(cells):
|
||||
"""Позиционная запись списка ячеек: позиция берётся из порядка, `col` не пишется.
|
||||
Ячейка, у которой кроме текста или параметра ничего нет, пишется строкой; span
|
||||
Ячейка, у которой кроме текста или параметра ничего нет, пишется значением; span
|
||||
раскрывается маркерами ">"; прочее — объектным элементом без col. Пропуск колонки —
|
||||
null. Выбираем ту запись, которая КОРОЧЕ: раньше позиционная форма отбрасывалась,
|
||||
как только первая ячейка стояла не в первой колонке, хотя один-два null впереди
|
||||
@@ -809,7 +809,9 @@ def main():
|
||||
expected += 1
|
||||
span = int(c.get("span", 1) or 1)
|
||||
keys = [k for k in c if k not in ("col", "span")]
|
||||
plain_text = len(keys) == 1 and keys[0] == "text" and isinstance(c["text"], str)
|
||||
# Текст — единственное содержимое: пишем значением. Оно бывает строкой либо
|
||||
# объектом «язык → текст», и в позиционной записи элемент И ЕСТЬ это значение.
|
||||
plain_text = len(keys) == 1 and keys[0] == "text"
|
||||
plain_param = len(keys) == 1 and keys[0] == "param"
|
||||
if plain_text:
|
||||
out.append(c["text"])
|
||||
@@ -1019,8 +1021,11 @@ def main():
|
||||
dsl_row["cells"] = to_positional_cells(dsl_cells)
|
||||
# Самая короткая из применимых форм: если у строки нет своих свойств, а список ячеек
|
||||
# позиционный — строка пишется просто массивом, без ключа cells.
|
||||
# Список позиционный, если позиция в нём НЕ записана: ни у одного элемента нет col.
|
||||
# Прежняя проверка искала элемент-строку, поэтому строка из одних многоязычных
|
||||
# текстов позиционной не признавалась и оставалась объектной.
|
||||
if (len(dsl_row) == 1 and "cells" in dsl_row
|
||||
and any(el is None or isinstance(el, str) for el in dsl_row["cells"])):
|
||||
and not any(isinstance(el, dict) and "col" in el for el in dsl_row["cells"])):
|
||||
area_rows.append(dsl_row["cells"])
|
||||
else:
|
||||
area_rows.append(dsl_row)
|
||||
|
||||
@@ -144,12 +144,16 @@
|
||||
| Элемент | Значение |
|
||||
|---------|----------|
|
||||
| `"текст"` | Статический текст (`text`) |
|
||||
| `{ "ru": "…", "en": "…" }` | Тот же текст на нескольких языках |
|
||||
| `"{Имя}"` | Параметр (`param`) |
|
||||
| `">"` | Продолжение ячейки слева — увеличивает её `span` |
|
||||
| `"|"` | Продолжение ячейки сверху — увеличивает её `rowspan` |
|
||||
| `null` | Пустая колонка: позиция занята, ячейка не создаётся |
|
||||
| `{ ... }` | Обычная ячейка **без** `col`; нужна для `style`, `detail`, `template` |
|
||||
|
||||
Объект-элемент читается как ячейка, если несёт хоть один её ключ (`span`, `rowspan`, `style`,
|
||||
`param`, `detail`, `text`, `template`), и как многоязычный текст в противном случае.
|
||||
|
||||
```json
|
||||
"rows": [
|
||||
["Вид", "Остаток", ">", "Итог"],
|
||||
|
||||
Reference in New Issue
Block a user