From d155086444a5164a2f0b34f4cb89588770a0ab83 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Mon, 6 Apr 2026 15:41:53 +0300 Subject: [PATCH] feat(skills): auto-detect XML format version from Configuration.xml When working with existing configs dumped from newer platforms (8.3.27+), XML files use version="2.20" instead of "2.17". Skills now detect the version from the nearest Configuration.xml walking up the directory tree, falling back to "2.17" if not found. This prevents format version mismatch errors during LoadConfigFromFiles. Updated skills (11): meta-compile, form-compile, form-add, template-add, cfe-borrow, epf-add-form, help-add, role-compile, subsystem-compile, interface-edit. Also fixed form-validate to accept version 2.20. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../skills/cfe-borrow/scripts/cfe-borrow.ps1 | 27 ++++++++++++++--- .../skills/cfe-borrow/scripts/cfe-borrow.py | 26 ++++++++++++++--- .../skills/epf-add-form/scripts/add-form.ps1 | 25 ++++++++++++++-- .../skills/epf-add-form/scripts/add-form.py | 25 ++++++++++++++-- .claude/skills/form-add/scripts/form-add.ps1 | 29 +++++++++++++++---- .claude/skills/form-add/scripts/form-add.py | 29 +++++++++++++++---- .../form-compile/scripts/form-compile.ps1 | 26 +++++++++++++++-- .../form-compile/scripts/form-compile.py | 24 +++++++++++++-- .../form-validate/scripts/form-validate.ps1 | 6 ++-- .../form-validate/scripts/form-validate.py | 6 ++-- .claude/skills/help-add/scripts/add-help.ps1 | 23 +++++++++++++-- .claude/skills/help-add/scripts/add-help.py | 23 +++++++++++++-- .../interface-edit/scripts/interface-edit.ps1 | 23 +++++++++++++-- .../interface-edit/scripts/interface-edit.py | 25 ++++++++++++++-- .../meta-compile/scripts/meta-compile.ps1 | 27 ++++++++++++++--- .../meta-compile/scripts/meta-compile.py | 29 ++++++++++++++++--- .../role-compile/scripts/role-compile.ps1 | 26 +++++++++++++++-- .../role-compile/scripts/role-compile.py | 25 ++++++++++++++-- .../scripts/subsystem-compile.ps1 | 23 +++++++++++++-- .../scripts/subsystem-compile.py | 22 ++++++++++++-- .../template-add/scripts/add-template.ps1 | 23 +++++++++++++-- .../template-add/scripts/add-template.py | 23 +++++++++++++-- 22 files changed, 450 insertions(+), 65 deletions(-) diff --git a/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 b/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 index c186c3f9..099ddac2 100644 --- a/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 +++ b/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 @@ -1,4 +1,4 @@ -# cfe-borrow v1.2 — Borrow objects from configuration into extension (CFE) +# cfe-borrow v1.3 — Borrow objects from configuration into extension (CFE) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][string]$ExtensionPath, @@ -316,6 +316,25 @@ function Expand-SelfClosingElement($container, $parentIndent) { } } +# --- 7b. Detect format version --- + +function Detect-FormatVersion([string]$dir) { + $d = $dir + while ($d) { + $cfgPath = Join-Path $d "Configuration.xml" + if (Test-Path $cfgPath) { + $head = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8).Substring(0, [Math]::Min(2000, (Get-Item $cfgPath).Length)) + if ($head -match ']+version="(\d+\.\d+)"') { return $Matches[1] } + } + $parent = Split-Path $d -Parent + if ($parent -eq $d) { break } + $d = $parent + } + return "2.17" +} + +$script:formatVersion = Detect-FormatVersion $extDir + # --- 8. Namespaces declaration for object XML --- $script:xmlnsDecl = 'xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' @@ -466,7 +485,7 @@ function Borrow-Form { $newFormUuid = [guid]::NewGuid().ToString() $formMetaSb = New-Object System.Text.StringBuilder $formMetaSb.AppendLine("") | Out-Null - $formMetaSb.AppendLine("") | Out-Null + $formMetaSb.AppendLine("") | Out-Null $formMetaSb.AppendLine("`t
") | Out-Null $formMetaSb.AppendLine("`t`t") | Out-Null $formMetaSb.AppendLine("`t`t") | Out-Null @@ -498,7 +517,7 @@ function Borrow-Form { $srcFormEl = $srcFormDoc.DocumentElement $formVersion = $srcFormEl.GetAttribute("version") - if (-not $formVersion) { $formVersion = "2.17" } + if (-not $formVersion) { $formVersion = $script:formatVersion } # Find direct children: form properties, AutoCommandBar, ChildItems $srcAutoCmd = $null @@ -1529,7 +1548,7 @@ function Build-BorrowedObjectXml { $sb = New-Object System.Text.StringBuilder $sb.AppendLine("") | Out-Null - $sb.AppendLine("") | Out-Null + $sb.AppendLine("") | Out-Null $sb.AppendLine("`t<${typeName} uuid=`"${newUuid}`">") | Out-Null # InternalInfo diff --git a/.claude/skills/cfe-borrow/scripts/cfe-borrow.py b/.claude/skills/cfe-borrow/scripts/cfe-borrow.py index 0140da1c..7ba8ade9 100644 --- a/.claude/skills/cfe-borrow/scripts/cfe-borrow.py +++ b/.claude/skills/cfe-borrow/scripts/cfe-borrow.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# cfe-borrow v1.2 — Borrow objects from configuration into extension (CFE) +# cfe-borrow v1.3 — Borrow objects from configuration into extension (CFE) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -254,6 +254,22 @@ XMLNS_DECL = ( ) +def detect_format_version(d): + while d: + cfg_path = os.path.join(d, "Configuration.xml") + if os.path.isfile(cfg_path): + with open(cfg_path, "r", encoding="utf-8-sig") as f: + head = f.read(2000) + m = re.search(r']+version="(\d+\.\d+)"', head) + if m: + return m.group(1) + parent = os.path.dirname(d) + if parent == d: + break + d = parent + return "2.17" + + def get_child_indent(container): if container.text and "\n" in container.text: after_nl = container.text.rsplit("\n", 1)[-1] @@ -365,6 +381,8 @@ def main(): cfg_resolved = os.path.abspath(cfg_path) cfg_dir = os.path.dirname(cfg_resolved) + format_version = detect_format_version(ext_dir) + # --- 2. Load extension Configuration.xml --- xml_parser = etree.XMLParser(remove_blank_text=False) tree = etree.parse(ext_resolved, xml_parser) @@ -501,7 +519,7 @@ def main(): lines = [] lines.append('') - lines.append(f'') + lines.append(f'') lines.append(f'\t<{type_name} uuid="{new_uuid_val}">') lines.append(internal_info_xml) lines.append("\t\t") @@ -1086,7 +1104,7 @@ def main(): new_form_uuid = new_guid() form_meta_lines = [ '', - f'', + f'', f'\t', '\t\t', '\t\t', @@ -1113,7 +1131,7 @@ def main(): src_form_tree = etree.parse(src_form_xml_path, src_form_parser) src_form_el = src_form_tree.getroot() - form_version = src_form_el.get("version", "2.17") + form_version = src_form_el.get("version", format_version) src_auto_cmd = None form_props = [] diff --git a/.claude/skills/epf-add-form/scripts/add-form.ps1 b/.claude/skills/epf-add-form/scripts/add-form.ps1 index 15266f7d..3befdccc 100644 --- a/.claude/skills/epf-add-form/scripts/add-form.ps1 +++ b/.claude/skills/epf-add-form/scripts/add-form.ps1 @@ -1,4 +1,4 @@ -# epf-add-form v1.0 — Add managed form to 1C processor +# epf-add-form v1.1 — Add managed form to 1C processor # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -16,6 +16,25 @@ param( $ErrorActionPreference = "Stop" +# --- Detect format version --- + +function Detect-FormatVersion([string]$dir) { + $d = $dir + while ($d) { + $cfgPath = Join-Path $d "Configuration.xml" + if (Test-Path $cfgPath) { + $head = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8).Substring(0, [Math]::Min(2000, (Get-Item $cfgPath).Length)) + if ($head -match ']+version="(\d+\.\d+)"') { return $Matches[1] } + } + $parent = Split-Path $d -Parent + if ($parent -eq $d) { break } + $d = $parent + } + return "2.17" +} + +$formatVersion = Detect-FormatVersion (Resolve-Path $SrcDir).Path + # --- Проверки --- $rootXmlPath = Join-Path $SrcDir "$ProcessorName.xml" @@ -52,7 +71,7 @@ $formUuid = [guid]::NewGuid().ToString() $formMetaXml = @" - + $FormName @@ -83,7 +102,7 @@ $formXmlPath = Join-Path $formExtDir "Form.xml" $formXml = @" - + true diff --git a/.claude/skills/epf-add-form/scripts/add-form.py b/.claude/skills/epf-add-form/scripts/add-form.py index 5ea16241..56926bf5 100644 --- a/.claude/skills/epf-add-form/scripts/add-form.py +++ b/.claude/skills/epf-add-form/scripts/add-form.py @@ -1,9 +1,10 @@ #!/usr/bin/env python3 -# add-form v1.0 — Add managed form to 1C external data processor +# add-form v1.1 — Add managed form to 1C external data processor # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os +import re import sys import uuid @@ -12,6 +13,22 @@ from lxml import etree NSMAP = {"md": "http://v8.1c.ru/8.3/MDClasses"} +def detect_format_version(d): + while d: + cfg_path = os.path.join(d, "Configuration.xml") + if os.path.isfile(cfg_path): + with open(cfg_path, "r", encoding="utf-8-sig") as f: + head = f.read(2000) + m = re.search(r']+version="(\d+\.\d+)"', head) + if m: + return m.group(1) + parent = os.path.dirname(d) + if parent == d: + break + d = parent + return "2.17" + + def save_xml_with_bom(tree, path): """Save XML tree to file with UTF-8 BOM.""" xml_bytes = etree.tostring(tree, xml_declaration=True, encoding="UTF-8") @@ -46,6 +63,8 @@ def main(): is_main = args.Main src_dir = args.SrcDir + format_version = detect_format_version(os.path.abspath(src_dir)) + # --- Checks --- root_xml_path = os.path.join(src_dir, f"{processor_name}.xml") @@ -92,7 +111,7 @@ def main(): ' xmlns:xr="http://v8.1c.ru/8.3/xcf/readable"' ' xmlns:xs="http://www.w3.org/2001/XMLSchema"' ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' - ' version="2.17">\n' + f' version="{format_version}">\n' f'\t\n' '\t\t\n' f'\t\t\t{form_name}\n' @@ -139,7 +158,7 @@ def main(): ' xmlns:xr="http://v8.1c.ru/8.3/xcf/readable"' ' xmlns:xs="http://www.w3.org/2001/XMLSchema"' ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' - ' version="2.17">\n' + f' version="{format_version}">\n' '\t\n' '\t\ttrue\n' '\t\n' diff --git a/.claude/skills/form-add/scripts/form-add.ps1 b/.claude/skills/form-add/scripts/form-add.ps1 index 0e0b6e82..2e57542f 100644 --- a/.claude/skills/form-add/scripts/form-add.ps1 +++ b/.claude/skills/form-add/scripts/form-add.ps1 @@ -1,4 +1,4 @@ -# form-add v1.2 — Add managed form to 1C config object +# form-add v1.3 — Add managed form to 1C config object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -16,6 +16,23 @@ param( $ErrorActionPreference = "Stop" +# --- Detect XML format version --- + +function Detect-FormatVersion([string]$dir) { + $d = $dir + while ($d) { + $cfgPath = Join-Path $d "Configuration.xml" + if (Test-Path $cfgPath) { + $head = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8).Substring(0, [Math]::Min(2000, (Get-Item $cfgPath).Length)) + if ($head -match ']+version="(\d+\.\d+)"') { return $Matches[1] } + } + $parent = Split-Path $d -Parent + if ($parent -eq $d) { break } + $d = $parent + } + return "2.17" +} + # --- Фаза 1: Определение типа объекта --- # Resolve ObjectPath (directory → .xml) @@ -36,6 +53,8 @@ if (-not (Test-Path $ObjectPath)) { } $objectXmlFull = Resolve-Path $ObjectPath +$script:formatVersion = Detect-FormatVersion (Split-Path $objectXmlFull.Path -Parent) + $xmlDoc = New-Object System.Xml.XmlDocument $xmlDoc.PreserveWhitespace = $true $xmlDoc.Load($objectXmlFull.Path) @@ -159,7 +178,7 @@ if ($objectType -in $processorLikeTypes) { $formMetaXml = @" - + $FormName @@ -196,7 +215,7 @@ if ($Purpose -eq "List" -or $Purpose -eq "Choice") { $formXml = @" - + true @@ -224,7 +243,7 @@ if ($Purpose -eq "List" -or $Purpose -eq "Choice") { $formXml = @" - + true @@ -267,7 +286,7 @@ if ($Purpose -eq "List" -or $Purpose -eq "Choice") { $formXml = @" - + true diff --git a/.claude/skills/form-add/scripts/form-add.py b/.claude/skills/form-add/scripts/form-add.py index e128de81..1b4d948c 100644 --- a/.claude/skills/form-add/scripts/form-add.py +++ b/.claude/skills/form-add/scripts/form-add.py @@ -1,9 +1,10 @@ #!/usr/bin/env python3 -# form-add v1.2 — Add managed form to 1C config object +# form-add v1.3 — Add managed form to 1C config object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os +import re import sys import uuid @@ -15,6 +16,22 @@ NSMAP = { } +def detect_format_version(d): + while d: + cfg_path = os.path.join(d, "Configuration.xml") + if os.path.isfile(cfg_path): + with open(cfg_path, "r", encoding="utf-8-sig") as f: + head = f.read(2000) + m = re.search(r']+version="(\d+\.\d+)"', head) + if m: + return m.group(1) + parent = os.path.dirname(d) + if parent == d: + break + d = parent + return "2.17" + + def save_xml_with_bom(tree, path): """Save XML tree to file with UTF-8 BOM.""" xml_bytes = etree.tostring(tree, xml_declaration=True, encoding="UTF-8") @@ -67,6 +84,8 @@ def main(): sys.exit(1) object_xml_full = os.path.abspath(object_path) + format_version = detect_format_version(os.path.dirname(object_xml_full)) + parser_xml = etree.XMLParser(remove_blank_text=False) tree = etree.parse(object_xml_full, parser_xml) root = tree.getroot() @@ -171,7 +190,7 @@ def main(): ' xmlns:xr="http://v8.1c.ru/8.3/xcf/readable"' ' xmlns:xs="http://www.w3.org/2001/XMLSchema"' ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' - ' version="2.17">\n' + f' version="{format_version}">\n' f'\t\n' '\t\t\n' f'\t\t\t{form_name}\n' @@ -225,7 +244,7 @@ def main(): form_xml = ( f'\n' - f'\n' + f'\n' '\t\n' '\t\ttrue\n' '\t\n' @@ -254,7 +273,7 @@ def main(): form_xml = ( f'\n' - f'\n' + f'\n' '\t\n' '\t\ttrue\n' '\t\n' @@ -297,7 +316,7 @@ def main(): form_xml = ( f'\n' - f'\n' + f'\n' '\t\n' '\t\ttrue\n' '\t\n' diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index 5b6151f3..847530c8 100644 --- a/.claude/skills/form-compile/scripts/form-compile.ps1 +++ b/.claude/skills/form-compile/scripts/form-compile.ps1 @@ -1,4 +1,4 @@ -# form-compile v1.1 — Compile 1C managed form from JSON +# form-compile v1.2 — Compile 1C managed form from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -11,6 +11,26 @@ param( $ErrorActionPreference = "Stop" [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 +# --- Detect XML format version --- + +function Detect-FormatVersion([string]$dir) { + $d = $dir + while ($d) { + $cfgPath = Join-Path $d "Configuration.xml" + if (Test-Path $cfgPath) { + $head = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8).Substring(0, [Math]::Min(2000, (Get-Item $cfgPath).Length)) + if ($head -match ']+version="(\d+\.\d+)"') { return $Matches[1] } + } + $parent = Split-Path $d -Parent + if ($parent -eq $d) { break } + $d = $parent + } + return "2.17" +} + +$script:outPathResolved = if ([System.IO.Path]::IsPathRooted($OutputPath)) { $OutputPath } else { Join-Path (Get-Location) $OutputPath } +$script:formatVersion = Detect-FormatVersion ([System.IO.Path]::GetDirectoryName($script:outPathResolved)) + # --- 1. Load and validate JSON --- if (-not (Test-Path $JsonPath)) { @@ -1107,7 +1127,7 @@ if ($def.title) { # Header X '' -X '' +X '' # Oops — Title was emitted before header. Need to fix the order. # Actually, let me restructure: build the body into a separate buffer, then assemble @@ -1117,7 +1137,7 @@ $script:xml = New-Object System.Text.StringBuilder 8192 $script:nextId = 1 X '' -X '' +X '' # 12a. Title (from def.title or properties.title — must be multilingual XML) $formTitle = $def.title diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 37be10e6..d5050bc0 100644 --- a/.claude/skills/form-compile/scripts/form-compile.py +++ b/.claude/skills/form-compile/scripts/form-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-compile v1.1 — Compile 1C managed form from JSON +# form-compile v1.2 — Compile 1C managed form from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -1002,6 +1002,22 @@ def emit_properties(lines, props, indent): lines.append(f'{indent}<{xml_name}>{val}') +def detect_format_version(d): + while d: + cfg_path = os.path.join(d, "Configuration.xml") + if os.path.isfile(cfg_path): + with open(cfg_path, "r", encoding="utf-8-sig") as f: + head = f.read(2000) + m = re.search(r']+version="(\d+\.\d+)"', head) + if m: + return m.group(1) + parent = os.path.dirname(d) + if parent == d: + break + d = parent + return "2.17" + + def main(): sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") @@ -1012,6 +1028,10 @@ def main(): parser.add_argument('-OutputPath', type=str, required=True) args = parser.parse_args() + # --- Detect XML format version --- + out_path_resolved = args.OutputPath if os.path.isabs(args.OutputPath) else os.path.join(os.getcwd(), args.OutputPath) + format_version = detect_format_version(os.path.dirname(out_path_resolved)) + # --- 1. Load and validate JSON --- json_path = args.JsonPath if not os.path.exists(json_path): @@ -1026,7 +1046,7 @@ def main(): lines = [] lines.append('') - lines.append('') + lines.append(f'') # Title form_title = defn.get('title') diff --git a/.claude/skills/form-validate/scripts/form-validate.ps1 b/.claude/skills/form-validate/scripts/form-validate.ps1 index c53a60ae..ad23601d 100644 --- a/.claude/skills/form-validate/scripts/form-validate.ps1 +++ b/.claude/skills/form-validate/scripts/form-validate.ps1 @@ -1,4 +1,4 @@ -# form-validate v1.3 — Validate 1C managed form +# form-validate v1.4 — Validate 1C managed form # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -126,10 +126,10 @@ if ($root.LocalName -ne "Form") { Report-Error "Root element is '$($root.LocalName)', expected 'Form'" } else { $version = $root.GetAttribute("version") - if ($version -eq "2.17") { + if ($version -eq "2.17" -or $version -eq "2.20") { Report-OK "Root element: Form version=$version" } elseif ($version) { - Report-Warn "Form version='$version' (expected 2.17)" + Report-Warn "Form version='$version' (expected 2.17 or 2.20)" } else { Report-Warn "Form version attribute missing" } diff --git a/.claude/skills/form-validate/scripts/form-validate.py b/.claude/skills/form-validate/scripts/form-validate.py index 91dac95b..e85eabb0 100644 --- a/.claude/skills/form-validate/scripts/form-validate.py +++ b/.claude/skills/form-validate/scripts/form-validate.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-validate v1.3 — Validate 1C managed form +# form-validate v1.4 — Validate 1C managed form # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -161,10 +161,10 @@ def main(): report_error(f"Root element is '{localname(root)}', expected 'Form'") else: version = root.get("version", "") - if version == "2.17": + if version in ("2.17", "2.20"): report_ok(f"Root element: Form version={version}") elif version: - report_warn(f"Form version='{version}' (expected 2.17)") + report_warn(f"Form version='{version}' (expected 2.17 or 2.20)") else: report_warn("Form version attribute missing") diff --git a/.claude/skills/help-add/scripts/add-help.ps1 b/.claude/skills/help-add/scripts/add-help.ps1 index 5211f700..ae067ec5 100644 --- a/.claude/skills/help-add/scripts/add-help.ps1 +++ b/.claude/skills/help-add/scripts/add-help.ps1 @@ -1,4 +1,4 @@ -# help-add v1.2 — Add built-in help to 1C object +# help-add v1.3 — Add built-in help to 1C object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -11,6 +11,25 @@ param( $ErrorActionPreference = "Stop" +# --- Detect format version --- + +function Detect-FormatVersion([string]$dir) { + $d = $dir + while ($d) { + $cfgPath = Join-Path $d "Configuration.xml" + if (Test-Path $cfgPath) { + $head = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8).Substring(0, [Math]::Min(2000, (Get-Item $cfgPath).Length)) + if ($head -match ']+version="(\d+\.\d+)"') { return $Matches[1] } + } + $parent = Split-Path $d -Parent + if ($parent -eq $d) { break } + $d = $parent + } + return "2.17" +} + +$formatVersion = Detect-FormatVersion (Resolve-Path $SrcDir).Path + # --- Проверки --- $objectDir = Join-Path $SrcDir $ObjectName @@ -35,7 +54,7 @@ $encBom = New-Object System.Text.UTF8Encoding($true) $helpXml = @" - + $Lang "@ diff --git a/.claude/skills/help-add/scripts/add-help.py b/.claude/skills/help-add/scripts/add-help.py index 03567724..ce6526d5 100644 --- a/.claude/skills/help-add/scripts/add-help.py +++ b/.claude/skills/help-add/scripts/add-help.py @@ -1,9 +1,10 @@ #!/usr/bin/env python3 -# add-help v1.2 — Add built-in help to 1C object +# add-help v1.3 — Add built-in help to 1C object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os +import re import sys from lxml import etree @@ -11,6 +12,22 @@ from lxml import etree NSMAP = {"md": "http://v8.1c.ru/8.3/MDClasses"} +def detect_format_version(d): + while d: + cfg_path = os.path.join(d, "Configuration.xml") + if os.path.isfile(cfg_path): + with open(cfg_path, "r", encoding="utf-8-sig") as f: + head = f.read(2000) + m = re.search(r']+version="(\d+\.\d+)"', head) + if m: + return m.group(1) + parent = os.path.dirname(d) + if parent == d: + break + d = parent + return "2.17" + + def save_xml_with_bom(tree, path): """Save XML tree to file with UTF-8 BOM.""" xml_bytes = etree.tostring(tree, xml_declaration=True, encoding="UTF-8") @@ -41,6 +58,8 @@ def main(): lang = args.Lang src_dir = args.SrcDir + format_version = detect_format_version(os.path.abspath(src_dir)) + # --- Checks --- object_dir = os.path.join(src_dir, object_name) @@ -62,7 +81,7 @@ def main(): '\n' + f' version="{format_version}">\n' f'\t{lang}\n' '' ) diff --git a/.claude/skills/interface-edit/scripts/interface-edit.ps1 b/.claude/skills/interface-edit/scripts/interface-edit.ps1 index adace28b..cefd9861 100644 --- a/.claude/skills/interface-edit/scripts/interface-edit.ps1 +++ b/.claude/skills/interface-edit/scripts/interface-edit.ps1 @@ -1,4 +1,4 @@ -# interface-edit v1.2 — Edit 1C CommandInterface.xml +# interface-edit v1.3 — Edit 1C CommandInterface.xml # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][string]$CIPath, @@ -23,6 +23,25 @@ if (-not [System.IO.Path]::IsPathRooted($CIPath)) { } $resolvedPath = $CIPath +# --- Detect format version --- + +function Detect-FormatVersion([string]$dir) { + $d = $dir + while ($d) { + $cfgPath = Join-Path $d "Configuration.xml" + if (Test-Path $cfgPath) { + $head = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8).Substring(0, [Math]::Min(2000, (Get-Item $cfgPath).Length)) + if ($head -match ']+version="(\d+\.\d+)"') { return $Matches[1] } + } + $parent = Split-Path $d -Parent + if ($parent -eq $d) { break } + $d = $parent + } + return "2.17" +} + +$formatVersion = Detect-FormatVersion ([System.IO.Path]::GetDirectoryName($CIPath)) + # --- Namespaces --- $script:ciNs = "http://v8.1c.ru/8.3/xcf/extrnprops" $script:xrNs = "http://v8.1c.ru/8.3/xcf/readable" @@ -42,7 +61,7 @@ if (-not (Test-Path $CIPath)) { xmlns:xr="$($script:xrNs)" xmlns:xs="$($script:xsNs)" xmlns:xsi="$($script:xsiNs)" - version="2.17"> + version="$formatVersion"> "@ $utf8Bom = New-Object System.Text.UTF8Encoding($true) diff --git a/.claude/skills/interface-edit/scripts/interface-edit.py b/.claude/skills/interface-edit/scripts/interface-edit.py index 0401a78a..951b91a9 100644 --- a/.claude/skills/interface-edit/scripts/interface-edit.py +++ b/.claude/skills/interface-edit/scripts/interface-edit.py @@ -1,14 +1,31 @@ #!/usr/bin/env python3 -# interface-edit v1.2 — Edit 1C CommandInterface.xml +# interface-edit v1.3 — Edit 1C CommandInterface.xml # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json import os +import re import subprocess import sys from lxml import etree +def detect_format_version(d): + while d: + cfg_path = os.path.join(d, "Configuration.xml") + if os.path.isfile(cfg_path): + with open(cfg_path, "r", encoding="utf-8-sig") as f: + head = f.read(2000) + m = re.search(r']+version="(\d+\.\d+)"', head) + if m: + return m.group(1) + parent = os.path.dirname(d) + if parent == d: + break + d = parent + return "2.17" + + CI_NS = "http://v8.1c.ru/8.3/xcf/extrnprops" XR_NS = "http://v8.1c.ru/8.3/xcf/readable" XSI_NS = "http://www.w3.org/2001/XMLSchema-instance" @@ -181,6 +198,10 @@ def main(): print("Either -DefinitionFile or -Operation is required", file=sys.stderr) sys.exit(1) + # --- Detect format version --- + ci_dir = os.path.dirname(os.path.abspath(args.CIPath)) + format_version = detect_format_version(ci_dir) + # --- Resolve path --- ci_path = args.CIPath if not os.path.isabs(ci_path): @@ -199,7 +220,7 @@ def main(): f'\txmlns:xr="{XR_NS}"\n' f'\txmlns:xs="{XS_NS}"\n' f'\txmlns:xsi="{XSI_NS}"\n' - f'\tversion="2.17">\n' + f'\tversion="{format_version}">\n' f'' ) with open(ci_path, "w", encoding="utf-8-sig") as fh: diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1 index 19615a16..02298d5a 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.ps1 +++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1 @@ -1,4 +1,4 @@ -# meta-compile v1.6 — Compile 1C metadata object from JSON +# meta-compile v1.7 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -2540,13 +2540,32 @@ function Emit-AddressingAttribute { $script:xmlnsDecl = 'xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +# --- 14a. Detect format version from existing Configuration.xml --- + +function Detect-FormatVersion([string]$dir) { + $d = $dir + while ($d) { + $cfgPath = Join-Path $d "Configuration.xml" + if (Test-Path $cfgPath) { + $head = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8).Substring(0, [Math]::Min(2000, (Get-Item $cfgPath).Length)) + if ($head -match ']+version="(\d+\.\d+)"') { return $Matches[1] } + } + $parent = Split-Path $d -Parent + if ($parent -eq $d) { break } + $d = $parent + } + return "2.17" +} + +$script:formatVersion = Detect-FormatVersion $OutputDir + # --- 15. Main assembler --- $uuid = New-Guid-String # XML declaration X '' -X "" +X "" X "`t<$objType uuid=`"$uuid`">" # InternalInfo @@ -2908,7 +2927,7 @@ if ($objType -eq "ExchangePlan") { $contentPath = Join-Path $extDir "Content.xml" if (-not (Test-Path $contentPath)) { Ensure-ExtDir - $contentXml = "`r`n`r`n" + $contentXml = "`r`n`r`n" [System.IO.File]::WriteAllText($contentPath, $contentXml, $enc) $modulesCreated += $contentPath } @@ -2917,7 +2936,7 @@ if ($objType -eq "BusinessProcess") { $flowchartPath = Join-Path $extDir "Flowchart.xml" if (-not (Test-Path $flowchartPath)) { Ensure-ExtDir - $flowchartXml = "`r`n`r`n" + $flowchartXml = "`r`n`r`n" [System.IO.File]::WriteAllText($flowchartPath, $flowchartXml, $enc) $modulesCreated += $flowchartPath } diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py index 30068532..9589efc8 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.py +++ b/.claude/skills/meta-compile/scripts/meta-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# meta-compile v1.6 — Compile 1C metadata object from JSON +# meta-compile v1.7 — Compile 1C metadata object from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -2202,6 +2202,27 @@ def emit_addressing_attribute(indent, addr_def): xmlns_decl = 'xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +# --------------------------------------------------------------------------- +# 14a. Detect format version from existing Configuration.xml +# --------------------------------------------------------------------------- + +def detect_format_version(d): + while d: + cfg_path = os.path.join(d, "Configuration.xml") + if os.path.isfile(cfg_path): + with open(cfg_path, "r", encoding="utf-8-sig") as f: + head = f.read(2000) + m = re.search(r']+version="(\d+\.\d+)"', head) + if m: + return m.group(1) + parent = os.path.dirname(d) + if parent == d: + break + d = parent + return "2.17" + +format_version = detect_format_version(output_dir) + # --------------------------------------------------------------------------- # 15. Main assembler # --------------------------------------------------------------------------- @@ -2209,7 +2230,7 @@ xmlns_decl = 'xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8 obj_uuid = new_uuid() X('') -X(f'') +X(f'') X(f'\t<{obj_type} uuid="{obj_uuid}">') # InternalInfo @@ -2529,7 +2550,7 @@ if obj_type == 'ExchangePlan': content_path = os.path.join(ext_dir, 'Content.xml') if not os.path.isfile(content_path): ensure_ext_dir() - content_xml = '\r\n\r\n' + content_xml = f'\r\n\r\n' write_utf8_bom(content_path, content_xml) modules_created.append(content_path) @@ -2537,7 +2558,7 @@ if obj_type == 'BusinessProcess': flowchart_path = os.path.join(ext_dir, 'Flowchart.xml') if not os.path.isfile(flowchart_path): ensure_ext_dir() - flowchart_xml = '\r\n\r\n' + flowchart_xml = f'\r\n\r\n' write_utf8_bom(flowchart_path, flowchart_xml) modules_created.append(flowchart_path) diff --git a/.claude/skills/role-compile/scripts/role-compile.ps1 b/.claude/skills/role-compile/scripts/role-compile.ps1 index 508ba64c..01133076 100644 --- a/.claude/skills/role-compile/scripts/role-compile.ps1 +++ b/.claude/skills/role-compile/scripts/role-compile.ps1 @@ -1,4 +1,4 @@ -# role-compile v1.3 — Compile 1C role from JSON +# role-compile v1.4 — Compile 1C role from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -505,6 +505,26 @@ if ($def.objects) { } } +# --- Detect format version --- + +function Detect-FormatVersion([string]$dir) { + $d = $dir + while ($d) { + $cfgPath = Join-Path $d "Configuration.xml" + if (Test-Path $cfgPath) { + $head = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8).Substring(0, [Math]::Min(2000, (Get-Item $cfgPath).Length)) + if ($head -match ']+version="(\d+\.\d+)"') { return $Matches[1] } + } + $parent = Split-Path $d -Parent + if ($parent -eq $d) { break } + $d = $parent + } + return "2.17" +} + +$resolvedOutputDir = if ([System.IO.Path]::IsPathRooted($OutputDir)) { $OutputDir } else { Join-Path (Get-Location) $OutputDir } +$formatVersion = Detect-FormatVersion $resolvedOutputDir + # --- 8. Generate UUID --- $uuid = [guid]::NewGuid().ToString() @@ -531,7 +551,7 @@ X ' xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef"' X ' xmlns:xr="http://v8.1c.ru/8.3/xcf/readable"' X ' xmlns:xs="http://www.w3.org/2001/XMLSchema"' X ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' -X ' version="2.17">' +X ' version="$formatVersion">' X " " X ' ' X " $roleName" @@ -560,7 +580,7 @@ X '' X '' +X " xsi:type=`"Rights`" version=`"$formatVersion`">" # Global flags (defaults match typical 1C roles) $sfno = if ($null -ne $def.setForNewObjects) { "$($def.setForNewObjects)".ToLower() } else { "false" } diff --git a/.claude/skills/role-compile/scripts/role-compile.py b/.claude/skills/role-compile/scripts/role-compile.py index 65dca59f..826fb2c9 100644 --- a/.claude/skills/role-compile/scripts/role-compile.py +++ b/.claude/skills/role-compile/scripts/role-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# role-compile v1.3 — Compile 1C role from JSON +# role-compile v1.4 — Compile 1C role from JSON # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -9,6 +9,22 @@ import sys import uuid +def detect_format_version(d): + while d: + cfg_path = os.path.join(d, "Configuration.xml") + if os.path.isfile(cfg_path): + with open(cfg_path, "r", encoding="utf-8-sig") as f: + head = f.read(2000) + m = re.search(r']+version="(\d+\.\d+)"', head) + if m: + return m.group(1) + parent = os.path.dirname(d) + if parent == d: + break + d = parent + return "2.17" + + def esc_xml(s): return s.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"') @@ -459,6 +475,9 @@ def main(): if not defn.get('objects') and defn.get('rights'): defn['objects'] = defn['rights'] + out_dir_resolved = args.OutputDir if os.path.isabs(args.OutputDir) else os.path.join(os.getcwd(), args.OutputDir) + format_version = detect_format_version(out_dir_resolved) + # --- 2. Parse all object entries --- parsed_objects = [] if defn.get('objects'): @@ -490,7 +509,7 @@ def main(): lines.append(' xmlns:xr="http://v8.1c.ru/8.3/xcf/readable"') lines.append(' xmlns:xs="http://www.w3.org/2001/XMLSchema"') lines.append(' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"') - lines.append(' version="2.17">') + lines.append(f' version="{format_version}">') lines.append(f' ') lines.append(' ') lines.append(f' {role_name}') @@ -516,7 +535,7 @@ def main(): lines.append('') + lines.append(f' xsi:type="Rights" version="{format_version}">') # Global flags sfno = str(defn['setForNewObjects']).lower() if defn.get('setForNewObjects') is not None else 'false' diff --git a/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 b/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 index 5580fa7b..ae4f1669 100644 --- a/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 +++ b/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 @@ -1,4 +1,4 @@ -# subsystem-compile v1.2 — Create 1C subsystem from JSON definition +# subsystem-compile v1.3 — Create 1C subsystem from JSON definition # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, @@ -267,12 +267,31 @@ if ($def.children) { foreach ($ch in $def.children) { $children += "$ch" } } +# --- Detect format version --- + +function Detect-FormatVersion([string]$dir) { + $d = $dir + while ($d) { + $cfgPath = Join-Path $d "Configuration.xml" + if (Test-Path $cfgPath) { + $head = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8).Substring(0, [Math]::Min(2000, (Get-Item $cfgPath).Length)) + if ($head -match ']+version="(\d+\.\d+)"') { return $Matches[1] } + } + $parent = Split-Path $d -Parent + if ($parent -eq $d) { break } + $d = $parent + } + return "2.17" +} + +$formatVersion = Detect-FormatVersion $OutputDir + # --- 4. Build XML --- $uuid = New-Guid-String $indent = "`t`t`t" X '' -X '' +X '' X "`t" X "`t`t" diff --git a/.claude/skills/subsystem-compile/scripts/subsystem-compile.py b/.claude/skills/subsystem-compile/scripts/subsystem-compile.py index 031a1ad0..311be981 100644 --- a/.claude/skills/subsystem-compile/scripts/subsystem-compile.py +++ b/.claude/skills/subsystem-compile/scripts/subsystem-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# subsystem-compile v1.2 — Create 1C subsystem from JSON definition +# subsystem-compile v1.3 — Create 1C subsystem from JSON definition # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -10,6 +10,22 @@ import uuid import xml.etree.ElementTree as ET +def detect_format_version(d): + while d: + cfg_path = os.path.join(d, "Configuration.xml") + if os.path.isfile(cfg_path): + with open(cfg_path, "r", encoding="utf-8-sig") as f: + head = f.read(2000) + m = re.search(r']+version="(\d+\.\d+)"', head) + if m: + return m.group(1) + parent = os.path.dirname(d) + if parent == d: + break + d = parent + return "2.17" + + def esc_xml(s): return s.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"') @@ -169,6 +185,8 @@ def main(): type_part = CONTENT_TYPE_MAP[type_part] return f'{type_part}.{name_part}' + format_version = detect_format_version(output_dir) + # --- 3. Resolve defaults --- synonym = str(defn['synonym']) if defn.get('synonym') else split_camel_case(obj_name) comment = str(defn['comment']) if defn.get('comment') else '' @@ -205,7 +223,7 @@ def main(): lines = [] lines.append('') - lines.append('') + lines.append(f'') lines.append(f'\t') lines.append('\t\t') diff --git a/.claude/skills/template-add/scripts/add-template.ps1 b/.claude/skills/template-add/scripts/add-template.ps1 index c6253e5b..98ebd718 100644 --- a/.claude/skills/template-add/scripts/add-template.ps1 +++ b/.claude/skills/template-add/scripts/add-template.ps1 @@ -1,4 +1,4 @@ -# template-add v1.2 — Add template to 1C object +# template-add v1.3 — Add template to 1C object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -59,13 +59,32 @@ New-Item -ItemType Directory -Path $templateExtDir -Force | Out-Null $encBom = New-Object System.Text.UTF8Encoding($true) +# --- Detect format version --- + +function Detect-FormatVersion([string]$dir) { + $d = $dir + while ($d) { + $cfgPath = Join-Path $d "Configuration.xml" + if (Test-Path $cfgPath) { + $head = [System.IO.File]::ReadAllText($cfgPath, [System.Text.Encoding]::UTF8).Substring(0, [Math]::Min(2000, (Get-Item $cfgPath).Length)) + if ($head -match ']+version="(\d+\.\d+)"') { return $Matches[1] } + } + $parent = Split-Path $d -Parent + if ($parent -eq $d) { break } + $d = $parent + } + return "2.17" +} + +$formatVersion = Detect-FormatVersion (Resolve-Path $SrcDir).Path + # --- 1. Метаданные макета (Templates/.xml) --- $templateUuid = [guid]::NewGuid().ToString() $templateMetaXml = @" - +