mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-13 22:35:16 +03:00
feat(meta-compile,meta-decompile): ML-синоним + ToolTip стандартных реквизитов (v1.24/v0.9)
Раундтрип-находка: у стандартных реквизитов синоним мультиязычен (корпус: 340 multi + 206 ru),
ToolTip непустой у 722 — компилятор писал синоним ru-only и <xr:ToolTip/> пусто, декомпилятор брал
Get-MLru (ru). Расширение существующего механизма standardAttributes.
- meta-compile (дуал-порт): Emit-StandardAttribute — синоним и ToolTip через Emit-MLText (строка|{ru,en});
DSL standardAttributes.X.tooltip + synonym без стрингификации. Заодно Emit-MLItems → Esc-XmlText
(кавычки в тексте элемента raw, не только у predefined).
- meta-decompile: синоним/tooltip станд. реквизита через Get-MLValue; Get-MLValue → $null при пустом
ru-содержимом (пустой ML-item ≡ отсутствие значения, не tooltip:"").
- spec §7.1.1 (synonym/tooltip — ML); тест-кейс catalog-standard-attributes расширен.
Валидация: PS==PY; ToolFip станд.реквизита 5903→404 (остаток — косметика пустой-item≡self-close);
−9049 (79620→70571); регресс 37/37; 1С-cert зелёный.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -341,14 +341,14 @@ function Emit-MLItems {
|
||||
param([string]$indent, $val)
|
||||
if ($val -is [System.Collections.IDictionary]) {
|
||||
foreach ($k in $val.Keys) {
|
||||
X "$indent<v8:item>"; X "$indent`t<v8:lang>$k</v8:lang>"; X "$indent`t<v8:content>$(Esc-Xml "$($val[$k])")</v8:content>"; X "$indent</v8:item>"
|
||||
X "$indent<v8:item>"; X "$indent`t<v8:lang>$k</v8:lang>"; X "$indent`t<v8:content>$(Esc-XmlText "$($val[$k])")</v8:content>"; X "$indent</v8:item>"
|
||||
}
|
||||
} elseif ($val -is [System.Management.Automation.PSCustomObject]) {
|
||||
foreach ($p in $val.PSObject.Properties) {
|
||||
X "$indent<v8:item>"; X "$indent`t<v8:lang>$($p.Name)</v8:lang>"; X "$indent`t<v8:content>$(Esc-Xml "$($p.Value)")</v8:content>"; X "$indent</v8:item>"
|
||||
X "$indent<v8:item>"; X "$indent`t<v8:lang>$($p.Name)</v8:lang>"; X "$indent`t<v8:content>$(Esc-XmlText "$($p.Value)")</v8:content>"; X "$indent</v8:item>"
|
||||
}
|
||||
} else {
|
||||
X "$indent<v8:item>"; X "$indent`t<v8:lang>ru</v8:lang>"; X "$indent`t<v8:content>$(Esc-Xml "$val")</v8:content>"; X "$indent</v8:item>"
|
||||
X "$indent<v8:item>"; X "$indent`t<v8:lang>ru</v8:lang>"; X "$indent`t<v8:content>$(Esc-XmlText "$val")</v8:content>"; X "$indent</v8:item>"
|
||||
}
|
||||
}
|
||||
function Emit-MLText {
|
||||
@@ -885,6 +885,7 @@ function Emit-StandardAttribute {
|
||||
$dh = OvOr 'DataHistory' 'Use'
|
||||
$fts = OvOr 'FullTextSearch' 'Use'
|
||||
$syn = OvOr 'Synonym' ''
|
||||
$tt = OvOr 'ToolTip' ''
|
||||
X "$indent<xr:StandardAttribute name=`"$attrName`">"
|
||||
X "$indent`t<xr:LinkByType/>"
|
||||
X "$indent`t<xr:FillChecking>$fc</xr:FillChecking>"
|
||||
@@ -892,7 +893,7 @@ function Emit-StandardAttribute {
|
||||
X "$indent`t<xr:FillFromFillingValue>$ffv</xr:FillFromFillingValue>"
|
||||
X "$indent`t<xr:CreateOnInput>Auto</xr:CreateOnInput>"
|
||||
X "$indent`t<xr:MaxValue xsi:nil=`"true`"/>"
|
||||
X "$indent`t<xr:ToolTip/>"
|
||||
Emit-MLText "$indent`t" "xr:ToolTip" $tt
|
||||
X "$indent`t<xr:ExtendedEdit>false</xr:ExtendedEdit>"
|
||||
X "$indent`t<xr:Format/>"
|
||||
X "$indent`t<xr:ChoiceForm/>"
|
||||
@@ -903,16 +904,7 @@ function Emit-StandardAttribute {
|
||||
X "$indent`t<xr:DataHistory>$dh</xr:DataHistory>"
|
||||
X "$indent`t<xr:MarkNegatives>false</xr:MarkNegatives>"
|
||||
X "$indent`t<xr:MinValue xsi:nil=`"true`"/>"
|
||||
if ($syn) {
|
||||
X "$indent`t<xr:Synonym>"
|
||||
X "$indent`t`t<v8:item>"
|
||||
X "$indent`t`t`t<v8:lang>ru</v8:lang>"
|
||||
X "$indent`t`t`t<v8:content>$(Esc-Xml $syn)</v8:content>"
|
||||
X "$indent`t`t</v8:item>"
|
||||
X "$indent`t</xr:Synonym>"
|
||||
} else {
|
||||
X "$indent`t<xr:Synonym/>"
|
||||
}
|
||||
Emit-MLText "$indent`t" "xr:Synonym" $syn
|
||||
X "$indent`t<xr:Comment/>"
|
||||
X "$indent`t<xr:FullTextSearch>$fts</xr:FullTextSearch>"
|
||||
X "$indent`t<xr:ChoiceParameterLinks/>"
|
||||
@@ -944,7 +936,8 @@ function Emit-StandardAttributes {
|
||||
if ($conditional -and $sa) {
|
||||
$d = $sa.$a
|
||||
if ($d) {
|
||||
if ($null -ne $d.synonym) { $ov['Synonym'] = "$($d.synonym)" }
|
||||
if ($null -ne $d.synonym) { $ov['Synonym'] = $d.synonym } # строка ИЛИ {ru,en}
|
||||
if ($null -ne $d.tooltip) { $ov['ToolTip'] = $d.tooltip } # строка ИЛИ {ru,en}
|
||||
if ($d.fillChecking) { $ov['FillChecking'] = "$($d.fillChecking)" }
|
||||
if ($null -ne $d.fillFromFillingValue) { $ov['FillFromFillingValue'] = if ($d.fillFromFillingValue) { 'true' } else { 'false' } }
|
||||
if ($d.fullTextSearch) { $ov['FullTextSearch'] = "$($d.fullTextSearch)" }
|
||||
|
||||
@@ -207,12 +207,12 @@ def emit_ml_items(indent, val):
|
||||
for k, v in val.items():
|
||||
X(f'{indent}<v8:item>')
|
||||
X(f'{indent}\t<v8:lang>{k}</v8:lang>')
|
||||
X(f'{indent}\t<v8:content>{esc_xml(str(v))}</v8:content>')
|
||||
X(f'{indent}\t<v8:content>{esc_xml_text(str(v))}</v8:content>')
|
||||
X(f'{indent}</v8:item>')
|
||||
else:
|
||||
X(f'{indent}<v8:item>')
|
||||
X(f'{indent}\t<v8:lang>ru</v8:lang>')
|
||||
X(f'{indent}\t<v8:content>{esc_xml(str(val))}</v8:content>')
|
||||
X(f'{indent}\t<v8:content>{esc_xml_text(str(val))}</v8:content>')
|
||||
X(f'{indent}</v8:item>')
|
||||
|
||||
def emit_mltext(indent, tag, text):
|
||||
@@ -881,6 +881,7 @@ def emit_standard_attribute(indent, attr_name, ov=None):
|
||||
dh = ov.get('DataHistory', 'Use')
|
||||
fts = ov.get('FullTextSearch', 'Use')
|
||||
syn = ov.get('Synonym', '')
|
||||
tt = ov.get('ToolTip', '')
|
||||
X(f'{indent}<xr:StandardAttribute name="{attr_name}">')
|
||||
X(f'{indent}\t<xr:LinkByType/>')
|
||||
X(f'{indent}\t<xr:FillChecking>{fc}</xr:FillChecking>')
|
||||
@@ -888,7 +889,7 @@ def emit_standard_attribute(indent, attr_name, ov=None):
|
||||
X(f'{indent}\t<xr:FillFromFillingValue>{ffv}</xr:FillFromFillingValue>')
|
||||
X(f'{indent}\t<xr:CreateOnInput>Auto</xr:CreateOnInput>')
|
||||
X(f'{indent}\t<xr:MaxValue xsi:nil="true"/>')
|
||||
X(f'{indent}\t<xr:ToolTip/>')
|
||||
emit_mltext(f'{indent}\t', 'xr:ToolTip', tt)
|
||||
X(f'{indent}\t<xr:ExtendedEdit>false</xr:ExtendedEdit>')
|
||||
X(f'{indent}\t<xr:Format/>')
|
||||
X(f'{indent}\t<xr:ChoiceForm/>')
|
||||
@@ -899,15 +900,7 @@ def emit_standard_attribute(indent, attr_name, ov=None):
|
||||
X(f'{indent}\t<xr:DataHistory>{dh}</xr:DataHistory>')
|
||||
X(f'{indent}\t<xr:MarkNegatives>false</xr:MarkNegatives>')
|
||||
X(f'{indent}\t<xr:MinValue xsi:nil="true"/>')
|
||||
if syn:
|
||||
X(f'{indent}\t<xr:Synonym>')
|
||||
X(f'{indent}\t\t<v8:item>')
|
||||
X(f'{indent}\t\t\t<v8:lang>ru</v8:lang>')
|
||||
X(f'{indent}\t\t\t<v8:content>{esc_xml(syn)}</v8:content>')
|
||||
X(f'{indent}\t\t</v8:item>')
|
||||
X(f'{indent}\t</xr:Synonym>')
|
||||
else:
|
||||
X(f'{indent}\t<xr:Synonym/>')
|
||||
emit_mltext(f'{indent}\t', 'xr:Synonym', syn)
|
||||
X(f'{indent}\t<xr:Comment/>')
|
||||
X(f'{indent}\t<xr:FullTextSearch>{fts}</xr:FullTextSearch>')
|
||||
X(f'{indent}\t<xr:ChoiceParameterLinks/>')
|
||||
@@ -936,7 +929,9 @@ def emit_standard_attributes(indent, object_type):
|
||||
d = sa.get(a)
|
||||
if d:
|
||||
if d.get('synonym') is not None:
|
||||
ov['Synonym'] = str(d['synonym'])
|
||||
ov['Synonym'] = d['synonym'] # строка ИЛИ {ru,en}
|
||||
if d.get('tooltip') is not None:
|
||||
ov['ToolTip'] = d['tooltip'] # строка ИЛИ {ru,en}
|
||||
if d.get('fillChecking'):
|
||||
ov['FillChecking'] = str(d['fillChecking'])
|
||||
if d.get('fillFromFillingValue') is not None:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# meta-decompile v0.8 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# meta-decompile v0.9 — XML объекта метаданных 1С → JSON-черновик формата meta-compile
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
#
|
||||
# Пилот: только Catalog. Инверс meta-compile (omit-on-default: ключ эмитим только
|
||||
@@ -115,7 +115,8 @@ function Get-MLValue {
|
||||
if ($items.Count -eq 1) {
|
||||
$lang = $items[0].SelectSingleNode('v8:lang', $nsm).InnerText
|
||||
$content = $items[0].SelectSingleNode('v8:content', $nsm).InnerText
|
||||
if ($lang -eq 'ru') { return $content }
|
||||
# Единственный ru-item: пустое содержимое ≡ отсутствие значения → $null (иначе tooltip:"" ≠ self-close).
|
||||
if ($lang -eq 'ru') { if ($content -eq '') { return $null } else { return $content } }
|
||||
}
|
||||
$o = [ordered]@{}
|
||||
foreach ($it in $items) {
|
||||
@@ -296,9 +297,11 @@ if ($saNode) {
|
||||
$ffvN = $sa.SelectSingleNode('xr:FillFromFillingValue', $nsm); $ffv = ($ffvN -and $ffvN.InnerText -eq 'true')
|
||||
$profFfv = ($prof['fillFromFillingValue'] -eq $true)
|
||||
if ($ffv -ne $profFfv) { $ov['fillFromFillingValue'] = $ffv }
|
||||
# Synonym (профиль пуст)
|
||||
$syn = Get-MLru ($sa.SelectSingleNode('xr:Synonym', $nsm))
|
||||
if ($syn) { $ov['synonym'] = $syn }
|
||||
# Synonym / ToolTip (профиль пуст) — строка ru | {ru,en}
|
||||
$syn = Get-MLValue ($sa.SelectSingleNode('xr:Synonym', $nsm))
|
||||
if ($null -ne $syn) { $ov['synonym'] = $syn }
|
||||
$tt = Get-MLValue ($sa.SelectSingleNode('xr:ToolTip', $nsm))
|
||||
if ($null -ne $tt) { $ov['tooltip'] = $tt }
|
||||
# FullTextSearch / DataHistory (профиль = Use)
|
||||
$ftsN = $sa.SelectSingleNode('xr:FullTextSearch', $nsm); if ($ftsN -and $ftsN.InnerText -ne 'Use') { $ov['fullTextSearch'] = $ftsN.InnerText }
|
||||
$dhN = $sa.SelectSingleNode('xr:DataHistory', $nsm); if ($dhN -and $dhN.InnerText -ne 'Use') { $ov['dataHistory'] = $dhN.InnerText }
|
||||
|
||||
@@ -285,7 +285,7 @@ JSON DSL для описания объектов метаданных конф
|
||||
|
||||
Формат: `standardAttributes` — объект `{ ИмяРеквизита: { переопределения } }`. Имена реквизитов — как в XML: `PredefinedDataName`, `Predefined`, `Ref`, `DeletionMark`, `IsFolder`, `Owner`, `Parent`, `Description`, `Code`.
|
||||
|
||||
Переопределяемые поля реквизита: `synonym` (строка → `<xr:Synonym>` ru), `fillChecking` (`DontCheck`|`ShowError`|`ShowWarning`), `fillFromFillingValue` (bool), `fullTextSearch` (`Use`|`DontUse`), `dataHistory` (`Use`|`DontUse`).
|
||||
Переопределяемые поля реквизита: `synonym` (ML — строка/`{ru,en}`), `tooltip` (ML), `fillChecking` (`DontCheck`|`ShowError`|`ShowWarning`), `fillFromFillingValue` (bool), `fullTextSearch` (`Use`|`DontUse`), `dataHistory` (`Use`|`DontUse`).
|
||||
|
||||
**Профиль материализованного блока** (значения, которые платформа заполняет автоматически — задавать их в DSL не нужно):
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
"type": "Catalog",
|
||||
"name": "Контрагенты",
|
||||
"standardAttributes": {
|
||||
"Description": { "synonym": "Наименование контрагента" },
|
||||
"Code": { "fillChecking": "ShowError" }
|
||||
"Description": { "synonym": { "ru": "Наименование контрагента", "en": "Counterparty name" }, "tooltip": "Полное наименование" },
|
||||
"Code": { "fillChecking": "ShowError", "tooltip": { "ru": "Код", "en": "Code" } }
|
||||
}
|
||||
},
|
||||
"validatePath": "Catalogs/Контрагенты",
|
||||
|
||||
+20
-2
@@ -238,7 +238,12 @@
|
||||
<xr:FillFromFillingValue>false</xr:FillFromFillingValue>
|
||||
<xr:CreateOnInput>Auto</xr:CreateOnInput>
|
||||
<xr:MaxValue xsi:nil="true"/>
|
||||
<xr:ToolTip/>
|
||||
<xr:ToolTip>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Полное наименование</v8:content>
|
||||
</v8:item>
|
||||
</xr:ToolTip>
|
||||
<xr:ExtendedEdit>false</xr:ExtendedEdit>
|
||||
<xr:Format/>
|
||||
<xr:ChoiceForm/>
|
||||
@@ -254,6 +259,10 @@
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Наименование контрагента</v8:content>
|
||||
</v8:item>
|
||||
<v8:item>
|
||||
<v8:lang>en</v8:lang>
|
||||
<v8:content>Counterparty name</v8:content>
|
||||
</v8:item>
|
||||
</xr:Synonym>
|
||||
<xr:Comment/>
|
||||
<xr:FullTextSearch>Use</xr:FullTextSearch>
|
||||
@@ -269,7 +278,16 @@
|
||||
<xr:FillFromFillingValue>false</xr:FillFromFillingValue>
|
||||
<xr:CreateOnInput>Auto</xr:CreateOnInput>
|
||||
<xr:MaxValue xsi:nil="true"/>
|
||||
<xr:ToolTip/>
|
||||
<xr:ToolTip>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Код</v8:content>
|
||||
</v8:item>
|
||||
<v8:item>
|
||||
<v8:lang>en</v8:lang>
|
||||
<v8:content>Code</v8:content>
|
||||
</v8:item>
|
||||
</xr:ToolTip>
|
||||
<xr:ExtendedEdit>false</xr:ExtendedEdit>
|
||||
<xr:Format/>
|
||||
<xr:ChoiceForm/>
|
||||
|
||||
Reference in New Issue
Block a user