mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-23 21:21:04 +03:00
feat(form-decompile,form-compile): заголовок реквизита — суппресс-маркер "" + omit авто-вывода (кластер Attribute>Title)
Компилятор для не-main реквизита БЕЗ ключа title додумывал <Title> из имени, хотя платформа реквизит без синонима хранит без <Title>. На корпусе (295609 реквизитов): 22% без <Title> — всем додумывался заголовок (ADDED Attribute>Title = 170 в выборке). Компилятор (ps1+py): эмиссия Title реквизита приведена к логике Emit-Title — нет ключа → авто-вывод (кроме main); title "" → подавить (раньше "" был falsy и уходил в авто-вывод — это и был баг); непустой → как есть. Декомпилятор (ps1): нет <Title> → title:"" (суппресс-маркер); ru-only заголовок, равный авто-выводу из имени → опускаем ключ (компилятор воспроизведёт, 35% = 103908 реквизитов корпуса); иначе → явный. Скопировано точное зеркало Title-FromName для сверки. Регресс: attributes-types.json — реквизит с title:"" (подавление) рядом с авто-выводом + снэпшот. spec §реквизиты обновлён. TOTAL diff lines выборки 2.17: 2255 → 1750 (−505); cascade ADDED 292 → 33. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
2367eaa353
commit
cfce486004
@@ -1,4 +1,4 @@
|
|||||||
# form-compile v1.61 — Compile 1C managed form from JSON or object metadata
|
# form-compile v1.62 — Compile 1C managed form from JSON or object metadata
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[string]$JsonPath,
|
[string]$JsonPath,
|
||||||
@@ -3664,9 +3664,13 @@ function Emit-Attributes {
|
|||||||
X "$indent`t<Attribute name=`"$attrName`" id=`"$attrId`">"
|
X "$indent`t<Attribute name=`"$attrName`" id=`"$attrId`">"
|
||||||
$inner = "$indent`t`t"
|
$inner = "$indent`t`t"
|
||||||
|
|
||||||
$attrTitle = if ($attr.title) { $attr.title } elseif ($attr.main -ne $true) { Title-FromName -name $attrName } else { '' }
|
# Title атрибута (зеркало Emit-Title): нет ключа → авто-вывод из имени (кроме main);
|
||||||
if ($attrTitle) {
|
# title "" → подавить; непустой → эмитить как есть.
|
||||||
Emit-MLText -tag "Title" -text $attrTitle -indent $inner
|
$hasTitleKey = $null -ne $attr.PSObject.Properties['title']
|
||||||
|
if ($hasTitleKey) {
|
||||||
|
if ($attr.title) { Emit-MLText -tag "Title" -text $attr.title -indent $inner }
|
||||||
|
} elseif ($attr.main -ne $true) {
|
||||||
|
Emit-MLText -tag "Title" -text (Title-FromName -name $attrName) -indent $inner
|
||||||
}
|
}
|
||||||
|
|
||||||
# Type
|
# Type
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# form-compile v1.61 — Compile 1C managed form from JSON or object metadata
|
# form-compile v1.62 — Compile 1C managed form from JSON or object metadata
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
import argparse
|
import argparse
|
||||||
import copy
|
import copy
|
||||||
@@ -3342,11 +3342,13 @@ def emit_attributes(lines, attrs, indent):
|
|||||||
lines.append(f'{indent}\t<Attribute name="{attr_name}" id="{attr_id}">')
|
lines.append(f'{indent}\t<Attribute name="{attr_name}" id="{attr_id}">')
|
||||||
inner = f'{indent}\t\t'
|
inner = f'{indent}\t\t'
|
||||||
|
|
||||||
attr_title = attr.get('title')
|
# Title атрибута (зеркало emit_title): нет ключа → авто-вывод из имени (кроме main);
|
||||||
if not attr_title and attr.get('main') is not True:
|
# title "" → подавить; непустой → эмитить как есть.
|
||||||
attr_title = title_from_name(attr_name)
|
if 'title' in attr:
|
||||||
if attr_title:
|
if attr.get('title'):
|
||||||
emit_mltext(lines, inner, 'Title', attr_title)
|
emit_mltext(lines, inner, 'Title', attr['title'])
|
||||||
|
elif attr.get('main') is not True:
|
||||||
|
emit_mltext(lines, inner, 'Title', title_from_name(attr_name))
|
||||||
|
|
||||||
# Type
|
# Type
|
||||||
if attr.get('type'):
|
if attr.get('type'):
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# form-decompile v0.42 — Decompile 1C managed Form.xml to JSON DSL (draft)
|
# form-decompile v0.43 — Decompile 1C managed Form.xml to JSON DSL (draft)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
|
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
|
||||||
param(
|
param(
|
||||||
@@ -230,6 +230,25 @@ function Get-LangText {
|
|||||||
return $map
|
return $map
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Авто-вывод заголовка из имени — ТОЧНОЕ зеркало Title-FromName из form-compile.
|
||||||
|
# Нужен, чтобы опускать ru-only заголовки, которые компилятор воспроизведёт сам.
|
||||||
|
function Title-FromName {
|
||||||
|
param([string]$name)
|
||||||
|
if (-not $name) { return '' }
|
||||||
|
$s = [regex]::Replace($name, '([А-ЯA-Z])([А-ЯA-Z][а-яa-z])', '$1 $2')
|
||||||
|
$s = [regex]::Replace($s, '([а-яa-z0-9])([А-ЯA-Z])', '$1 $2')
|
||||||
|
$parts = $s -split ' '
|
||||||
|
if ($parts.Count -eq 0) { return $s }
|
||||||
|
$out = New-Object System.Collections.ArrayList
|
||||||
|
[void]$out.Add($parts[0])
|
||||||
|
for ($i = 1; $i -lt $parts.Count; $i++) {
|
||||||
|
$p = $parts[$i]
|
||||||
|
if ($p.Length -gt 1 -and $p -ceq $p.ToUpper()) { [void]$out.Add($p) }
|
||||||
|
else { [void]$out.Add($p.ToLower()) }
|
||||||
|
}
|
||||||
|
return ($out -join ' ')
|
||||||
|
}
|
||||||
|
|
||||||
# Детектор «настоящей» inline-разметки форматированного текста (идентичен form-compile!).
|
# Детектор «настоящей» inline-разметки форматированного текста (идентичен form-compile!).
|
||||||
$script:fmtMarkupRe = '</>|<\s*(?:link|b|i|u|s|color|colorStyle|bgColor|bgColorStyle|font|fontSize|fontStyle|img)(?:\s|>)'
|
$script:fmtMarkupRe = '</>|<\s*(?:link|b|i|u|s|color|colorStyle|bgColor|bgColorStyle|font|fontSize|fontStyle|img)(?:\s|>)'
|
||||||
function Test-HasRealMarkup {
|
function Test-HasRealMarkup {
|
||||||
@@ -1343,7 +1362,19 @@ if ($attrsNode) {
|
|||||||
if ((Get-Child $a 'MainAttribute') -eq 'true') { $ao['main'] = $true }
|
if ((Get-Child $a 'MainAttribute') -eq 'true') { $ao['main'] = $true }
|
||||||
$vw = Decompile-XrFlag $a 'View'; if ($null -ne $vw) { $ao['view'] = $vw }
|
$vw = Decompile-XrFlag $a 'View'; if ($null -ne $vw) { $ao['view'] = $vw }
|
||||||
$ed = Decompile-XrFlag $a 'Edit'; if ($null -ne $ed) { $ao['edit'] = $ed }
|
$ed = Decompile-XrFlag $a 'Edit'; if ($null -ne $ed) { $ao['edit'] = $ed }
|
||||||
$tNode = $a.SelectSingleNode("lf:Title", $ns); if ($tNode) { $t = Get-LangText $tNode; if ($null -ne $t) { $ao['title'] = $t } }
|
# Title атрибута. Компилятор для не-main атрибута без ключа title додумывает заголовок
|
||||||
|
# из имени. Поэтому: нет <Title> → суппресс-маркер ''; ru-only == авто-вывод → опускаем
|
||||||
|
# ключ (компилятор воспроизведёт); иначе → явный заголовок.
|
||||||
|
$isMain = $ao.Contains('main')
|
||||||
|
$tNode = $a.SelectSingleNode("lf:Title", $ns)
|
||||||
|
if ($tNode) {
|
||||||
|
$t = Get-LangText $tNode
|
||||||
|
if ($null -ne $t) {
|
||||||
|
if ($isMain -or -not ($t -is [string]) -or $t -ne (Title-FromName $ao['name'])) { $ao['title'] = $t }
|
||||||
|
}
|
||||||
|
} elseif (-not $isMain) {
|
||||||
|
$ao['title'] = ''
|
||||||
|
}
|
||||||
if ((Get-Child $a 'SavedData') -eq 'true') { $ao['savedData'] = $true }
|
if ((Get-Child $a 'SavedData') -eq 'true') { $ao['savedData'] = $true }
|
||||||
$fc = Get-Child $a 'FillChecking'; if ($fc) { $ao['fillChecking'] = $fc }
|
$fc = Get-Child $a 'FillChecking'; if ($fc) { $ao['fillChecking'] = $fc }
|
||||||
$afo = Decompile-FunctionalOptions $a; if ($afo) { $ao['functionalOptions'] = $afo }
|
$afo = Decompile-FunctionalOptions $a; if ($afo) { $ao['functionalOptions'] = $afo }
|
||||||
|
|||||||
@@ -623,7 +623,7 @@ Pages поддерживает `pagesRepresentation`: `None`, `TabsOnTop`, `Tabs
|
|||||||
| `name` | string | Имя реквизита (обязательно) |
|
| `name` | string | Имя реквизита (обязательно) |
|
||||||
| `type` | string | Тип (shorthand) |
|
| `type` | string | Тип (shorthand) |
|
||||||
| `main` | bool | Основной реквизит формы |
|
| `main` | bool | Основной реквизит формы |
|
||||||
| `title` | string | Заголовок |
|
| `title` | string/object | Заголовок. **Нет ключа** → авто-вывод из имени (как у элементов; кроме `main`). **`""`** → подавить (`<Title>` не эмитится — так платформа и хранит реквизит без синонима). Строка → ru; объект `{ru,en}` → мультиязычный. Декомпилятор опускает ключ, когда ru-заголовок совпадает с авто-выводом из имени |
|
||||||
| `view` | bool/object | Просмотр по ролям (`<View>`). См. §4.1c |
|
| `view` | bool/object | Просмотр по ролям (`<View>`). См. §4.1c |
|
||||||
| `edit` | bool/object | Редактирование по ролям (`<Edit>`). См. §4.1c |
|
| `edit` | bool/object | Редактирование по ролям (`<Edit>`). См. §4.1c |
|
||||||
| `functionalOptions` | array | Функциональные опции (`<FunctionalOptions><Item>FunctionalOption.X</Item>…`). Массив имён; forgiving: `"X"`/`"FunctionalOption.X"`. Также у колонок (`columns[*]`) и команд (§7) |
|
| `functionalOptions` | array | Функциональные опции (`<FunctionalOptions><Item>FunctionalOption.X</Item>…`). Массив имён; forgiving: `"X"`/`"FunctionalOption.X"`. Также у колонок (`columns[*]`) и команд (§7) |
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
{ "name": "Объект", "type": "DataProcessorObject.Типы", "main": true },
|
{ "name": "Объект", "type": "DataProcessorObject.Типы", "main": true },
|
||||||
{ "name": "Строка", "type": "string(200)", "view": false },
|
{ "name": "Строка", "type": "string(200)", "view": false },
|
||||||
{ "name": "Число", "type": "decimal(10,0,nonneg)", "edit": false },
|
{ "name": "Число", "type": "decimal(10,0,nonneg)", "edit": false },
|
||||||
{ "name": "Дата", "type": "dateTime" },
|
{ "name": "Дата", "type": "dateTime", "title": "" },
|
||||||
{ "name": "Булево", "type": "boolean" },
|
{ "name": "Булево", "type": "boolean" },
|
||||||
{ "name": "СписокЗначений", "type": "ValueList" },
|
{ "name": "СписокЗначений", "type": "ValueList" },
|
||||||
{ "name": "Идентификатор", "type": "v8:UUID" }
|
{ "name": "Идентификатор", "type": "v8:UUID" }
|
||||||
|
|||||||
-6
@@ -78,12 +78,6 @@
|
|||||||
</Edit>
|
</Edit>
|
||||||
</Attribute>
|
</Attribute>
|
||||||
<Attribute name="Дата" id="16">
|
<Attribute name="Дата" id="16">
|
||||||
<Title>
|
|
||||||
<v8:item>
|
|
||||||
<v8:lang>ru</v8:lang>
|
|
||||||
<v8:content>Дата</v8:content>
|
|
||||||
</v8:item>
|
|
||||||
</Title>
|
|
||||||
<Type>
|
<Type>
|
||||||
<v8:Type>xs:dateTime</v8:Type>
|
<v8:Type>xs:dateTime</v8:Type>
|
||||||
<v8:DateQualifiers>
|
<v8:DateQualifiers>
|
||||||
|
|||||||
Reference in New Issue
Block a user