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): шрифт ссылкой на стиль или системный
Шрифт бывает не собственным описанием, а ссылкой: на элемент стиля конфигурации
(style:) или на системный шрифт (sys:). Своих атрибутов у такого шрифта нет, и мы
превращали его в пустую запись — faceName="" height="0". ps1 при сборке подставлял
туда Arial 10, то есть подменял данные молча.
В корпусе таких шрифтов 272 в 213 макетах из 10 924: StyleItem 209, WindowsFont 63.
Запись — та же, что у шрифта в описании формы: { "ref": "style:TextFont" }.
kind выводится из префикса, ключом быть не обязан.
Синтетический стенд показал деталь, которую по корпусу было не разглядеть: префикс
sys в корне документа не объявлен, поэтому платформа дописывает объявление xmlns
прямо на узел шрифта — тот же приём, что с цветами из web-палитры.
Порты после этого сошлись ПОЛНОСТЬЮ: на пилоте из 40 макетов совпадают и JSON
декомпиляторов, и собранный XML. Макет со шрифтами добавлен в побайтовую
регрессию, стенд 8 из 13.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
0a8671a166
commit
98bcf79b41
@@ -18,6 +18,18 @@
|
||||
Шрифт `"default"` используется, когда стиль не указывает шрифт явно. Если не определён,
|
||||
создаётся автоматически (Arial 10).
|
||||
|
||||
Вместо собственного описания шрифт может быть **ссылкой** — на элемент стиля конфигурации
|
||||
или на системный шрифт. Тогда у него единственное поле:
|
||||
|
||||
```json
|
||||
"fonts": {
|
||||
"основной": { "ref": "style:TextFont" },
|
||||
"системный": { "ref": "sys:DefaultGUIFont" }
|
||||
}
|
||||
```
|
||||
|
||||
Это та же запись, что у шрифта в описании формы.
|
||||
|
||||
## Стили (`styles.<name>`)
|
||||
|
||||
Ключ стиля — имя свойства так, как оно называется в выгрузке. Ниже частые; полный список
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# mxl-compile v1.39 — Compile 1C spreadsheet from JSON
|
||||
# mxl-compile v1.40 — Compile 1C spreadsheet from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -232,8 +232,21 @@ function Format-Num {
|
||||
return [System.Convert]::ToString($v, [System.Globalization.CultureInfo]::InvariantCulture)
|
||||
}
|
||||
|
||||
# Шрифт бывает не собственным, а ссылкой: на элемент стиля конфигурации (style:) или на
|
||||
# системный шрифт (sys:). Вид ссылки определяет kind, и он выводится из префикса.
|
||||
function Get-FontRefKind {
|
||||
param([string]$ref)
|
||||
if ($ref -like 'sys:*') { return 'WindowsFont' }
|
||||
return 'StyleItem'
|
||||
}
|
||||
|
||||
function Add-Font {
|
||||
param([string]$name, $fontDef)
|
||||
if ($fontDef.ref) {
|
||||
$script:fontMap[$name] = $script:fontEntries.Count
|
||||
$script:fontEntries += @{ Ref = "$($fontDef.ref)"; Kind = (Get-FontRefKind "$($fontDef.ref)") }
|
||||
return
|
||||
}
|
||||
$face = if ($fontDef.face) { $fontDef.face } else { "Arial" }
|
||||
$size = if ($fontDef.size) { ConvertTo-FontSize $fontDef.size } else { 10 }
|
||||
$bold = if ($fontDef.bold -eq $true) { "true" } else { "false" }
|
||||
@@ -1618,6 +1631,16 @@ foreach ($ln in $script:lineRegistry) {
|
||||
|
||||
# 7i. Font palette
|
||||
foreach ($fe in $fontEntries) {
|
||||
if ($fe.Ref) {
|
||||
# Префикс sys в корне документа не объявлен, поэтому платформа дописывает объявление
|
||||
# прямо на узел — тот же приём, что с цветами из web-палитры.
|
||||
if ($fe.Ref -like 'sys:*') {
|
||||
X "`t<font xmlns:sys=`"http://v8.1c.ru/8.1/data/ui/fonts/system`" ref=`"$(Esc-Xml $fe.Ref)`" kind=`"$($fe.Kind)`"/>"
|
||||
} else {
|
||||
X "`t<font ref=`"$(Esc-Xml $fe.Ref)`" kind=`"$($fe.Kind)`"/>"
|
||||
}
|
||||
continue
|
||||
}
|
||||
X "`t<font faceName=`"$($fe.Face)`" height=`"$(Format-Num $fe.Size)`" bold=`"$($fe.Bold)`" italic=`"$($fe.Italic)`" underline=`"$($fe.Underline)`" strikeout=`"$($fe.Strikeout)`" kind=`"Absolute`" scale=`"100`"/>"
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# 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
|
||||
import argparse
|
||||
import hashlib
|
||||
@@ -480,7 +480,17 @@ def main():
|
||||
font_map = {} # name -> 0-based index
|
||||
font_entries = [] # list of dicts
|
||||
|
||||
def font_ref_kind(ref):
|
||||
"""Шрифт бывает не собственным, а ссылкой: на элемент стиля конфигурации (style:)
|
||||
или на системный шрифт (sys:). Вид ссылки определяет kind, он выводится из префикса."""
|
||||
return 'WindowsFont' if ref.startswith('sys:') else 'StyleItem'
|
||||
|
||||
def add_font(name, font_def):
|
||||
if font_def and font_def.get('ref'):
|
||||
ref = str(font_def['ref'])
|
||||
font_map[name] = len(font_entries)
|
||||
font_entries.append({'Ref': ref, 'Kind': font_ref_kind(ref)})
|
||||
return
|
||||
face = font_def.get('face', 'Arial') if font_def else 'Arial'
|
||||
size = to_font_size(font_def.get('size', 10)) if font_def else 10
|
||||
bold = 'true' if font_def and font_def.get('bold') is True else 'false'
|
||||
@@ -1564,6 +1574,15 @@ def main():
|
||||
|
||||
# 7i. Font palette
|
||||
for fe in font_entries:
|
||||
if fe.get('Ref'):
|
||||
# Префикс sys в корне документа не объявлен, поэтому платформа дописывает
|
||||
# объявление прямо на узел — тот же приём, что с цветами из web-палитры.
|
||||
if fe['Ref'].startswith('sys:'):
|
||||
lines.append(f' <font xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system"'
|
||||
f' ref="{esc_xml(fe["Ref"])}" kind="{fe["Kind"]}"/>')
|
||||
else:
|
||||
lines.append(f' <font ref="{esc_xml(fe["Ref"])}" kind="{fe["Kind"]}"/>')
|
||||
continue
|
||||
lines.append(f'\t<font faceName="{fe["Face"]}" height="{fe["Size"]}" bold="{fe["Bold"]}" italic="{fe["Italic"]}" underline="{fe["Underline"]}" strikeout="{fe["Strikeout"]}" kind="Absolute" scale="100"/>')
|
||||
|
||||
# 7j. Format palette
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# mxl-decompile v1.19 — Decompile 1C spreadsheet to JSON
|
||||
# mxl-decompile v1.20 — Decompile 1C spreadsheet to JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -97,6 +97,9 @@ function ConvertTo-FontSize {
|
||||
$rawFonts = @()
|
||||
foreach ($fNode in $root.SelectNodes("d:font", $ns)) {
|
||||
$rawFonts += @{
|
||||
# Шрифт бывает ссылкой на элемент стиля (style:) или системный шрифт (sys:) —
|
||||
# тогда своих атрибутов у него нет, и без этого он превращался в пустую запись.
|
||||
Ref = $fNode.GetAttribute("ref")
|
||||
Face = $fNode.GetAttribute("faceName")
|
||||
Size = ConvertTo-FontSize $fNode.GetAttribute("height")
|
||||
Bold = $fNode.GetAttribute("bold") -eq "true"
|
||||
@@ -454,6 +457,7 @@ if ($rawFonts.Count -gt 0) {
|
||||
|
||||
function Get-FontKey {
|
||||
param($f)
|
||||
if ($f.Ref) { return "ref=$($f.Ref)" }
|
||||
return "$($f.Face)|$($f.Size)|$($f.Bold)|$($f.Italic)|$($f.Underline)|$($f.Strikeout)"
|
||||
}
|
||||
|
||||
@@ -473,7 +477,11 @@ for ($i = 1; $i -lt $rawFonts.Count; $i++) {
|
||||
|
||||
$name = $null
|
||||
|
||||
if ($f.Face -eq $df.Face -and $f.Size -eq $df.Size) {
|
||||
if ($f.Ref) {
|
||||
# Имя из ссылки: style:SmallTextFont → small-text-font-подобное читаемое имя не даёт
|
||||
# ничего сверх самой ссылки, поэтому берём часть после префикса.
|
||||
$name = ($f.Ref -replace '^[^:]+:', '').ToLowerInvariant()
|
||||
} elseif ($f.Face -eq $df.Face -and $f.Size -eq $df.Size) {
|
||||
if ($f.Bold -and -not $df.Bold -and -not $f.Italic -and -not $f.Underline -and -not $f.Strikeout) {
|
||||
$name = "bold"
|
||||
} elseif ($f.Italic -and -not $df.Italic -and -not $f.Bold) {
|
||||
@@ -1115,6 +1123,7 @@ if ($colWidthMap.Count -gt 0) {
|
||||
$fontsOut = [ordered]@{}
|
||||
foreach ($name in $fontDefs.Keys) {
|
||||
$f = $fontDefs[$name]
|
||||
if ($f.Ref) { $fontsOut[$name] = [ordered]@{ ref = $f.Ref }; continue }
|
||||
$fOut = [ordered]@{ face = $f.Face; size = $f.Size }
|
||||
if ($f.Bold) { $fOut["bold"] = $true }
|
||||
if ($f.Italic) { $fOut["italic"] = $true }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# mxl-decompile v1.19 — Decompile 1C spreadsheet to JSON
|
||||
# mxl-decompile v1.20 — Decompile 1C spreadsheet to JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -267,6 +267,9 @@ def main():
|
||||
raw_fonts = []
|
||||
for f_node in findall(root, "d:font"):
|
||||
raw_fonts.append({
|
||||
# Шрифт бывает ссылкой на элемент стиля (style:) или системный шрифт (sys:) —
|
||||
# тогда своих атрибутов у него нет, и без этого он превращался в пустую запись.
|
||||
"Ref": f_node.get("ref", ""),
|
||||
"Face": f_node.get("faceName", ""),
|
||||
"Size": to_font_size(f_node.get("height", "0")),
|
||||
"Bold": f_node.get("bold") == "true",
|
||||
@@ -610,6 +613,10 @@ def main():
|
||||
font_defs["default"] = raw_fonts[0]
|
||||
|
||||
def get_font_key(f):
|
||||
# Ссылку различаем по ней самой: своих атрибутов у такого шрифта нет, и без этого
|
||||
# две РАЗНЫЕ ссылки схлопывались в одну как «пустые».
|
||||
if f.get("Ref"):
|
||||
return "ref=" + f["Ref"]
|
||||
return f"{f['Face']}|{f['Size']}|{f['Bold']}|{f['Italic']}|{f['Underline']}|{f['Strikeout']}"
|
||||
|
||||
font_key_map = {}
|
||||
@@ -628,7 +635,10 @@ def main():
|
||||
|
||||
name = None
|
||||
|
||||
if f["Face"] == df["Face"] and f["Size"] == df["Size"]:
|
||||
if f.get("Ref"):
|
||||
# Имя из ссылки: читаемее самой ссылки ничего не придумать.
|
||||
name = f["Ref"].split(":", 1)[1].lower()
|
||||
elif f["Face"] == df["Face"] and f["Size"] == df["Size"]:
|
||||
if f["Bold"] and not df["Bold"] and not f["Italic"] and not f["Underline"] and not f["Strikeout"]:
|
||||
name = "bold"
|
||||
elif f["Italic"] and not df["Italic"] and not f["Bold"]:
|
||||
@@ -1117,6 +1127,9 @@ def main():
|
||||
|
||||
fonts_out = OrderedDict()
|
||||
for name, f in font_defs.items():
|
||||
if f.get("Ref"):
|
||||
fonts_out[name] = OrderedDict([("ref", f["Ref"])])
|
||||
continue
|
||||
f_out = OrderedDict()
|
||||
f_out["face"] = f["Face"]
|
||||
f_out["size"] = f["Size"]
|
||||
|
||||
@@ -18,6 +18,18 @@
|
||||
Шрифт `"default"` используется, когда стиль не указывает шрифт явно. Если не определён,
|
||||
создаётся автоматически (Arial 10).
|
||||
|
||||
Вместо собственного описания шрифт может быть **ссылкой** — на элемент стиля конфигурации
|
||||
или на системный шрифт. Тогда у него единственное поле:
|
||||
|
||||
```json
|
||||
"fonts": {
|
||||
"основной": { "ref": "style:TextFont" },
|
||||
"системный": { "ref": "sys:DefaultGUIFont" }
|
||||
}
|
||||
```
|
||||
|
||||
Это та же запись, что у шрифта в описании формы.
|
||||
|
||||
## Стили (`styles.<name>`)
|
||||
|
||||
Ключ стиля — имя свойства так, как оно называется в выгрузке. Ниже частые; полный список
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
<?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>
|
||||
<languageInfo>
|
||||
<id>en</id>
|
||||
<code>Английский</code>
|
||||
<description>Английский</description>
|
||||
</languageInfo>
|
||||
</languageSettings>
|
||||
<columns>
|
||||
<size>1</size>
|
||||
</columns>
|
||||
<rowsItem>
|
||||
<index>0</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>0</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Умолчание</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>1</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>1</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Шрифт стиля</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>2</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>2</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>системный шрифт</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>3</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>3</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Другой шрифт</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>4</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>4</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Полужирный</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<rowsItem>
|
||||
<index>5</index>
|
||||
<row>
|
||||
<c>
|
||||
<c>
|
||||
<f>5</f>
|
||||
<tl>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>размер</v8:content>
|
||||
</v8:item>
|
||||
</tl>
|
||||
</c>
|
||||
</c>
|
||||
</row>
|
||||
</rowsItem>
|
||||
<templateMode>true</templateMode>
|
||||
<defaultFormatIndex>6</defaultFormatIndex>
|
||||
<height>6</height>
|
||||
<vgRows>6</vgRows>
|
||||
<font ref="style:SmallTextFont" kind="StyleItem"/>
|
||||
<font xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" ref="sys:ANSIVariableFont" kind="WindowsFont"/>
|
||||
<font faceName="Times New Roman" height="8" bold="false" italic="false" underline="false" strikeout="false" kind="Absolute" scale="100"/>
|
||||
<font faceName="Arial" height="8" bold="true" italic="false" underline="false" strikeout="false" kind="Absolute" scale="100"/>
|
||||
<font faceName="Arial" height="12" bold="false" italic="false" underline="false" strikeout="false" kind="Absolute" scale="100"/>
|
||||
<format>
|
||||
<font>0</font>
|
||||
</format>
|
||||
<format>
|
||||
<font>1</font>
|
||||
</format>
|
||||
<format>
|
||||
<font>2</font>
|
||||
</format>
|
||||
<format>
|
||||
<font>3</font>
|
||||
</format>
|
||||
<format>
|
||||
<font>4</font>
|
||||
</format>
|
||||
<format>
|
||||
<width>72</width>
|
||||
</format>
|
||||
</document>
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "Раундтрип макета ПЛАТФОРМЫ байт в байт: Шрифты",
|
||||
"setup": "fixture:platform-roundtrip",
|
||||
"inputFrom": "back.json",
|
||||
"preRun": [
|
||||
{
|
||||
"script": "mxl-decompile/scripts/mxl-decompile",
|
||||
"args": {
|
||||
"-TemplatePath": "Шрифты.xml",
|
||||
"-OutputPath": "back.json"
|
||||
},
|
||||
"cwd": "{workDir}"
|
||||
}
|
||||
],
|
||||
"params": {
|
||||
"outputPath": "out.xml"
|
||||
},
|
||||
"noSnapshot": "эталон — файл платформы, сверяется expect.filesEqual",
|
||||
"expect": {
|
||||
"filesEqual": {
|
||||
"actual": "out.xml",
|
||||
"expected": "Шрифты.xml"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user