From 6f32e18e37eeedea1609067c18712176a1660b7c Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sat, 21 Feb 2026 17:22:05 +0300 Subject: [PATCH] improve(skills): auto-resolve ConfigPath, auto-register forms, handle LF line endings - cfe-init, cfe-borrow SKILL.md: auto-resolve ConfigPath from .v8-project.json configSrc - form-compile: auto-register
in parent ChildObjects from OutputPath convention - form-compile SKILL.md: document new workflow (form-add no longer required first) - cfe-borrow: handle LF line endings in OuterXml split (-split "\r?\n") Co-Authored-By: Claude Opus 4.6 --- .claude/skills/cfe-borrow/SKILL.md | 8 +++ .../skills/cfe-borrow/scripts/cfe-borrow.ps1 | 4 +- .claude/skills/cfe-init/SKILL.md | 12 ++-- .claude/skills/form-compile/SKILL.md | 6 ++ .../form-compile/scripts/form-compile.ps1 | 65 +++++++++++++++++++ 5 files changed, 89 insertions(+), 6 deletions(-) diff --git a/.claude/skills/cfe-borrow/SKILL.md b/.claude/skills/cfe-borrow/SKILL.md index c39ab7be..0bf747f5 100644 --- a/.claude/skills/cfe-borrow/SKILL.md +++ b/.claude/skills/cfe-borrow/SKILL.md @@ -16,6 +16,14 @@ allowed-tools: Расширение должно быть создано (`/cfe-init`) и содержать валидный `Configuration.xml`. +### Авто-определение ConfigPath + +Если пользователь не указал `-ConfigPath` — попробуй определить автоматически: +1. Прочитай `.v8-project.json` из корня проекта +2. Разреши целевую базу (по имени, ветке или `default` — алгоритм из `/db-list`) +3. Если у базы есть поле `configSrc` — используй как `-ConfigPath` +4. Если `configSrc` нет — спроси у пользователя + ## Параметры | Параметр | Описание | diff --git a/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 b/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 index 98eb50c4..0b526b35 100644 --- a/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 +++ b/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 @@ -537,7 +537,7 @@ function Borrow-Form { if ($autoCmdXml) { # Reindent for BaseForm: first line gets 2 tabs, other lines get +1 tab - $acLines = $autoCmdXml -split "`r`n" + $acLines = $autoCmdXml -split "`r?`n" for ($li = 0; $li -lt $acLines.Count; $li++) { if ($li -eq 0) { $formXmlSb.Append("`t`t$($acLines[$li])") | Out-Null } else { $formXmlSb.Append("`t$($acLines[$li])") | Out-Null } @@ -545,7 +545,7 @@ function Borrow-Form { } } - $ciLines = $childItemsXml -split "`r`n" + $ciLines = $childItemsXml -split "`r?`n" for ($li = 0; $li -lt $ciLines.Count; $li++) { if ($li -eq 0) { $formXmlSb.Append("`t`t$($ciLines[$li])") | Out-Null } else { $formXmlSb.Append("`t$($ciLines[$li])") | Out-Null } diff --git a/.claude/skills/cfe-init/SKILL.md b/.claude/skills/cfe-init/SKILL.md index c1c73602..5fac5bbf 100644 --- a/.claude/skills/cfe-init/SKILL.md +++ b/.claude/skills/cfe-init/SKILL.md @@ -16,11 +16,15 @@ allowed-tools: Если есть выгрузка базовой конфигурации, передай `-ConfigPath` — скрипт автоматически определит `CompatibilityMode` и UUID языка из базовой конфигурации. -Если `-ConfigPath` не задан, рекомендуется предварительно получить режим совместимости: +### Авто-определение ConfigPath -``` -/cf-info -Mode brief -``` +Если пользователь не указал `-ConfigPath` — попробуй определить автоматически: +1. Прочитай `.v8-project.json` из корня проекта +2. Разреши целевую базу (по имени, ветке или `default` — алгоритм из `/db-list`) +3. Если у базы есть поле `configSrc` — используй как `-ConfigPath` +4. Если `configSrc` нет — спроси у пользователя + +Если `.v8-project.json` не найден и `-ConfigPath` не задан — расширение создастся с предупреждением (UUID языка = нули, CompatibilityMode по умолчанию). ## Параметры diff --git a/.claude/skills/form-compile/SKILL.md b/.claude/skills/form-compile/SKILL.md index d2db3ba5..c4a991eb 100644 --- a/.claude/skills/form-compile/SKILL.md +++ b/.claude/skills/form-compile/SKILL.md @@ -395,6 +395,12 @@ powershell.exe -NoProfile -File .claude/skills/form-compile/scripts/form-compile - **ID**: последовательная нумерация, AutoCommandBar = id="-1" - **Unknown keys**: выводится предупреждение о нераспознанных ключах +## Workflow + +1. **Компиляция**: `/form-compile` генерирует `Form.xml` и автоматически регистрирует `` в `ChildObjects` родительского объекта (если OutputPath следует конвенции `.../TypePlural/ObjectName/Forms/FormName/Ext/Form.xml`). +2. **Метаданные формы** (`ФормаСписка.xml`) и `Module.bsl` создаёт `/form-add`. Если `/form-add` ещё не вызывался — вызови после `/form-compile`. Он не перезаписывает существующий Form.xml. +3. **Проверка**: `/form-validate`, `/form-info`. + ## Верификация ``` diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index 14a918ba..2f0652e6 100644 --- a/.claude/skills/form-compile/scripts/form-compile.ps1 +++ b/.claude/skills/form-compile/scripts/form-compile.ps1 @@ -1137,6 +1137,71 @@ if (-not (Test-Path $outDir)) { $enc = New-Object System.Text.UTF8Encoding($true) [System.IO.File]::WriteAllText($outPath, $xml.ToString(), $enc) +# --- 13b. Auto-register form in parent object XML --- + +# Infer parent from OutputPath: .../TypePlural/ObjectName/Forms/FormName/Ext/Form.xml +$formXmlDir = [System.IO.Path]::GetDirectoryName($outPath) +$formNameDir = [System.IO.Path]::GetDirectoryName($formXmlDir) +$formsDir = [System.IO.Path]::GetDirectoryName($formNameDir) +$objectDir = [System.IO.Path]::GetDirectoryName($formsDir) +$typePluralDir = [System.IO.Path]::GetDirectoryName($objectDir) + +$formName = [System.IO.Path]::GetFileName($formNameDir) +$objectName = [System.IO.Path]::GetFileName($objectDir) +$formsLeaf = [System.IO.Path]::GetFileName($formsDir) + +if ($formsLeaf -eq 'Forms') { + $objectXmlPath = Join-Path $typePluralDir "$objectName.xml" + if (Test-Path $objectXmlPath) { + $objDoc = New-Object System.Xml.XmlDocument + $objDoc.PreserveWhitespace = $true + $objDoc.Load($objectXmlPath) + + $nsMgr = New-Object System.Xml.XmlNamespaceManager($objDoc.NameTable) + $nsMgr.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses") + + $childObjects = $objDoc.SelectSingleNode("//md:ChildObjects", $nsMgr) + if ($childObjects) { + $existing = $childObjects.SelectSingleNode("md:Form[text()='$formName']", $nsMgr) + if (-not $existing) { + $formElem = $objDoc.CreateElement("Form", "http://v8.1c.ru/8.3/MDClasses") + $formElem.InnerText = $formName + + $insertBefore = $childObjects.SelectSingleNode("md:Template", $nsMgr) + if (-not $insertBefore) { $insertBefore = $childObjects.SelectSingleNode("md:TabularSection", $nsMgr) } + + if ($insertBefore) { + $childObjects.InsertBefore($formElem, $insertBefore) | Out-Null + $ws = $objDoc.CreateWhitespace("`n`t`t`t") + $childObjects.InsertBefore($ws, $insertBefore) | Out-Null + } else { + $lastChild = $childObjects.LastChild + if ($lastChild -and $lastChild.NodeType -eq [System.Xml.XmlNodeType]::Whitespace) { + $childObjects.InsertBefore($objDoc.CreateWhitespace("`n`t`t`t"), $lastChild) | Out-Null + $childObjects.InsertBefore($formElem, $lastChild) | Out-Null + } else { + $childObjects.AppendChild($objDoc.CreateWhitespace("`n`t`t`t")) | Out-Null + $childObjects.AppendChild($formElem) | Out-Null + $childObjects.AppendChild($objDoc.CreateWhitespace("`n`t`t")) | Out-Null + } + } + + $regEnc = New-Object System.Text.UTF8Encoding($true) + $regSettings = New-Object System.Xml.XmlWriterSettings + $regSettings.Encoding = $regEnc + $regSettings.Indent = $false + $regStream = New-Object System.IO.FileStream($objectXmlPath, [System.IO.FileMode]::Create) + $regWriter = [System.Xml.XmlWriter]::Create($regStream, $regSettings) + $objDoc.Save($regWriter) + $regWriter.Close() + $regStream.Close() + + Write-Host " Registered: $formName in $objectName.xml" + } + } + } +} + # --- 14. Summary --- $elCount = $script:nextId - 1