From fde6d346d7209ec1940881c5898473b0ad2738f4 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Thu, 5 Mar 2026 12:00:09 +0300 Subject: [PATCH] feat(meta-compile): support composite types and fix d5p1 namespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add composite type support via + separator in Emit-TypeContent (PS/PY) - Fix reference types: cfg: → d5p1: with local xmlns declaration in Emit-TypeContent, valueTypes loop, EventSubscription source - Fix lxml stripping xmlns:d5p1 in meta-edit.py save_xml (post-process) - Fix IndentationError in meta-compile.py and meta-validate.py - Document composite type syntax in SKILL.md Co-Authored-By: Claude Opus 4.6 --- .claude/skills/meta-compile/SKILL.md | 2 ++ .../meta-compile/scripts/meta-compile.ps1 | 17 +++++++++++++---- .../skills/meta-compile/scripts/meta-compile.py | 16 +++++++++++----- .claude/skills/meta-edit/scripts/meta-edit.py | 7 +++++++ .../meta-validate/scripts/meta-validate.py | 2 +- 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/.claude/skills/meta-compile/SKILL.md b/.claude/skills/meta-compile/SKILL.md index 5bf94833..9af0db6b 100644 --- a/.claude/skills/meta-compile/SKILL.md +++ b/.claude/skills/meta-compile/SKILL.md @@ -69,6 +69,8 @@ Constant (Константа), DefinedType (ОпределяемыйТип), Com Русские синонимы типов: `Строка`, `Число`, `Булево`, `Дата`, `СправочникСсылка.Xxx`, `ДокументСсылка.Xxx`, `ПланСчетовСсылка.Xxx`. +Составной тип (несколько допустимых типов через `+`): `"Значение: Строка + Число(15,2) + Дата + CatalogRef.Контрагенты"`. + Флаги: `req`, `index`, `indexAdditional`, `nonneg`, `master`, `mainFilter`, `denyIncomplete`, `useInTotals`. ## Примеры diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1 index 09ebcf5e..85dbee1d 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.ps1 +++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1 @@ -198,6 +198,15 @@ function Emit-TypeContent { param([string]$indent, [string]$typeStr) if (-not $typeStr) { return } + # Composite type: "Type1 + Type2 + Type3" + if ($typeStr.Contains(' + ')) { + $parts = $typeStr -split '\s*\+\s*' + foreach ($part in $parts) { + Emit-TypeContent $indent $part.Trim() + } + return + } + $typeStr = Resolve-TypeStr $typeStr # Boolean @@ -254,9 +263,9 @@ function Emit-TypeContent { return } - # Reference types: CatalogRef.XXX, DocumentRef.XXX, etc. + # Reference types — use local xmlns declaration for 1C compatibility if ($typeStr -match '^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|TaskRef)\.(.+)$') { - X "$indentcfg:$typeStr" + X "$indentd5p1:$typeStr" return } @@ -1237,7 +1246,7 @@ function Emit-DefinedTypeProperties { foreach ($vt in $valueTypes) { $resolved = Resolve-TypeStr "$vt" if ($resolved -match '^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|TaskRef)\.') { - X "$i`tcfg:$resolved" + X "$i`td5p1:$resolved" } elseif ($resolved -eq "Boolean") { X "$i`txs:boolean" } elseif ($resolved -match '^String') { @@ -1342,7 +1351,7 @@ function Emit-EventSubscriptionProperties { X "$i" foreach ($src in $sources) { $resolved = Resolve-TypeStr "$src" - X "$i`tcfg:$resolved" + X "$i`td5p1:$resolved" } X "$i" } else { diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py index 46f8b3a1..b2c6e548 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.py +++ b/.claude/skills/meta-compile/scripts/meta-compile.py @@ -11,7 +11,7 @@ import uuid import xml.etree.ElementTree as ET sys.stdout.reconfigure(encoding="utf-8") - sys.stderr.reconfigure(encoding="utf-8") +sys.stderr.reconfigure(encoding="utf-8") # --------------------------------------------------------------------------- # Inline utilities @@ -207,6 +207,12 @@ def resolve_type_str(type_str): def emit_type_content(indent, type_str): if not type_str: return + # Composite type: "Type1 + Type2 + Type3" + if ' + ' in type_str: + parts = [p.strip() for p in type_str.split('+')] + for part in parts: + emit_type_content(indent, part) + return type_str = resolve_type_str(type_str) # Boolean if type_str == 'Boolean': @@ -254,10 +260,10 @@ def emit_type_content(indent, type_str): dt_name = m.group(1) X(f'{indent}cfg:DefinedType.{dt_name}') return - # Reference types + # Reference types — use local xmlns declaration for 1C compatibility m = re.match(r'^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|TaskRef)\.(.+)$', type_str) if m: - X(f'{indent}cfg:{type_str}') + X(f'{indent}d5p1:{type_str}') return # Fallback X(f'{indent}{type_str}') @@ -1066,7 +1072,7 @@ def emit_defined_type_properties(indent): for vt in value_types: resolved = resolve_type_str(str(vt)) if re.match(r'^(CatalogRef|DocumentRef|EnumRef|ChartOfAccountsRef|ChartOfCharacteristicTypesRef|ChartOfCalculationTypesRef|ExchangePlanRef|BusinessProcessRef|TaskRef)\.', resolved): - X(f'{i}\tcfg:{resolved}') + X(f'{i}\td5p1:{resolved}') elif resolved == 'Boolean': X(f'{i}\txs:boolean') elif re.match(r'^String', resolved): @@ -1155,7 +1161,7 @@ def emit_event_subscription_properties(indent): X(f'{i}') for src in sources: resolved = resolve_type_str(str(src)) - X(f'{i}\tcfg:{resolved}') + X(f'{i}\td5p1:{resolved}') X(f'{i}') else: X(f'{i}') diff --git a/.claude/skills/meta-edit/scripts/meta-edit.py b/.claude/skills/meta-edit/scripts/meta-edit.py index 1aa495fa..e593f6c7 100644 --- a/.claude/skills/meta-edit/scripts/meta-edit.py +++ b/.claude/skills/meta-edit/scripts/meta-edit.py @@ -1971,6 +1971,13 @@ def save_xml(tree, path): xml_bytes = etree.tostring(tree, xml_declaration=True, encoding="UTF-8") # Fix encoding quotes: encoding='UTF-8' -> encoding="UTF-8" xml_bytes = xml_bytes.replace(b"encoding='UTF-8'", b'encoding="UTF-8"') + # Fix d5p1 namespace declarations stripped by lxml (it treats them as unused + # because d5p1: appears only in text content, not in element/attribute names) + xml_bytes = re.sub( + b'(d5p1:)', + b'\\1 xmlns:d5p1="http://v8.1c.ru/8.1/data/enterprise/current-config"\\2', + xml_bytes + ) with open(path, "wb") as f: f.write(b"\xef\xbb\xbf") f.write(xml_bytes) diff --git a/.claude/skills/meta-validate/scripts/meta-validate.py b/.claude/skills/meta-validate/scripts/meta-validate.py index 1b078c25..14004de4 100644 --- a/.claude/skills/meta-validate/scripts/meta-validate.py +++ b/.claude/skills/meta-validate/scripts/meta-validate.py @@ -8,7 +8,7 @@ import sys from lxml import etree sys.stdout.reconfigure(encoding="utf-8") - sys.stderr.reconfigure(encoding="utf-8") +sys.stderr.reconfigure(encoding="utf-8") # ── arg parsing ──────────────────────────────────────────────