diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1
index d52c7c2b..60d4eb95 100644
--- a/.claude/skills/meta-compile/scripts/meta-compile.ps1
+++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1
@@ -341,14 +341,14 @@ function Emit-MLItems {
param([string]$indent, $val)
if ($val -is [System.Collections.IDictionary]) {
foreach ($k in $val.Keys) {
- X "$indent"; X "$indent`t$k"; X "$indent`t$(Esc-Xml "$($val[$k])")"; X "$indent"
+ X "$indent"; X "$indent`t$k"; X "$indent`t$(Esc-XmlText "$($val[$k])")"; X "$indent"
}
} elseif ($val -is [System.Management.Automation.PSCustomObject]) {
foreach ($p in $val.PSObject.Properties) {
- X "$indent"; X "$indent`t$($p.Name)"; X "$indent`t$(Esc-Xml "$($p.Value)")"; X "$indent"
+ X "$indent"; X "$indent`t$($p.Name)"; X "$indent`t$(Esc-XmlText "$($p.Value)")"; X "$indent"
}
} else {
- X "$indent"; X "$indent`tru"; X "$indent`t$(Esc-Xml "$val")"; X "$indent"
+ X "$indent"; X "$indent`tru"; X "$indent`t$(Esc-XmlText "$val")"; X "$indent"
}
}
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"
X "$indent`t"
X "$indent`t$fc"
@@ -892,7 +893,7 @@ function Emit-StandardAttribute {
X "$indent`t$ffv"
X "$indent`tAuto"
X "$indent`t"
- X "$indent`t"
+ Emit-MLText "$indent`t" "xr:ToolTip" $tt
X "$indent`tfalse"
X "$indent`t"
X "$indent`t"
@@ -903,16 +904,7 @@ function Emit-StandardAttribute {
X "$indent`t$dh"
X "$indent`tfalse"
X "$indent`t"
- if ($syn) {
- X "$indent`t"
- X "$indent`t`t"
- X "$indent`t`t`tru"
- X "$indent`t`t`t$(Esc-Xml $syn)"
- X "$indent`t`t"
- X "$indent`t"
- } else {
- X "$indent`t"
- }
+ Emit-MLText "$indent`t" "xr:Synonym" $syn
X "$indent`t"
X "$indent`t$fts"
X "$indent`t"
@@ -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)" }
diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py
index 651ae312..31e14afa 100644
--- a/.claude/skills/meta-compile/scripts/meta-compile.py
+++ b/.claude/skills/meta-compile/scripts/meta-compile.py
@@ -207,12 +207,12 @@ def emit_ml_items(indent, val):
for k, v in val.items():
X(f'{indent}')
X(f'{indent}\t{k}')
- X(f'{indent}\t{esc_xml(str(v))}')
+ X(f'{indent}\t{esc_xml_text(str(v))}')
X(f'{indent}')
else:
X(f'{indent}')
X(f'{indent}\tru')
- X(f'{indent}\t{esc_xml(str(val))}')
+ X(f'{indent}\t{esc_xml_text(str(val))}')
X(f'{indent}')
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}')
X(f'{indent}\t')
X(f'{indent}\t{fc}')
@@ -888,7 +889,7 @@ def emit_standard_attribute(indent, attr_name, ov=None):
X(f'{indent}\t{ffv}')
X(f'{indent}\tAuto')
X(f'{indent}\t')
- X(f'{indent}\t')
+ emit_mltext(f'{indent}\t', 'xr:ToolTip', tt)
X(f'{indent}\tfalse')
X(f'{indent}\t')
X(f'{indent}\t')
@@ -899,15 +900,7 @@ def emit_standard_attribute(indent, attr_name, ov=None):
X(f'{indent}\t{dh}')
X(f'{indent}\tfalse')
X(f'{indent}\t')
- if syn:
- X(f'{indent}\t')
- X(f'{indent}\t\t')
- X(f'{indent}\t\t\tru')
- X(f'{indent}\t\t\t{esc_xml(syn)}')
- X(f'{indent}\t\t')
- X(f'{indent}\t')
- else:
- X(f'{indent}\t')
+ emit_mltext(f'{indent}\t', 'xr:Synonym', syn)
X(f'{indent}\t')
X(f'{indent}\t{fts}')
X(f'{indent}\t')
@@ -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:
diff --git a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1 b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1
index af14d17d..eb739842 100644
--- a/.claude/skills/meta-decompile/scripts/meta-decompile.ps1
+++ b/.claude/skills/meta-decompile/scripts/meta-decompile.ps1
@@ -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 }
diff --git a/docs/meta-dsl-spec.md b/docs/meta-dsl-spec.md
index bad57c67..ce48b43a 100644
--- a/docs/meta-dsl-spec.md
+++ b/docs/meta-dsl-spec.md
@@ -285,7 +285,7 @@ JSON DSL для описания объектов метаданных конф
Формат: `standardAttributes` — объект `{ ИмяРеквизита: { переопределения } }`. Имена реквизитов — как в XML: `PredefinedDataName`, `Predefined`, `Ref`, `DeletionMark`, `IsFolder`, `Owner`, `Parent`, `Description`, `Code`.
-Переопределяемые поля реквизита: `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 не нужно):
diff --git a/tests/skills/cases/meta-compile/catalog-standard-attributes.json b/tests/skills/cases/meta-compile/catalog-standard-attributes.json
index f3e10e21..00f0eb6b 100644
--- a/tests/skills/cases/meta-compile/catalog-standard-attributes.json
+++ b/tests/skills/cases/meta-compile/catalog-standard-attributes.json
@@ -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/Контрагенты",
diff --git a/tests/skills/cases/meta-compile/snapshots/catalog-standard-attributes/Catalogs/Контрагенты.xml b/tests/skills/cases/meta-compile/snapshots/catalog-standard-attributes/Catalogs/Контрагенты.xml
index 8dc5bde3..f20a7f35 100644
--- a/tests/skills/cases/meta-compile/snapshots/catalog-standard-attributes/Catalogs/Контрагенты.xml
+++ b/tests/skills/cases/meta-compile/snapshots/catalog-standard-attributes/Catalogs/Контрагенты.xml
@@ -238,7 +238,12 @@
false
Auto
-
+
+
+ ru
+ Полное наименование
+
+
false
@@ -254,6 +259,10 @@
ru
Наименование контрагента
+
+ en
+ Counterparty name
+
Use
@@ -269,7 +278,16 @@
false
Auto
-
+
+
+ ru
+ Код
+
+
+ en
+ Code
+
+
false