mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-31 23:40:51 +03:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba721dc650 |
@@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "cc-1c-skills",
|
|
||||||
"interface": {
|
|
||||||
"displayName": "1C Skills"
|
|
||||||
},
|
|
||||||
"plugins": [
|
|
||||||
{
|
|
||||||
"name": "1c-skills",
|
|
||||||
"source": {
|
|
||||||
"source": "url",
|
|
||||||
"url": "https://github.com/Nikolay-Shirokov/cc-1c-skills.git",
|
|
||||||
"ref": "port-codex"
|
|
||||||
},
|
|
||||||
"policy": {
|
|
||||||
"installation": "AVAILABLE"
|
|
||||||
},
|
|
||||||
"category": "Development"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "1c-skills-py",
|
|
||||||
"source": {
|
|
||||||
"source": "url",
|
|
||||||
"url": "https://github.com/Nikolay-Shirokov/cc-1c-skills.git",
|
|
||||||
"ref": "port-codex-py"
|
|
||||||
},
|
|
||||||
"policy": {
|
|
||||||
"installation": "AVAILABLE"
|
|
||||||
},
|
|
||||||
"category": "Development"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -24,7 +24,7 @@ allowed-tools:
|
|||||||
| `NoValidate` | Пропустить авто-валидацию |
|
| `NoValidate` | Пропустить авто-валидацию |
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-edit.ps1" -ConfigPath '<path>' -Operation modify-property -Value 'Version=1.0.0.1'
|
powershell.exe -NoProfile -File ".augment/skills/cf-edit/scripts/cf-edit.ps1" -ConfigPath '<path>' -Operation modify-property -Value 'Version=1.0.0.1'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Операции
|
## Операции
|
||||||
@@ -34,6 +34,7 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-edit.ps1" -Confi
|
|||||||
| `modify-property` | `Ключ=Значение` (batch `;;`) | Изменить свойство |
|
| `modify-property` | `Ключ=Значение` (batch `;;`) | Изменить свойство |
|
||||||
| `add-childObject` | `Type.Name` (batch `;;`) | Зарегистрировать уже существующий файл объекта в ChildObjects. Для создания нового объекта используй `/meta-compile`, `/role-compile`, `/subsystem-compile` — они регистрируют автоматически |
|
| `add-childObject` | `Type.Name` (batch `;;`) | Зарегистрировать уже существующий файл объекта в ChildObjects. Для создания нового объекта используй `/meta-compile`, `/role-compile`, `/subsystem-compile` — они регистрируют автоматически |
|
||||||
| `remove-childObject` | `Type.Name` (batch `;;`) | Удалить объект из ChildObjects |
|
| `remove-childObject` | `Type.Name` (batch `;;`) | Удалить объект из ChildObjects |
|
||||||
|
| `sort-childObjects` | вид, напр. `Catalog` (batch `;;`), либо пусто | Упорядочить ChildObjects по имени внутри вида. Без значения — все виды, кроме четырёх (см. reference) |
|
||||||
| `add-defaultRole` | `Role.Name` или `Name` | Добавить роль по умолчанию |
|
| `add-defaultRole` | `Role.Name` или `Name` | Добавить роль по умолчанию |
|
||||||
| `remove-defaultRole` | `Role.Name` или `Name` | Удалить роль по умолчанию |
|
| `remove-defaultRole` | `Role.Name` или `Name` | Удалить роль по умолчанию |
|
||||||
| `set-defaultRoles` | Имена через `;;` | Заменить список ролей по умолчанию |
|
| `set-defaultRoles` | Имена через `;;` | Заменить список ролей по умолчанию |
|
||||||
@@ -39,6 +39,20 @@
|
|||||||
|
|
||||||
Batch: `"Catalog.Товары ;; Document.Заказ ;; Enum.ВидыОплат"`
|
Batch: `"Catalog.Товары ;; Document.Заказ ;; Enum.ВидыОплат"`
|
||||||
|
|
||||||
|
## sort-childObjects
|
||||||
|
|
||||||
|
Упорядочивает объекты в `<ChildObjects>` по имени **внутри вида**. Значение — имя вида (`Catalog`, `Role`, …), batch через `;;`. Без значения обрабатываются все виды, какие есть в файле.
|
||||||
|
|
||||||
|
```
|
||||||
|
-Operation sort-childObjects — все виды, кроме перечисленных ниже
|
||||||
|
-Operation sort-childObjects -Value "Catalog" — только справочники
|
||||||
|
-Operation sort-childObjects -Value "Catalog ;; Role"
|
||||||
|
```
|
||||||
|
|
||||||
|
Не сортируются, пока вид не назван явно: `CommonAttribute`, `Subsystem`, `CommandGroup`, `Language`.
|
||||||
|
|
||||||
|
Вызов без значения дополнительно ставит группы видов в канонический порядок; вызов с явным видом трогает только имена внутри него.
|
||||||
|
|
||||||
## add-defaultRole / remove-defaultRole / set-defaultRoles
|
## add-defaultRole / remove-defaultRole / set-defaultRoles
|
||||||
|
|
||||||
Имя роли: `ПолныеПрава` или `Role.ПолныеПрава` (префикс `Role.` добавляется автоматически).
|
Имя роли: `ПолныеПрава` или `Role.ПолныеПрава` (префикс `Role.` добавляется автоматически).
|
||||||
+295
-32
@@ -1,10 +1,10 @@
|
|||||||
# cf-edit v1.23 — Edit 1C configuration root (Configuration.xml)
|
# cf-edit v1.28 — Edit 1C configuration root (Configuration.xml)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
[CmdletBinding(PositionalBinding=$false)]
|
[CmdletBinding(PositionalBinding=$false)]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)][Alias('Path')][string]$ConfigPath,
|
[Parameter(Mandatory)][Alias('Path')][string]$ConfigPath,
|
||||||
[string]$DefinitionFile,
|
[string]$DefinitionFile,
|
||||||
[ValidateSet("modify-property","add-childObject","remove-childObject","add-defaultRole","remove-defaultRole","set-defaultRoles","set-panels","set-home-page")]
|
[ValidateSet("modify-property","add-childObject","remove-childObject","add-defaultRole","remove-defaultRole","set-defaultRoles","set-panels","set-home-page","sort-childObjects")]
|
||||||
[string]$Operation,
|
[string]$Operation,
|
||||||
[string]$Value,
|
[string]$Value,
|
||||||
[switch]$NoValidate
|
[switch]$NoValidate
|
||||||
@@ -277,14 +277,14 @@ foreach ($child in $script:propsEl.ChildNodes) {
|
|||||||
}
|
}
|
||||||
Info "Configuration: $($script:objName)"
|
Info "Configuration: $($script:objName)"
|
||||||
|
|
||||||
# --- Canonical type order for ChildObjects (44 types) ---
|
# --- Canonical type order for ChildObjects (46 types) ---
|
||||||
$script:typeOrder = @(
|
$script:typeOrder = @(
|
||||||
"Language","Subsystem","StyleItem","Style",
|
"Language","Subsystem","StyleItem","Style",
|
||||||
"CommonPicture","SessionParameter","Role","CommonTemplate",
|
"CommonPicture","SessionParameter","Role","CommonTemplate",
|
||||||
"FilterCriterion","CommonModule","Bot","CommonAttribute","ExchangePlan",
|
"FilterCriterion","CommonModule","CommonAttribute","ExchangePlan",
|
||||||
"XDTOPackage","WebService","HTTPService","WSReference",
|
"XDTOPackage","WebService","HTTPService","WSReference",
|
||||||
"EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption",
|
"EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption",
|
||||||
"FunctionalOptionsParameter","DefinedType","CommonCommand","CommandGroup",
|
"FunctionalOptionsParameter","DefinedType","Bot","PaletteColor","CommonCommand","CommandGroup",
|
||||||
"Constant","CommonForm","Catalog","Document",
|
"Constant","CommonForm","Catalog","Document",
|
||||||
"DocumentNumerator","Sequence","DocumentJournal","Enum",
|
"DocumentNumerator","Sequence","DocumentJournal","Enum",
|
||||||
"Report","DataProcessor","InformationRegister","AccumulationRegister",
|
"Report","DataProcessor","InformationRegister","AccumulationRegister",
|
||||||
@@ -297,7 +297,7 @@ $script:typeOrder = @(
|
|||||||
$script:typeToDir = @{
|
$script:typeToDir = @{
|
||||||
"Language"="Languages"; "Subsystem"="Subsystems"; "StyleItem"="StyleItems"; "Style"="Styles"
|
"Language"="Languages"; "Subsystem"="Subsystems"; "StyleItem"="StyleItems"; "Style"="Styles"
|
||||||
"CommonPicture"="CommonPictures"; "SessionParameter"="SessionParameters"; "Role"="Roles"; "CommonTemplate"="CommonTemplates"
|
"CommonPicture"="CommonPictures"; "SessionParameter"="SessionParameters"; "Role"="Roles"; "CommonTemplate"="CommonTemplates"
|
||||||
"FilterCriterion"="FilterCriteria"; "CommonModule"="CommonModules"; "Bot"="Bots"; "CommonAttribute"="CommonAttributes"; "ExchangePlan"="ExchangePlans"
|
"FilterCriterion"="FilterCriteria"; "CommonModule"="CommonModules"; "Bot"="Bots"; "PaletteColor"="PaletteColors"; "CommonAttribute"="CommonAttributes"; "ExchangePlan"="ExchangePlans"
|
||||||
"XDTOPackage"="XDTOPackages"; "WebService"="WebServices"; "HTTPService"="HTTPServices"; "WSReference"="WSReferences"
|
"XDTOPackage"="XDTOPackages"; "WebService"="WebServices"; "HTTPService"="HTTPServices"; "WSReference"="WSReferences"
|
||||||
"EventSubscription"="EventSubscriptions"; "ScheduledJob"="ScheduledJobs"; "SettingsStorage"="SettingsStorages"; "FunctionalOption"="FunctionalOptions"
|
"EventSubscription"="EventSubscriptions"; "ScheduledJob"="ScheduledJobs"; "SettingsStorage"="SettingsStorages"; "FunctionalOption"="FunctionalOptions"
|
||||||
"FunctionalOptionsParameter"="FunctionalOptionsParameters"; "DefinedType"="DefinedTypes"; "CommonCommand"="CommonCommands"; "CommandGroup"="CommandGroups"
|
"FunctionalOptionsParameter"="FunctionalOptionsParameters"; "DefinedType"="DefinedTypes"; "CommonCommand"="CommonCommands"; "CommandGroup"="CommandGroups"
|
||||||
@@ -376,6 +376,21 @@ function Import-Fragment([string]$xmlString) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# --- Parse batch value (split by ;;) ---
|
# --- Parse batch value (split by ;;) ---
|
||||||
|
|
||||||
|
# Имя вида из пользовательского ввода → каноническое имя или $null.
|
||||||
|
# Ввод прощающий: регистр не важен, принимается имя каталога выгрузки (Catalogs → Catalog)
|
||||||
|
# и русское имя вида в единственном и множественном числе.
|
||||||
|
function Resolve-TypeName([string]$token) {
|
||||||
|
$key = "$token".Trim()
|
||||||
|
if (-not $key) { return $null }
|
||||||
|
foreach ($canon in $script:typeOrder) { if ($canon -eq $key) { return $canon } }
|
||||||
|
$byDir = $script:dirToType[$key.ToLowerInvariant()]
|
||||||
|
if ($byDir) { return $byDir }
|
||||||
|
$ru = $script:ruTypeMap[$key.ToLowerInvariant()]
|
||||||
|
if ($ru) { return $ru }
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
function Parse-BatchValue([string]$val) {
|
function Parse-BatchValue([string]$val) {
|
||||||
$items = @()
|
$items = @()
|
||||||
foreach ($part in $val.Split(";;")) {
|
foreach ($part in $val.Split(";;")) {
|
||||||
@@ -441,6 +456,220 @@ function Do-ModifyProperty([string]$batchVal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# --- Operation: add-childObject ---
|
# --- Operation: add-childObject ---
|
||||||
|
# Куда навык ставит новую запись в <ChildObjects> — настройка newObjectPosition.
|
||||||
|
# databases[].newObjectPosition базы, чей configSrc охватывает каталог родительского XML,
|
||||||
|
# иначе корневое поле, иначе end. Значения: end — после последнего объекта того же вида
|
||||||
|
# (так дописывает Конфигуратор); byName — по имени среди объектов того же вида.
|
||||||
|
# Файл ищем от рабочего каталога вверх, каталог конфигурации — запасной путь: так же
|
||||||
|
# его ищут support-guard и группа db-*, а скрипт навыка зовут по абсолютному пути, и cwd
|
||||||
|
# остаётся рабочим каталогом проекта.
|
||||||
|
# configSrc считается от каталога .v8-project.json, как задокументировано в
|
||||||
|
# docs/v8-project-guide.md. Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
function Get-NewObjectPosition([string]$cfgDir) {
|
||||||
|
try {
|
||||||
|
if (-not $cfgDir) { $cfgDir = "." }
|
||||||
|
$pj = Find-V8Project (Get-Location).Path
|
||||||
|
if (-not $pj) { $pj = Find-V8Project ([System.IO.Path]::GetFullPath($cfgDir)) }
|
||||||
|
if (-not $pj) { return "end" }
|
||||||
|
$proj = Get-Content -Raw $pj | ConvertFrom-Json
|
||||||
|
$projDir = [System.IO.Path]::GetDirectoryName($pj)
|
||||||
|
$cfgFull = [System.IO.Path]::GetFullPath($cfgDir).TrimEnd('\', '/')
|
||||||
|
if ($proj.databases) {
|
||||||
|
foreach ($db in $proj.databases) {
|
||||||
|
if ($db.configSrc -and $db.newObjectPosition) {
|
||||||
|
$src = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($projDir, $db.configSrc)).TrimEnd('\', '/')
|
||||||
|
if ($cfgFull -eq $src -or $cfgFull.StartsWith($src + [System.IO.Path]::DirectorySeparatorChar)) {
|
||||||
|
if ("$($db.newObjectPosition)" -eq "byName") { return "byName" }
|
||||||
|
return "end"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("$($proj.newObjectPosition)" -eq "byName") { return "byName" }
|
||||||
|
return "end"
|
||||||
|
} catch { return "end" }
|
||||||
|
}
|
||||||
|
|
||||||
|
# Виды, у которых порядок в дереве несёт смысл: автоматически их не упорядочиваем.
|
||||||
|
# CommonAttribute — исключение самого стандарта (#std467): у общих реквизитов-разделителей
|
||||||
|
# порядок в дереве задаёт порядок установки параметров сеанса. Subsystem и CommandGroup:
|
||||||
|
# пока они не перечислены в <SubsystemsOrder> / <GroupsOrder> файла Ext/CommandInterface.xml,
|
||||||
|
# порядок дерева задаёт порядок в интерфейсе, а платформа эти списки сама не заводит
|
||||||
|
# (в выгрузке ACC вне GroupsOrder 15 живых групп из 39). Language исключён из осторожности,
|
||||||
|
# без замера: языков обычно один-два, и в типовых их порядок не алфавитный.
|
||||||
|
# Явно названный вид сортируется в любом случае.
|
||||||
|
# Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
function Test-OrderSensitiveType([string]$typeName) {
|
||||||
|
return @("CommonAttribute", "Subsystem", "CommandGroup", "Language") -ccontains $typeName
|
||||||
|
}
|
||||||
|
|
||||||
|
# Порядок имён объектов метаданных, как в дереве Конфигуратора.
|
||||||
|
# Ключ — пары «ранг+символ»: регистр не учитывается, подчёркивание раньше цифр, цифры раньше
|
||||||
|
# букв, буквы по кодам (латиница раньше кириллицы), ё на месте е. Культурные таблицы не
|
||||||
|
# используются — они разные на разных ОС и в разных рантаймах, а так оба порта сравнивают
|
||||||
|
# одинаково везде. Равные ключи разводит ordinal-сравнение исходных строк.
|
||||||
|
# Возвращает -1 | 0 | 1. Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
function Compare-MetadataNames([string]$a, [string]$b) {
|
||||||
|
$keys = @("", "")
|
||||||
|
$names = @($a, $b)
|
||||||
|
for ($i = 0; $i -lt 2; $i++) {
|
||||||
|
$sb = New-Object System.Text.StringBuilder
|
||||||
|
foreach ($ch in $names[$i].ToLowerInvariant().ToCharArray()) {
|
||||||
|
if ($ch -eq [char]0x0451) { $ch = [char]0x0435 }
|
||||||
|
if ([char]::IsDigit($ch)) { [void]$sb.Append('1') }
|
||||||
|
elseif ([char]::IsLetter($ch)) { [void]$sb.Append('2') }
|
||||||
|
else { [void]$sb.Append('0') }
|
||||||
|
[void]$sb.Append($ch)
|
||||||
|
}
|
||||||
|
$keys[$i] = $sb.ToString()
|
||||||
|
}
|
||||||
|
$r = [string]::CompareOrdinal($keys[0], $keys[1])
|
||||||
|
if ($r -eq 0) { $r = [string]::CompareOrdinal($a, $b) }
|
||||||
|
if ($r -lt 0) { return -1 }
|
||||||
|
if ($r -gt 0) { return 1 }
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Сортировка имён компаратором Compare-MetadataNames. В py-порту ту же роль играет
|
||||||
|
# functools.cmp_to_key — штатный способ отсортировать компаратором; в PS 5.1 его нет,
|
||||||
|
# поэтому слияние вручную. Порядок обоих портов задаёт один и тот же компаратор.
|
||||||
|
function Sort-MetadataNames([string[]]$names) {
|
||||||
|
# Возврат без запятой-обёртки: приёмная сторона всегда пишет @(...), и одноэлементный
|
||||||
|
# результат остаётся массивом. С `return ,@(...)` @() собрал бы ОДИН объект-массив.
|
||||||
|
if ($names.Count -le 1) { return $names }
|
||||||
|
$mid = [int]($names.Count / 2)
|
||||||
|
$left = @(Sort-MetadataNames $names[0..($mid - 1)])
|
||||||
|
$right = @(Sort-MetadataNames $names[$mid..($names.Count - 1)])
|
||||||
|
$out = New-Object System.Collections.ArrayList
|
||||||
|
$i = 0; $j = 0
|
||||||
|
while ($i -lt $left.Count -and $j -lt $right.Count) {
|
||||||
|
if ((Compare-MetadataNames $left[$i] $right[$j]) -le 0) { [void]$out.Add($left[$i]); $i++ }
|
||||||
|
else { [void]$out.Add($right[$j]); $j++ }
|
||||||
|
}
|
||||||
|
while ($i -lt $left.Count) { [void]$out.Add($left[$i]); $i++ }
|
||||||
|
while ($j -lt $right.Count) { [void]$out.Add($right[$j]); $j++ }
|
||||||
|
return $out.ToArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
# Упорядочить <ChildObjects>: имена внутри вида, а без аргумента — и группы видов.
|
||||||
|
# Виды из Test-OrderSensitiveType по имени не сортируются, пока не названы явно.
|
||||||
|
# Вызов без значения дополнительно ставит группы видов в канонический порядок: платформа
|
||||||
|
# починила бы его только при загрузке-выгрузке, то есть неканоничный файл даёт диф на
|
||||||
|
# ровном месте. Переставляем ЗНАЧЕНИЯ узлов, а не сами узлы — отступы и структура файла
|
||||||
|
# остаются как были, в дифе только перестановка строк.
|
||||||
|
function Do-SortChildObjects([string]$batchVal) {
|
||||||
|
if (-not $script:childObjsEl) { Write-Error "No <ChildObjects> element found"; exit 1 }
|
||||||
|
|
||||||
|
# Ввод прощающий: регистр не важен, принимается и имя каталога (Catalogs → Catalog) —
|
||||||
|
# в дереве выгрузки виды видны именно во множественном числе.
|
||||||
|
# Без @(...) на приёме: Parse-BatchValue возвращает ,$items — обёртка, которую @()
|
||||||
|
# собрал бы как ОДИН объект-массив, и вид не нашёлся бы в $script:typeOrder.
|
||||||
|
$tokens = @()
|
||||||
|
if ("$batchVal".Trim()) { $tokens = Parse-BatchValue $batchVal }
|
||||||
|
$requested = @()
|
||||||
|
foreach ($token in $tokens) {
|
||||||
|
$canon = Resolve-TypeName $token
|
||||||
|
if (-not $canon) { Write-Error "Unknown type '$token'. Valid: $($script:typeOrder -join ', ')"; exit 1 }
|
||||||
|
$requested += $canon
|
||||||
|
}
|
||||||
|
|
||||||
|
$groups = New-Object System.Collections.Specialized.OrderedDictionary
|
||||||
|
foreach ($child in $script:childObjsEl.ChildNodes) {
|
||||||
|
if ($child.NodeType -ne 'Element') { continue }
|
||||||
|
$ln = $child.get_LocalName()
|
||||||
|
if (-not $groups.Contains($ln)) { $groups[$ln] = New-Object System.Collections.ArrayList }
|
||||||
|
[void]$groups[$ln].Add($child)
|
||||||
|
}
|
||||||
|
|
||||||
|
$targets = if ($requested.Count -gt 0) { $requested } else { @($groups.Keys | Where-Object { -not (Test-OrderSensitiveType $_) }) }
|
||||||
|
foreach ($typeName in $targets) {
|
||||||
|
if (-not $groups.Contains($typeName)) { continue }
|
||||||
|
$els = $groups[$typeName]
|
||||||
|
if ($els.Count -lt 2) { continue }
|
||||||
|
$names = @(foreach ($e in $els) { $e.InnerText })
|
||||||
|
$ordered = @(Sort-MetadataNames $names)
|
||||||
|
$same = $true
|
||||||
|
for ($i = 0; $i -lt $names.Count; $i++) { if ($names[$i] -cne $ordered[$i]) { $same = $false; break } }
|
||||||
|
if ($same) { continue }
|
||||||
|
for ($i = 0; $i -lt $els.Count; $i++) { $els[$i].InnerText = $ordered[$i] }
|
||||||
|
$script:modifyCount++
|
||||||
|
Info "Sorted: $typeName ($($els.Count))"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($requested.Count -gt 0) { return }
|
||||||
|
|
||||||
|
# Без аргумента приводим в порядок и сами группы видов: собранная навыками конфигурация
|
||||||
|
# может держать их не в каноне, и первая же выгрузка платформы даст диф. Переставляем
|
||||||
|
# содержимое существующих узлов, а не узлы, поэтому отступы и структура файла не меняются —
|
||||||
|
# в дифе только перестановка строк. Имя тега у XmlElement неизменяемо, поэтому там, где вид
|
||||||
|
# меняется, узел заменяется через ReplaceChild: он сохраняет окружающие пробельные узлы.
|
||||||
|
$elems = @()
|
||||||
|
foreach ($child in $script:childObjsEl.ChildNodes) {
|
||||||
|
if ($child.NodeType -eq 'Element') { $elems += $child }
|
||||||
|
}
|
||||||
|
$tags = @(); $texts = @()
|
||||||
|
foreach ($e in $elems) { $tags += $e.get_LocalName(); $texts += $e.InnerText }
|
||||||
|
$rank = @()
|
||||||
|
for ($i = 0; $i -lt $tags.Count; $i++) {
|
||||||
|
$r = $script:typeOrder.IndexOf($tags[$i])
|
||||||
|
if ($r -lt 0) { $r = $script:typeOrder.Count }
|
||||||
|
$rank += $r
|
||||||
|
}
|
||||||
|
# Порядок стабильный: вторым ключом идёт исходная позиция
|
||||||
|
$order = @(0..($tags.Count - 1) | Sort-Object @{e={$rank[$_]}}, @{e={$_}})
|
||||||
|
$same = $true
|
||||||
|
for ($i = 0; $i -lt $order.Count; $i++) { if ($order[$i] -ne $i) { $same = $false; break } }
|
||||||
|
if ($same) { return }
|
||||||
|
|
||||||
|
for ($i = 0; $i -lt $elems.Count; $i++) {
|
||||||
|
$srcIdx = $order[$i]
|
||||||
|
if ($tags[$i] -ceq $tags[$srcIdx]) {
|
||||||
|
$elems[$i].InnerText = $texts[$srcIdx]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$newEl = $script:xmlDoc.CreateElement($tags[$srcIdx], $script:mdNs)
|
||||||
|
$newEl.InnerText = $texts[$srcIdx]
|
||||||
|
[void]$script:childObjsEl.ReplaceChild($newEl, $elems[$i])
|
||||||
|
}
|
||||||
|
$script:modifyCount++
|
||||||
|
Info "Reordered type groups: $($elems.Count) entries"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Стиль существующего файла для round-trip-сохранения: BOM / EOL / регистр encoding /
|
||||||
|
# финальный перенос. $null → файл новый (сохранить текущее поведение).
|
||||||
|
# Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
function Detect-XmlStyle([string]$path) {
|
||||||
|
if (-not (Test-Path -LiteralPath $path)) { return $null }
|
||||||
|
$raw = [System.IO.File]::ReadAllBytes($path)
|
||||||
|
$bom = ($raw.Length -ge 3 -and $raw[0] -eq 0xEF -and $raw[1] -eq 0xBB -and $raw[2] -eq 0xBF)
|
||||||
|
$body = if ($bom) { [System.Text.Encoding]::UTF8.GetString($raw, 3, $raw.Length - 3) } else { [System.Text.Encoding]::UTF8.GetString($raw) }
|
||||||
|
$head = if ($body.Length -gt 200) { $body.Substring(0, 200) } else { $body }
|
||||||
|
$m = [regex]::Match($head, 'encoding="([^"]+)"')
|
||||||
|
return @{
|
||||||
|
bom = $bom
|
||||||
|
crlf = $body.Contains("`r`n")
|
||||||
|
enc = $(if ($m.Success) { $m.Groups[1].Value } else { "utf-8" })
|
||||||
|
finalNl = $body.EndsWith("`n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Привести текст XmlWriter к стилю оригинала; для НОВОГО файла ($null) — к канону выгрузки
|
||||||
|
# Конфигуратора: encoding="UTF-8", CRLF, без перевода строки в конце.
|
||||||
|
# Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
function Finalize-XmlText([string]$text, $style) {
|
||||||
|
if ($text.Length -gt 0 -and $text[0] -eq [char]0xFEFF) { $text = $text.Substring(1) }
|
||||||
|
$encDecl = $(if ($style) { $style.enc } else { "UTF-8" })
|
||||||
|
$text = $text.Replace('encoding="utf-8"', 'encoding="' + $encDecl + '"')
|
||||||
|
# Пустой элемент: XmlWriter отдаёт `<a />`, Конфигуратор пишет `<a/>`. Внутри
|
||||||
|
# CDATA/комментария ` />` может быть содержимым (там `>` не экранируется),
|
||||||
|
# поэтому они идут первыми ветками альтернации и возвращаются как есть.
|
||||||
|
$text = [regex]::Replace($text, '(?s)<!\[CDATA\[.*?\]\]>|<!--.*?-->|(?<=\S) />', { param($m) if ($m.Value -eq ' />') { '/>' } else { $m.Value } })
|
||||||
|
$text = ($text -replace "`r`n", "`n").TrimEnd("`n")
|
||||||
|
if ($style -and $style.finalNl) { $text += "`n" }
|
||||||
|
if (-not $style -or $style.crlf) { $text = $text -replace "`n", "`r`n" }
|
||||||
|
return $text
|
||||||
|
}
|
||||||
|
|
||||||
function Do-AddChildObject([string]$batchVal) {
|
function Do-AddChildObject([string]$batchVal) {
|
||||||
if (-not $script:childObjsEl) { Write-Error "No <ChildObjects> element found"; exit 1 }
|
if (-not $script:childObjsEl) { Write-Error "No <ChildObjects> element found"; exit 1 }
|
||||||
|
|
||||||
@@ -460,6 +689,8 @@ function Do-AddChildObject([string]$batchVal) {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$typeName = $item.Substring(0, $dotIdx)
|
$typeName = $item.Substring(0, $dotIdx)
|
||||||
|
$canonType = Resolve-TypeName $typeName
|
||||||
|
if ($canonType) { $typeName = $canonType }
|
||||||
$objNameVal = $item.Substring($dotIdx + 1)
|
$objNameVal = $item.Substring($dotIdx + 1)
|
||||||
|
|
||||||
# Check type is valid
|
# Check type is valid
|
||||||
@@ -504,11 +735,11 @@ To create a new $typeName, use $hintSkill (auto-registers in Configuration.xml):
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
# Find insertion point: after last element of same type, or after last element of preceding type
|
# Место вставки. Вид — по $script:typeOrder; внутри вида — по newObjectPosition.
|
||||||
|
$byName = (-not (Test-OrderSensitiveType $typeName) -and (Get-NewObjectPosition $script:configDir) -eq "byName")
|
||||||
$insertBefore = $null
|
$insertBefore = $null
|
||||||
$lastSameType = $null
|
$lastSameType = $null
|
||||||
$lastPrecedingType = $null
|
$firstLaterType = $null
|
||||||
$currentTypeIdx = -1
|
|
||||||
|
|
||||||
foreach ($child in $script:childObjsEl.ChildNodes) {
|
foreach ($child in $script:childObjsEl.ChildNodes) {
|
||||||
if ($child.NodeType -ne 'Element') { continue }
|
if ($child.NodeType -ne 'Element') { continue }
|
||||||
@@ -516,17 +747,29 @@ To create a new $typeName, use $hintSkill (auto-registers in Configuration.xml):
|
|||||||
if ($childTypeIdx -lt 0) { continue }
|
if ($childTypeIdx -lt 0) { continue }
|
||||||
|
|
||||||
if ($child.LocalName -eq $typeName) {
|
if ($child.LocalName -eq $typeName) {
|
||||||
# Same type — check alphabetical order
|
# Внутри вида — по newObjectPosition: end (по умолчанию) кладёт после последнего
|
||||||
if ($child.InnerText -gt $objNameVal -and -not $insertBefore) {
|
# объекта того же вида, byName — по имени. Subsystem по имени не упорядочиваем
|
||||||
# Insert before this element (alphabetical)
|
# никогда: порядок подсистем в дереве задаёт порядок разделов в панели.
|
||||||
|
$lastSameType = $child
|
||||||
|
if ($byName -and -not $insertBefore -and (Compare-MetadataNames $child.InnerText $objNameVal) -gt 0) {
|
||||||
$insertBefore = $child
|
$insertBefore = $child
|
||||||
}
|
}
|
||||||
$lastSameType = $child
|
} elseif ($childTypeIdx -gt $typeIdx -and -not $firstLaterType) {
|
||||||
} elseif ($childTypeIdx -lt $typeIdx) {
|
$firstLaterType = $child
|
||||||
$lastPrecedingType = $child
|
}
|
||||||
} elseif ($childTypeIdx -gt $typeIdx -and -not $insertBefore) {
|
}
|
||||||
# First element of a later type — insert before it
|
|
||||||
$insertBefore = $child
|
if (-not $insertBefore) {
|
||||||
|
# Место не выбрано именем — ставим сразу за последним объектом того же вида,
|
||||||
|
# то есть перед его следующим соседом. Через $firstLaterType этого не сделать:
|
||||||
|
# если видов старше в файле нет, запись уехала бы в самый конец блока,
|
||||||
|
# за пределы своей группы.
|
||||||
|
if ($lastSameType) {
|
||||||
|
$next = $lastSameType.NextSibling
|
||||||
|
while ($next -and $next.NodeType -ne 'Element') { $next = $next.NextSibling }
|
||||||
|
$insertBefore = $next
|
||||||
|
} else {
|
||||||
|
$insertBefore = $firstLaterType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,6 +801,8 @@ function Do-RemoveChildObject([string]$batchVal) {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
$typeName = $item.Substring(0, $dotIdx)
|
$typeName = $item.Substring(0, $dotIdx)
|
||||||
|
$canonType = Resolve-TypeName $typeName
|
||||||
|
if ($canonType) { $typeName = $canonType }
|
||||||
$objNameVal = $item.Substring($dotIdx + 1)
|
$objNameVal = $item.Substring($dotIdx + 1)
|
||||||
|
|
||||||
$found = $false
|
$found = $false
|
||||||
@@ -787,6 +1032,29 @@ $script:ruTypeMap = @{
|
|||||||
"бот" = "Bot"
|
"бот" = "Bot"
|
||||||
"планобмена" = "ExchangePlan"
|
"планобмена" = "ExchangePlan"
|
||||||
"хранилищенастроек" = "SettingsStorage"
|
"хранилищенастроек" = "SettingsStorage"
|
||||||
|
# Множественное число: в дереве конфигурации виды подписаны именно так.
|
||||||
|
"справочники" = "Catalog"
|
||||||
|
"документы" = "Document"
|
||||||
|
"перечисления" = "Enum"
|
||||||
|
"отчёты" = "Report"
|
||||||
|
"отчеты" = "Report"
|
||||||
|
"обработки" = "DataProcessor"
|
||||||
|
"общиеформы" = "CommonForm"
|
||||||
|
"журналыдокументов" = "DocumentJournal"
|
||||||
|
"планывидовхарактеристик" = "ChartOfCharacteristicTypes"
|
||||||
|
"планысчетов" = "ChartOfAccounts"
|
||||||
|
"планывидоврасчета" = "ChartOfCalculationTypes"
|
||||||
|
"планывидоврасчёта" = "ChartOfCalculationTypes"
|
||||||
|
"регистрысведений" = "InformationRegister"
|
||||||
|
"регистрынакопления" = "AccumulationRegister"
|
||||||
|
"регистрыбухгалтерии" = "AccountingRegister"
|
||||||
|
"регистрырасчета" = "CalculationRegister"
|
||||||
|
"регистрырасчёта" = "CalculationRegister"
|
||||||
|
"бизнеспроцессы" = "BusinessProcess"
|
||||||
|
"задачи" = "Task"
|
||||||
|
"боты" = "Bot"
|
||||||
|
"планыобмена" = "ExchangePlan"
|
||||||
|
"хранилищанастроек" = "SettingsStorage"
|
||||||
}
|
}
|
||||||
# plural folder → singular type
|
# plural folder → singular type
|
||||||
$script:dirToType = @{}
|
$script:dirToType = @{}
|
||||||
@@ -1028,11 +1296,16 @@ foreach ($op in $operations) {
|
|||||||
"set-defaultRoles" { Do-SetDefaultRoles $opValueStr }
|
"set-defaultRoles" { Do-SetDefaultRoles $opValueStr }
|
||||||
"set-panels" { Do-SetPanels $opValue }
|
"set-panels" { Do-SetPanels $opValue }
|
||||||
"set-home-page" { Do-SetHomePage $opValue }
|
"set-home-page" { Do-SetHomePage $opValue }
|
||||||
|
"sort-childObjects" { Do-SortChildObjects $opValueStr }
|
||||||
default { Write-Error "Unknown operation: $opName"; exit 1 }
|
default { Write-Error "Unknown operation: $opName"; exit 1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Save ---
|
# --- Save ---
|
||||||
|
# Стиль исходника снимаем ДО записи: правка чужого файла наследует его BOM/EOL/заголовок
|
||||||
|
# (#44/#46/#47), новый файл получает канон выгрузки. Зеркало _detect_xml_style в py-порту.
|
||||||
|
$xmlStyle = Detect-XmlStyle $resolvedPath
|
||||||
|
|
||||||
$settings = New-Object System.Xml.XmlWriterSettings
|
$settings = New-Object System.Xml.XmlWriterSettings
|
||||||
$settings.Encoding = New-Object System.Text.UTF8Encoding($true)
|
$settings.Encoding = New-Object System.Text.UTF8Encoding($true)
|
||||||
$settings.Indent = $false
|
$settings.Indent = $false
|
||||||
@@ -1043,22 +1316,12 @@ $writer = [System.Xml.XmlWriter]::Create($memStream, $settings)
|
|||||||
$script:xmlDoc.Save($writer)
|
$script:xmlDoc.Save($writer)
|
||||||
$writer.Flush(); $writer.Close()
|
$writer.Flush(); $writer.Close()
|
||||||
|
|
||||||
$bytes = $memStream.ToArray()
|
$text = [System.Text.Encoding]::UTF8.GetString($memStream.ToArray())
|
||||||
$memStream.Close()
|
$memStream.Close()
|
||||||
$text = [System.Text.Encoding]::UTF8.GetString($bytes)
|
$text = Finalize-XmlText $text $xmlStyle
|
||||||
if ($text.Length -gt 0 -and $text[0] -eq [char]0xFEFF) { $text = $text.Substring(1) }
|
|
||||||
$text = $text.Replace('encoding="utf-8"', 'encoding="UTF-8"')
|
|
||||||
# Пустой элемент: XmlWriter отдаёт `<a />`, Конфигуратор пишет `<a/>`. Внутри
|
|
||||||
# CDATA/комментария ` />` может быть содержимым (там `>` не экранируется),
|
|
||||||
# поэтому они идут первыми ветками альтернации и возвращаются как есть.
|
|
||||||
$text = [regex]::Replace($text, '(?s)<!\[CDATA\[.*?\]\]>|<!--.*?-->|(?<=\S) />', { param($m) if ($m.Value -eq ' />') { '/>' } else { $m.Value } })
|
|
||||||
# Целевой перевод строки: стиль файла-назначения — правка наследует его (#44/#46/#47),
|
|
||||||
# новый файл получает канон выгрузки CRLF. Зеркало _detect_xml_style в py-порту.
|
|
||||||
$targetEol = if ((Test-Path -LiteralPath $resolvedPath) -and ([System.IO.File]::ReadAllText($resolvedPath) -notmatch "`r`n")) { "`n" } else { "`r`n" }
|
|
||||||
$text = ($text -replace "`r`n", "`n") -replace "`n", $targetEol
|
|
||||||
|
|
||||||
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
$writeBom = ($null -eq $xmlStyle) -or $xmlStyle.bom
|
||||||
[System.IO.File]::WriteAllText($resolvedPath, $text, $utf8Bom)
|
[System.IO.File]::WriteAllText($resolvedPath, $text, (New-Object System.Text.UTF8Encoding($writeBom)))
|
||||||
Info "Saved: $resolvedPath"
|
Info "Saved: $resolvedPath"
|
||||||
|
|
||||||
# --- Auto-validate ---
|
# --- Auto-validate ---
|
||||||
+230
-30
@@ -1,8 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# cf-edit v1.23 — Edit 1C configuration root (Configuration.xml)
|
# cf-edit v1.28 — Edit 1C configuration root (Configuration.xml)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import functools
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@@ -316,14 +317,14 @@ XSI_NS = "http://www.w3.org/2001/XMLSchema-instance"
|
|||||||
V8_NS = "http://v8.1c.ru/8.1/data/core"
|
V8_NS = "http://v8.1c.ru/8.1/data/core"
|
||||||
XS_NS = "http://www.w3.org/2001/XMLSchema"
|
XS_NS = "http://www.w3.org/2001/XMLSchema"
|
||||||
|
|
||||||
# Canonical type order for ChildObjects (44 types)
|
# Canonical type order for ChildObjects (46 types)
|
||||||
TYPE_ORDER = [
|
TYPE_ORDER = [
|
||||||
"Language", "Subsystem", "StyleItem", "Style",
|
"Language", "Subsystem", "StyleItem", "Style",
|
||||||
"CommonPicture", "SessionParameter", "Role", "CommonTemplate",
|
"CommonPicture", "SessionParameter", "Role", "CommonTemplate",
|
||||||
"FilterCriterion", "CommonModule", "Bot", "CommonAttribute", "ExchangePlan",
|
"FilterCriterion", "CommonModule", "CommonAttribute", "ExchangePlan",
|
||||||
"XDTOPackage", "WebService", "HTTPService", "WSReference",
|
"XDTOPackage", "WebService", "HTTPService", "WSReference",
|
||||||
"EventSubscription", "ScheduledJob", "SettingsStorage", "FunctionalOption",
|
"EventSubscription", "ScheduledJob", "SettingsStorage", "FunctionalOption",
|
||||||
"FunctionalOptionsParameter", "DefinedType", "CommonCommand", "CommandGroup",
|
"FunctionalOptionsParameter", "DefinedType", "Bot", "PaletteColor", "CommonCommand", "CommandGroup",
|
||||||
"Constant", "CommonForm", "Catalog", "Document",
|
"Constant", "CommonForm", "Catalog", "Document",
|
||||||
"DocumentNumerator", "Sequence", "DocumentJournal", "Enum",
|
"DocumentNumerator", "Sequence", "DocumentJournal", "Enum",
|
||||||
"Report", "DataProcessor", "InformationRegister", "AccumulationRegister",
|
"Report", "DataProcessor", "InformationRegister", "AccumulationRegister",
|
||||||
@@ -336,7 +337,7 @@ TYPE_ORDER = [
|
|||||||
TYPE_TO_DIR = {
|
TYPE_TO_DIR = {
|
||||||
"Language": "Languages", "Subsystem": "Subsystems", "StyleItem": "StyleItems", "Style": "Styles",
|
"Language": "Languages", "Subsystem": "Subsystems", "StyleItem": "StyleItems", "Style": "Styles",
|
||||||
"CommonPicture": "CommonPictures", "SessionParameter": "SessionParameters", "Role": "Roles", "CommonTemplate": "CommonTemplates",
|
"CommonPicture": "CommonPictures", "SessionParameter": "SessionParameters", "Role": "Roles", "CommonTemplate": "CommonTemplates",
|
||||||
"FilterCriterion": "FilterCriteria", "CommonModule": "CommonModules", "Bot": "Bots", "CommonAttribute": "CommonAttributes", "ExchangePlan": "ExchangePlans",
|
"FilterCriterion": "FilterCriteria", "CommonModule": "CommonModules", "Bot": "Bots", "PaletteColor": "PaletteColors", "PaletteColor": "PaletteColors", "CommonAttribute": "CommonAttributes", "ExchangePlan": "ExchangePlans",
|
||||||
"XDTOPackage": "XDTOPackages", "WebService": "WebServices", "HTTPService": "HTTPServices", "WSReference": "WSReferences",
|
"XDTOPackage": "XDTOPackages", "WebService": "WebServices", "HTTPService": "HTTPServices", "WSReference": "WSReferences",
|
||||||
"EventSubscription": "EventSubscriptions", "ScheduledJob": "ScheduledJobs", "SettingsStorage": "SettingsStorages", "FunctionalOption": "FunctionalOptions",
|
"EventSubscription": "EventSubscriptions", "ScheduledJob": "ScheduledJobs", "SettingsStorage": "SettingsStorages", "FunctionalOption": "FunctionalOptions",
|
||||||
"FunctionalOptionsParameter": "FunctionalOptionsParameters", "DefinedType": "DefinedTypes", "CommonCommand": "CommonCommands", "CommandGroup": "CommandGroups",
|
"FunctionalOptionsParameter": "FunctionalOptionsParameters", "DefinedType": "DefinedTypes", "CommonCommand": "CommonCommands", "CommandGroup": "CommandGroups",
|
||||||
@@ -353,6 +354,137 @@ SCALAR_PROPS = ["Name", "Version", "Vendor", "Comment", "NamePrefix", "UpdateCat
|
|||||||
REF_PROPS = ["DefaultLanguage"]
|
REF_PROPS = ["DefaultLanguage"]
|
||||||
|
|
||||||
|
|
||||||
|
def get_new_object_position(cfg_dir):
|
||||||
|
"""Куда навык ставит новую запись в <ChildObjects> — настройка newObjectPosition.
|
||||||
|
|
||||||
|
databases[].newObjectPosition базы, чей configSrc охватывает каталог родительского XML,
|
||||||
|
иначе корневое поле, иначе end. Значения: end — после последнего объекта того же вида
|
||||||
|
(так дописывает Конфигуратор); byName — по имени среди объектов того же вида.
|
||||||
|
Файл ищем от рабочего каталога вверх, каталог конфигурации — запасной путь: так же
|
||||||
|
его ищут support-guard и группа db-*, а скрипт навыка зовут по абсолютному пути, и cwd
|
||||||
|
остаётся рабочим каталогом проекта.
|
||||||
|
configSrc считается от каталога .v8-project.json, как задокументировано в
|
||||||
|
docs/v8-project-guide.md. Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
pj = _sg_find_v8project(os.getcwd()) or _sg_find_v8project(os.path.abspath(cfg_dir or "."))
|
||||||
|
if not pj:
|
||||||
|
return "end"
|
||||||
|
proj = json.loads(open(pj, encoding="utf-8-sig").read())
|
||||||
|
proj_dir = os.path.dirname(pj)
|
||||||
|
cfg_full = os.path.normcase(os.path.abspath(cfg_dir or ".")).rstrip("\\/")
|
||||||
|
for db in proj.get("databases", []):
|
||||||
|
src = db.get("configSrc")
|
||||||
|
if src and db.get("newObjectPosition"):
|
||||||
|
src_full = os.path.normcase(os.path.abspath(os.path.join(proj_dir, src))).rstrip("\\/")
|
||||||
|
if cfg_full == src_full or cfg_full.startswith(src_full + os.sep):
|
||||||
|
return "byName" if str(db["newObjectPosition"]).lower() == "byname" else "end"
|
||||||
|
if str(proj.get("newObjectPosition") or "").lower() == "byname":
|
||||||
|
return "byName"
|
||||||
|
return "end"
|
||||||
|
except Exception:
|
||||||
|
return "end"
|
||||||
|
|
||||||
|
|
||||||
|
def is_order_sensitive_type(type_name):
|
||||||
|
"""Виды, у которых порядок в дереве несёт смысл: автоматически их не упорядочиваем.
|
||||||
|
|
||||||
|
CommonAttribute — исключение самого стандарта (#std467): у общих реквизитов-разделителей
|
||||||
|
порядок в дереве задаёт порядок установки параметров сеанса. Subsystem и CommandGroup:
|
||||||
|
пока они не перечислены в <SubsystemsOrder> / <GroupsOrder> файла Ext/CommandInterface.xml,
|
||||||
|
порядок дерева задаёт порядок в интерфейсе, а платформа эти списки сама не заводит
|
||||||
|
(в выгрузке ACC вне GroupsOrder 15 живых групп из 39). Language исключён из осторожности,
|
||||||
|
без замера: языков обычно один-два, и в типовых их порядок не алфавитный.
|
||||||
|
Явно названный вид сортируется в любом случае.
|
||||||
|
Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
"""
|
||||||
|
return type_name in ("CommonAttribute", "Subsystem", "CommandGroup", "Language")
|
||||||
|
|
||||||
|
|
||||||
|
def compare_metadata_names(a, b):
|
||||||
|
"""Порядок имён объектов метаданных, как в дереве Конфигуратора.
|
||||||
|
|
||||||
|
Ключ — пары «ранг+символ»: регистр не учитывается, подчёркивание раньше цифр, цифры раньше
|
||||||
|
букв, буквы по кодам (латиница раньше кириллицы), ё на месте е. Культурные таблицы не
|
||||||
|
используются — они разные на разных ОС и в разных рантаймах, а так оба порта сравнивают
|
||||||
|
одинаково везде. Равные ключи разводит ordinal-сравнение исходных строк.
|
||||||
|
Возвращает -1 | 0 | 1. Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
"""
|
||||||
|
keys = []
|
||||||
|
for name in (a, b):
|
||||||
|
parts = []
|
||||||
|
for ch in name.lower():
|
||||||
|
if ch == "ё":
|
||||||
|
ch = "е"
|
||||||
|
if ch.isdigit():
|
||||||
|
parts.append("1" + ch)
|
||||||
|
elif ch.isalpha():
|
||||||
|
parts.append("2" + ch)
|
||||||
|
else:
|
||||||
|
parts.append("0" + ch)
|
||||||
|
keys.append("".join(parts))
|
||||||
|
if keys[0] != keys[1]:
|
||||||
|
return -1 if keys[0] < keys[1] else 1
|
||||||
|
if a != b:
|
||||||
|
return -1 if a < b else 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
RU_TYPE_MAP = {
|
||||||
|
"справочник": "Catalog", "документ": "Document", "перечисление": "Enum",
|
||||||
|
"отчёт": "Report", "отчет": "Report", "обработка": "DataProcessor",
|
||||||
|
"общаяформа": "CommonForm", "журналдокументов": "DocumentJournal",
|
||||||
|
"планвидовхарактеристик": "ChartOfCharacteristicTypes",
|
||||||
|
"плансчетов": "ChartOfAccounts",
|
||||||
|
"планвидоврасчета": "ChartOfCalculationTypes",
|
||||||
|
"планвидоврасчёта": "ChartOfCalculationTypes",
|
||||||
|
"регистрсведений": "InformationRegister",
|
||||||
|
"регистрнакопления": "AccumulationRegister",
|
||||||
|
"регистрбухгалтерии": "AccountingRegister",
|
||||||
|
"регистррасчета": "CalculationRegister",
|
||||||
|
"регистррасчёта": "CalculationRegister",
|
||||||
|
"бизнеспроцесс": "BusinessProcess",
|
||||||
|
"бот": "Bot",
|
||||||
|
"задача": "Task", "планобмена": "ExchangePlan",
|
||||||
|
"хранилищенастроек": "SettingsStorage",
|
||||||
|
# Множественное число: в дереве конфигурации виды подписаны именно так.
|
||||||
|
"справочники": "Catalog", "документы": "Document", "перечисления": "Enum",
|
||||||
|
"отчёты": "Report", "отчеты": "Report", "обработки": "DataProcessor",
|
||||||
|
"общиеформы": "CommonForm", "журналыдокументов": "DocumentJournal",
|
||||||
|
"планывидовхарактеристик": "ChartOfCharacteristicTypes",
|
||||||
|
"планысчетов": "ChartOfAccounts",
|
||||||
|
"планывидоврасчета": "ChartOfCalculationTypes",
|
||||||
|
"планывидоврасчёта": "ChartOfCalculationTypes",
|
||||||
|
"регистрысведений": "InformationRegister",
|
||||||
|
"регистрынакопления": "AccumulationRegister",
|
||||||
|
"регистрыбухгалтерии": "AccountingRegister",
|
||||||
|
"регистррасчета": "CalculationRegister", "регистрырасчета": "CalculationRegister",
|
||||||
|
"регистрырасчёта": "CalculationRegister",
|
||||||
|
"бизнеспроцессы": "BusinessProcess",
|
||||||
|
"боты": "Bot",
|
||||||
|
"задачи": "Task", "планыобмена": "ExchangePlan",
|
||||||
|
"хранилищанастроек": "SettingsStorage",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_type_name(token):
|
||||||
|
"""Имя вида из пользовательского ввода → каноническое имя или None.
|
||||||
|
|
||||||
|
Ввод прощающий: регистр не важен, принимается имя каталога выгрузки
|
||||||
|
(Catalogs → Catalog) и русское имя вида в единственном и множественном числе.
|
||||||
|
"""
|
||||||
|
key = (token or "").strip().lower()
|
||||||
|
if not key:
|
||||||
|
return None
|
||||||
|
for canon in TYPE_ORDER:
|
||||||
|
if canon.lower() == key:
|
||||||
|
return canon
|
||||||
|
for canon, dir_name in TYPE_TO_DIR.items():
|
||||||
|
if dir_name.lower() == key:
|
||||||
|
return canon
|
||||||
|
return RU_TYPE_MAP.get(key)
|
||||||
|
|
||||||
|
|
||||||
def localname(el):
|
def localname(el):
|
||||||
return etree.QName(el.tag).localname
|
return etree.QName(el.tag).localname
|
||||||
|
|
||||||
@@ -498,7 +630,7 @@ def main():
|
|||||||
parser = argparse.ArgumentParser(description="Edit 1C configuration root (Configuration.xml)", allow_abbrev=False)
|
parser = argparse.ArgumentParser(description="Edit 1C configuration root (Configuration.xml)", allow_abbrev=False)
|
||||||
parser.add_argument("-ConfigPath", "-Path", required=True)
|
parser.add_argument("-ConfigPath", "-Path", required=True)
|
||||||
parser.add_argument("-DefinitionFile", default=None)
|
parser.add_argument("-DefinitionFile", default=None)
|
||||||
parser.add_argument("-Operation", default=None, choices=["modify-property", "add-childObject", "remove-childObject", "add-defaultRole", "remove-defaultRole", "set-defaultRoles", "set-panels", "set-home-page"])
|
parser.add_argument("-Operation", default=None, choices=["modify-property", "add-childObject", "remove-childObject", "add-defaultRole", "remove-defaultRole", "set-defaultRoles", "set-panels", "set-home-page", "sort-childObjects"])
|
||||||
parser.add_argument("-Value", default=None)
|
parser.add_argument("-Value", default=None)
|
||||||
parser.add_argument("-NoValidate", action="store_true")
|
parser.add_argument("-NoValidate", action="store_true")
|
||||||
args = ci_parse_args(parser)
|
args = ci_parse_args(parser)
|
||||||
@@ -637,7 +769,7 @@ def main():
|
|||||||
if dot_idx < 1:
|
if dot_idx < 1:
|
||||||
print(f"Invalid format '{item}', expected 'Type.Name'", file=sys.stderr)
|
print(f"Invalid format '{item}', expected 'Type.Name'", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
type_name = item[:dot_idx]
|
type_name = resolve_type_name(item[:dot_idx]) or item[:dot_idx]
|
||||||
obj_name_val = item[dot_idx + 1:]
|
obj_name_val = item[dot_idx + 1:]
|
||||||
|
|
||||||
if type_name not in TYPE_ORDER:
|
if type_name not in TYPE_ORDER:
|
||||||
@@ -674,8 +806,15 @@ def main():
|
|||||||
warn(f"Already exists: {type_name}.{obj_name_val}")
|
warn(f"Already exists: {type_name}.{obj_name_val}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Find insertion point
|
# Место вставки. Вид — по TYPE_ORDER; внутри вида — по newObjectPosition:
|
||||||
|
# end (по умолчанию) кладёт после последнего объекта того же вида, byName — по имени.
|
||||||
|
# Subsystem по имени не упорядочиваем никогда: порядок подсистем в дереве задаёт
|
||||||
|
# порядок разделов в панели, пока их не перечислили в <SubsystemsOrder>.
|
||||||
|
by_name = (not is_order_sensitive_type(type_name)
|
||||||
|
and get_new_object_position(config_dir) == "byName")
|
||||||
insert_before = None
|
insert_before = None
|
||||||
|
last_same = None
|
||||||
|
first_later = None
|
||||||
for child in child_objs_el:
|
for child in child_objs_el:
|
||||||
if not isinstance(child.tag, str):
|
if not isinstance(child.tag, str):
|
||||||
continue
|
continue
|
||||||
@@ -685,10 +824,24 @@ def main():
|
|||||||
child_type_idx = TYPE_ORDER.index(child_type_name)
|
child_type_idx = TYPE_ORDER.index(child_type_name)
|
||||||
|
|
||||||
if child_type_name == type_name:
|
if child_type_name == type_name:
|
||||||
if (child.text or "") > obj_name_val and insert_before is None:
|
last_same = child
|
||||||
|
if (by_name and insert_before is None
|
||||||
|
and compare_metadata_names(child.text or "", obj_name_val) > 0):
|
||||||
insert_before = child
|
insert_before = child
|
||||||
elif child_type_idx > type_idx and insert_before is None:
|
elif child_type_idx > type_idx and first_later is None:
|
||||||
insert_before = child
|
first_later = child
|
||||||
|
|
||||||
|
if insert_before is None:
|
||||||
|
# Место не выбрано именем — ставим сразу за последним объектом того же вида,
|
||||||
|
# то есть перед его следующим соседом. Через first_later этого не сделать:
|
||||||
|
# если видов старше в файле нет, запись уехала бы в самый конец блока,
|
||||||
|
# за пределы своей группы.
|
||||||
|
if last_same is not None:
|
||||||
|
siblings = [c for c in child_objs_el if isinstance(c.tag, str)]
|
||||||
|
pos = siblings.index(last_same)
|
||||||
|
insert_before = siblings[pos + 1] if pos + 1 < len(siblings) else None
|
||||||
|
else:
|
||||||
|
insert_before = first_later
|
||||||
|
|
||||||
new_el = etree.Element(f"{{{MD_NS}}}{type_name}")
|
new_el = etree.Element(f"{{{MD_NS}}}{type_name}")
|
||||||
new_el.text = obj_name_val
|
new_el.text = obj_name_val
|
||||||
@@ -701,6 +854,69 @@ def main():
|
|||||||
add_count += 1
|
add_count += 1
|
||||||
info(f"Added: {type_name}.{obj_name_val}")
|
info(f"Added: {type_name}.{obj_name_val}")
|
||||||
|
|
||||||
|
def do_sort_child_objects(batch_val):
|
||||||
|
"""Упорядочить <ChildObjects>: имена внутри вида, а без аргумента — и группы видов.
|
||||||
|
|
||||||
|
Виды из is_order_sensitive_type по имени не сортируются, пока не названы явно.
|
||||||
|
Вызов без значения дополнительно ставит группы видов в канонический порядок: платформа
|
||||||
|
починила бы его только при загрузке-выгрузке, то есть неканоничный файл даёт диф на
|
||||||
|
ровном месте. Переставляем ЗНАЧЕНИЯ узлов, а не сами узлы — отступы и структура файла
|
||||||
|
остаются как были, в дифе только перестановка строк.
|
||||||
|
"""
|
||||||
|
nonlocal modify_count
|
||||||
|
if child_objs_el is None:
|
||||||
|
print("No <ChildObjects> element found", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
requested = []
|
||||||
|
for token in (parse_batch_value(batch_val) if str(batch_val or "").strip() else []):
|
||||||
|
canon = resolve_type_name(token)
|
||||||
|
if canon is None:
|
||||||
|
print(f"Unknown type '{token}'. Valid: {', '.join(TYPE_ORDER)}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
requested.append(canon)
|
||||||
|
|
||||||
|
groups = {}
|
||||||
|
for child in child_objs_el:
|
||||||
|
if not isinstance(child.tag, str):
|
||||||
|
continue
|
||||||
|
groups.setdefault(localname(child), []).append(child)
|
||||||
|
|
||||||
|
targets = requested or [t for t in groups if not is_order_sensitive_type(t)]
|
||||||
|
for type_name in targets:
|
||||||
|
els = groups.get(type_name, [])
|
||||||
|
if len(els) < 2:
|
||||||
|
continue
|
||||||
|
names = [e.text or "" for e in els]
|
||||||
|
ordered = sorted(names, key=functools.cmp_to_key(compare_metadata_names))
|
||||||
|
if names == ordered:
|
||||||
|
continue
|
||||||
|
for el, name in zip(els, ordered):
|
||||||
|
el.text = name
|
||||||
|
modify_count += 1
|
||||||
|
info(f"Sorted: {type_name} ({len(els)})")
|
||||||
|
|
||||||
|
if requested:
|
||||||
|
# Вид назван явно — точечная операция: взаимный порядок групп не трогаем.
|
||||||
|
return
|
||||||
|
|
||||||
|
# Без аргумента приводим в порядок и сами группы видов: собранная навыками
|
||||||
|
# конфигурация может держать их не в каноне, и первая же выгрузка платформы даст
|
||||||
|
# диф. Переставляем содержимое существующих узлов, а не узлы, поэтому отступы и
|
||||||
|
# структура файла не меняются — в дифе только перестановка строк.
|
||||||
|
elems = [c for c in child_objs_el if isinstance(c.tag, str)]
|
||||||
|
pairs = [(localname(c), c.text or "") for c in elems]
|
||||||
|
ranked = sorted(range(len(pairs)),
|
||||||
|
key=lambda i: (TYPE_ORDER.index(pairs[i][0]) if pairs[i][0] in TYPE_ORDER else len(TYPE_ORDER), i))
|
||||||
|
wanted = [pairs[i] for i in ranked]
|
||||||
|
if wanted == pairs:
|
||||||
|
return
|
||||||
|
for el, (tag, text) in zip(elems, wanted):
|
||||||
|
el.tag = f'{{{MD_NS}}}{tag}'
|
||||||
|
el.text = text
|
||||||
|
modify_count += 1
|
||||||
|
info(f"Reordered type groups: {len(elems)} entries")
|
||||||
|
|
||||||
def do_remove_child_object(batch_val):
|
def do_remove_child_object(batch_val):
|
||||||
nonlocal remove_count
|
nonlocal remove_count
|
||||||
if child_objs_el is None:
|
if child_objs_el is None:
|
||||||
@@ -713,7 +929,7 @@ def main():
|
|||||||
if dot_idx < 1:
|
if dot_idx < 1:
|
||||||
print(f"Invalid format '{item}', expected 'Type.Name'", file=sys.stderr)
|
print(f"Invalid format '{item}', expected 'Type.Name'", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
type_name = item[:dot_idx]
|
type_name = resolve_type_name(item[:dot_idx]) or item[:dot_idx]
|
||||||
obj_name_val = item[dot_idx + 1:]
|
obj_name_val = item[dot_idx + 1:]
|
||||||
|
|
||||||
found = False
|
found = False
|
||||||
@@ -933,24 +1149,6 @@ def main():
|
|||||||
info(f"Wrote panel layout: {cai_path}")
|
info(f"Wrote panel layout: {cai_path}")
|
||||||
|
|
||||||
# --- set-home-page (writes Ext/HomePageWorkArea.xml from scratch) ---
|
# --- set-home-page (writes Ext/HomePageWorkArea.xml from scratch) ---
|
||||||
RU_TYPE_MAP = {
|
|
||||||
"справочник": "Catalog", "документ": "Document", "перечисление": "Enum",
|
|
||||||
"отчёт": "Report", "отчет": "Report", "обработка": "DataProcessor",
|
|
||||||
"общаяформа": "CommonForm", "журналдокументов": "DocumentJournal",
|
|
||||||
"планвидовхарактеристик": "ChartOfCharacteristicTypes",
|
|
||||||
"плансчетов": "ChartOfAccounts",
|
|
||||||
"планвидоврасчета": "ChartOfCalculationTypes",
|
|
||||||
"планвидоврасчёта": "ChartOfCalculationTypes",
|
|
||||||
"регистрсведений": "InformationRegister",
|
|
||||||
"регистрнакопления": "AccumulationRegister",
|
|
||||||
"регистрбухгалтерии": "AccountingRegister",
|
|
||||||
"регистррасчета": "CalculationRegister",
|
|
||||||
"регистррасчёта": "CalculationRegister",
|
|
||||||
"бизнеспроцесс": "BusinessProcess",
|
|
||||||
"бот": "Bot",
|
|
||||||
"задача": "Task", "планобмена": "ExchangePlan",
|
|
||||||
"хранилищенастроек": "SettingsStorage",
|
|
||||||
}
|
|
||||||
DIR_TO_TYPE = {v.lower(): k for k, v in TYPE_TO_DIR.items()}
|
DIR_TO_TYPE = {v.lower(): k for k, v in TYPE_TO_DIR.items()}
|
||||||
UUID_RE = __import__("re").compile(r"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$")
|
UUID_RE = __import__("re").compile(r"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$")
|
||||||
|
|
||||||
@@ -1130,6 +1328,8 @@ def main():
|
|||||||
do_set_panels(op_value)
|
do_set_panels(op_value)
|
||||||
elif op_key == "set-home-page":
|
elif op_key == "set-home-page":
|
||||||
do_set_home_page(op_value)
|
do_set_home_page(op_value)
|
||||||
|
elif op_key == "sort-childobjects":
|
||||||
|
do_sort_child_objects(op_value if isinstance(op_value, str) else str(op_value))
|
||||||
else:
|
else:
|
||||||
print(f"Unknown operation: {op_name}", file=sys.stderr)
|
print(f"Unknown operation: {op_name}", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@@ -23,7 +23,7 @@ allowed-tools:
|
|||||||
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-info.ps1" -ConfigPath "<путь>"
|
powershell.exe -NoProfile -File ".augment/skills/cf-info/scripts/cf-info.ps1" -ConfigPath "<путь>"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Три режима
|
## Три режима
|
||||||
+4
-4
@@ -1,4 +1,4 @@
|
|||||||
# cf-info v1.7 — Compact summary of 1C configuration root
|
# cf-info v1.8 — Compact summary of 1C configuration root
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
[CmdletBinding(PositionalBinding=$false)]
|
[CmdletBinding(PositionalBinding=$false)]
|
||||||
param(
|
param(
|
||||||
@@ -86,14 +86,14 @@ function Get-PropML([string]$propName) {
|
|||||||
return (Get-MLText $n)
|
return (Get-MLText $n)
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Type name maps (canonical order, 44 types) ---
|
# --- Type name maps (canonical order, 46 types) ---
|
||||||
$typeOrder = @(
|
$typeOrder = @(
|
||||||
"Language","Subsystem","StyleItem","Style",
|
"Language","Subsystem","StyleItem","Style",
|
||||||
"CommonPicture","SessionParameter","Role","CommonTemplate",
|
"CommonPicture","SessionParameter","Role","CommonTemplate",
|
||||||
"FilterCriterion","CommonModule","Bot","CommonAttribute","ExchangePlan",
|
"FilterCriterion","CommonModule","CommonAttribute","ExchangePlan",
|
||||||
"XDTOPackage","WebService","HTTPService","WSReference",
|
"XDTOPackage","WebService","HTTPService","WSReference",
|
||||||
"EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption",
|
"EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption",
|
||||||
"FunctionalOptionsParameter","DefinedType","CommonCommand","CommandGroup",
|
"FunctionalOptionsParameter","DefinedType","Bot","PaletteColor","CommonCommand","CommandGroup",
|
||||||
"Constant","CommonForm","Catalog","Document",
|
"Constant","CommonForm","Catalog","Document",
|
||||||
"DocumentNumerator","Sequence","DocumentJournal","Enum",
|
"DocumentNumerator","Sequence","DocumentJournal","Enum",
|
||||||
"Report","DataProcessor","InformationRegister","AccumulationRegister",
|
"Report","DataProcessor","InformationRegister","AccumulationRegister",
|
||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# cf-info v1.7 — Compact summary of 1C configuration root
|
# cf-info v1.8 — Compact summary of 1C configuration root
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -113,14 +113,14 @@ def get_prop_ml(prop_name):
|
|||||||
n = props_node.find(f"md:{prop_name}", NS)
|
n = props_node.find(f"md:{prop_name}", NS)
|
||||||
return get_ml_text(n)
|
return get_ml_text(n)
|
||||||
|
|
||||||
# --- Type name maps (canonical order, 44 types) ---
|
# --- Type name maps (canonical order, 46 types) ---
|
||||||
type_order = [
|
type_order = [
|
||||||
"Language", "Subsystem", "StyleItem", "Style",
|
"Language", "Subsystem", "StyleItem", "Style",
|
||||||
"CommonPicture", "SessionParameter", "Role", "CommonTemplate",
|
"CommonPicture", "SessionParameter", "Role", "CommonTemplate",
|
||||||
"FilterCriterion", "CommonModule", "Bot", "CommonAttribute", "ExchangePlan",
|
"FilterCriterion", "CommonModule", "CommonAttribute", "ExchangePlan",
|
||||||
"XDTOPackage", "WebService", "HTTPService", "WSReference",
|
"XDTOPackage", "WebService", "HTTPService", "WSReference",
|
||||||
"EventSubscription", "ScheduledJob", "SettingsStorage", "FunctionalOption",
|
"EventSubscription", "ScheduledJob", "SettingsStorage", "FunctionalOption",
|
||||||
"FunctionalOptionsParameter", "DefinedType", "CommonCommand", "CommandGroup",
|
"FunctionalOptionsParameter", "DefinedType", "Bot", "PaletteColor", "CommonCommand", "CommandGroup",
|
||||||
"Constant", "CommonForm", "Catalog", "Document",
|
"Constant", "CommonForm", "Catalog", "Document",
|
||||||
"DocumentNumerator", "Sequence", "DocumentJournal", "Enum",
|
"DocumentNumerator", "Sequence", "DocumentJournal", "Enum",
|
||||||
"Report", "DataProcessor", "InformationRegister", "AccumulationRegister",
|
"Report", "DataProcessor", "InformationRegister", "AccumulationRegister",
|
||||||
@@ -39,7 +39,7 @@ allowed-tools:
|
|||||||
не будет.
|
не будет.
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-init.ps1" -Name "МояКонфигурация"
|
powershell.exe -NoProfile -File ".augment/skills/cf-init/scripts/cf-init.ps1" -Name "МояКонфигурация"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
@@ -24,6 +24,6 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty"
|
powershell.exe -NoProfile -File ".augment/skills/cf-validate/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty"
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty/Configuration.xml"
|
powershell.exe -NoProfile -File ".augment/skills/cf-validate/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty/Configuration.xml"
|
||||||
```
|
```
|
||||||
+4
-3
@@ -1,4 +1,4 @@
|
|||||||
# cf-validate v1.8 — Validate 1C configuration root structure
|
# cf-validate v1.9 — Validate 1C configuration root structure
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
[CmdletBinding(PositionalBinding=$false)]
|
[CmdletBinding(PositionalBinding=$false)]
|
||||||
param(
|
param(
|
||||||
@@ -122,10 +122,10 @@ $validClassIds = @(
|
|||||||
$childObjectTypes = @(
|
$childObjectTypes = @(
|
||||||
"Language","Subsystem","StyleItem","Style",
|
"Language","Subsystem","StyleItem","Style",
|
||||||
"CommonPicture","SessionParameter","Role","CommonTemplate",
|
"CommonPicture","SessionParameter","Role","CommonTemplate",
|
||||||
"FilterCriterion","CommonModule","Bot","CommonAttribute","ExchangePlan",
|
"FilterCriterion","CommonModule","CommonAttribute","ExchangePlan",
|
||||||
"XDTOPackage","WebService","HTTPService","WSReference",
|
"XDTOPackage","WebService","HTTPService","WSReference",
|
||||||
"EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption",
|
"EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption",
|
||||||
"FunctionalOptionsParameter","DefinedType","CommonCommand","CommandGroup",
|
"FunctionalOptionsParameter","DefinedType","Bot","PaletteColor","CommonCommand","CommandGroup",
|
||||||
"Constant","CommonForm","Catalog","Document",
|
"Constant","CommonForm","Catalog","Document",
|
||||||
"DocumentNumerator","Sequence","DocumentJournal","Enum",
|
"DocumentNumerator","Sequence","DocumentJournal","Enum",
|
||||||
"Report","DataProcessor","InformationRegister","AccumulationRegister",
|
"Report","DataProcessor","InformationRegister","AccumulationRegister",
|
||||||
@@ -140,6 +140,7 @@ $childTypeDirMap = @{
|
|||||||
"CommonPicture"="CommonPictures"; "SessionParameter"="SessionParameters"; "Role"="Roles"
|
"CommonPicture"="CommonPictures"; "SessionParameter"="SessionParameters"; "Role"="Roles"
|
||||||
"CommonTemplate"="CommonTemplates"; "FilterCriterion"="FilterCriteria"; "CommonModule"="CommonModules"
|
"CommonTemplate"="CommonTemplates"; "FilterCriterion"="FilterCriteria"; "CommonModule"="CommonModules"
|
||||||
"Bot"="Bots"
|
"Bot"="Bots"
|
||||||
|
"PaletteColor"="PaletteColors"
|
||||||
"CommonAttribute"="CommonAttributes"; "ExchangePlan"="ExchangePlans"; "XDTOPackage"="XDTOPackages"
|
"CommonAttribute"="CommonAttributes"; "ExchangePlan"="ExchangePlans"; "XDTOPackage"="XDTOPackages"
|
||||||
"WebService"="WebServices"; "HTTPService"="HTTPServices"; "WSReference"="WSReferences"
|
"WebService"="WebServices"; "HTTPService"="HTTPServices"; "WSReference"="WSReferences"
|
||||||
"EventSubscription"="EventSubscriptions"; "ScheduledJob"="ScheduledJobs"
|
"EventSubscription"="EventSubscriptions"; "ScheduledJob"="ScheduledJobs"
|
||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# cf-validate v1.8 — Validate 1C configuration XML structure
|
# cf-validate v1.9 — Validate 1C configuration XML structure
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
"""Validates Configuration.xml: root structure, InternalInfo, properties, ChildObjects, languages."""
|
"""Validates Configuration.xml: root structure, InternalInfo, properties, ChildObjects, languages."""
|
||||||
import sys, os, argparse, re
|
import sys, os, argparse, re
|
||||||
@@ -59,10 +59,10 @@ VALID_CLASS_IDS = [
|
|||||||
CHILD_OBJECT_TYPES = [
|
CHILD_OBJECT_TYPES = [
|
||||||
'Language', 'Subsystem', 'StyleItem', 'Style',
|
'Language', 'Subsystem', 'StyleItem', 'Style',
|
||||||
'CommonPicture', 'SessionParameter', 'Role', 'CommonTemplate',
|
'CommonPicture', 'SessionParameter', 'Role', 'CommonTemplate',
|
||||||
'FilterCriterion', 'CommonModule', 'Bot', 'CommonAttribute', 'ExchangePlan',
|
'FilterCriterion', 'CommonModule', 'CommonAttribute', 'ExchangePlan',
|
||||||
'XDTOPackage', 'WebService', 'HTTPService', 'WSReference',
|
'XDTOPackage', 'WebService', 'HTTPService', 'WSReference',
|
||||||
'EventSubscription', 'ScheduledJob', 'SettingsStorage', 'FunctionalOption',
|
'EventSubscription', 'ScheduledJob', 'SettingsStorage', 'FunctionalOption',
|
||||||
'FunctionalOptionsParameter', 'DefinedType', 'CommonCommand', 'CommandGroup',
|
'FunctionalOptionsParameter', 'DefinedType', 'Bot', 'PaletteColor', 'CommonCommand', 'CommandGroup',
|
||||||
'Constant', 'CommonForm', 'Catalog', 'Document',
|
'Constant', 'CommonForm', 'Catalog', 'Document',
|
||||||
'DocumentNumerator', 'Sequence', 'DocumentJournal', 'Enum',
|
'DocumentNumerator', 'Sequence', 'DocumentJournal', 'Enum',
|
||||||
'Report', 'DataProcessor', 'InformationRegister', 'AccumulationRegister',
|
'Report', 'DataProcessor', 'InformationRegister', 'AccumulationRegister',
|
||||||
@@ -76,7 +76,7 @@ CHILD_TYPE_DIR_MAP = {
|
|||||||
'Language': 'Languages', 'Subsystem': 'Subsystems', 'StyleItem': 'StyleItems', 'Style': 'Styles',
|
'Language': 'Languages', 'Subsystem': 'Subsystems', 'StyleItem': 'StyleItems', 'Style': 'Styles',
|
||||||
'CommonPicture': 'CommonPictures', 'SessionParameter': 'SessionParameters', 'Role': 'Roles',
|
'CommonPicture': 'CommonPictures', 'SessionParameter': 'SessionParameters', 'Role': 'Roles',
|
||||||
'CommonTemplate': 'CommonTemplates', 'FilterCriterion': 'FilterCriteria', 'CommonModule': 'CommonModules',
|
'CommonTemplate': 'CommonTemplates', 'FilterCriterion': 'FilterCriteria', 'CommonModule': 'CommonModules',
|
||||||
'Bot': 'Bots',
|
'Bot': 'Bots', 'PaletteColor': 'PaletteColors',
|
||||||
'CommonAttribute': 'CommonAttributes', 'ExchangePlan': 'ExchangePlans', 'XDTOPackage': 'XDTOPackages',
|
'CommonAttribute': 'CommonAttributes', 'ExchangePlan': 'ExchangePlans', 'XDTOPackage': 'XDTOPackages',
|
||||||
'WebService': 'WebServices', 'HTTPService': 'HTTPServices', 'WSReference': 'WSReferences',
|
'WebService': 'WebServices', 'HTTPService': 'HTTPServices', 'WSReference': 'WSReferences',
|
||||||
'EventSubscription': 'EventSubscriptions', 'ScheduledJob': 'ScheduledJobs',
|
'EventSubscription': 'EventSubscriptions', 'ScheduledJob': 'ScheduledJobs',
|
||||||
@@ -71,7 +71,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-borrow.ps1" -ExtensionPath src\cfe\extname -ConfigPath src\cf -Object "Catalog.Контрагенты"
|
powershell.exe -NoProfile -File ".augment/skills/cfe-borrow/scripts/cfe-borrow.ps1" -ExtensionPath src\cfe\extname -ConfigPath src\cf -Object "Catalog.Контрагенты"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
+155
-60
@@ -1,4 +1,4 @@
|
|||||||
# cfe-borrow v1.33 — Borrow objects from configuration into extension (CFE)
|
# cfe-borrow v1.36 — Borrow objects from configuration into extension (CFE)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
[CmdletBinding(PositionalBinding=$false)]
|
[CmdletBinding(PositionalBinding=$false)]
|
||||||
param(
|
param(
|
||||||
@@ -260,7 +260,7 @@ $childTypeDirMap = @{
|
|||||||
"Sequence"="Sequences"; "IntegrationService"="IntegrationServices"
|
"Sequence"="Sequences"; "IntegrationService"="IntegrationServices"
|
||||||
"XDTOPackage"="XDTOPackages"; "WebService"="WebServices"
|
"XDTOPackage"="XDTOPackages"; "WebService"="WebServices"
|
||||||
"HTTPService"="HTTPServices"; "WSReference"="WSReferences"
|
"HTTPService"="HTTPServices"; "WSReference"="WSReferences"
|
||||||
"CommonAttribute"="CommonAttributes"; "Style"="Styles"; "Bot"="Bots"; "Language"="Languages"
|
"CommonAttribute"="CommonAttributes"; "Style"="Styles"; "Bot"="Bots"; "PaletteColor"="PaletteColors"; "Language"="Languages"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 4a. Модули заимствованных объектов ---
|
# --- 4a. Модули заимствованных объектов ---
|
||||||
@@ -310,14 +310,14 @@ $synonymMap = @{
|
|||||||
"HTTPСервис"="HTTPService"; "СервисИнтеграции"="IntegrationService"
|
"HTTPСервис"="HTTPService"; "СервисИнтеграции"="IntegrationService"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- 5. Canonical type order (44 types) ---
|
# --- 5. Canonical type order (46 types) ---
|
||||||
$script:typeOrder = @(
|
$script:typeOrder = @(
|
||||||
"Language","Subsystem","StyleItem","Style",
|
"Language","Subsystem","StyleItem","Style",
|
||||||
"CommonPicture","SessionParameter","Role","CommonTemplate",
|
"CommonPicture","SessionParameter","Role","CommonTemplate",
|
||||||
"FilterCriterion","CommonModule","Bot","CommonAttribute","ExchangePlan",
|
"FilterCriterion","CommonModule","CommonAttribute","ExchangePlan",
|
||||||
"XDTOPackage","WebService","HTTPService","WSReference",
|
"XDTOPackage","WebService","HTTPService","WSReference",
|
||||||
"EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption",
|
"EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption",
|
||||||
"FunctionalOptionsParameter","DefinedType","CommonCommand","CommandGroup",
|
"FunctionalOptionsParameter","DefinedType","Bot","PaletteColor","CommonCommand","CommandGroup",
|
||||||
"Constant","CommonForm","Catalog","Document",
|
"Constant","CommonForm","Catalog","Document",
|
||||||
"DocumentNumerator","Sequence","DocumentJournal","Enum",
|
"DocumentNumerator","Sequence","DocumentJournal","Enum",
|
||||||
"Report","DataProcessor","InformationRegister","AccumulationRegister",
|
"Report","DataProcessor","InformationRegister","AccumulationRegister",
|
||||||
@@ -1347,32 +1347,22 @@ function Register-FormInObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Save object XML
|
# Save object XML
|
||||||
|
# Стиль исходника снимаем ДО записи: правка чужого файла наследует его BOM/EOL/заголовок
|
||||||
|
# (#44/#46/#47), новый файл получает канон выгрузки. Зеркало _detect_xml_style в py-порту.
|
||||||
|
$style2 = Detect-XmlStyle $objFile
|
||||||
$settings2 = New-Object System.Xml.XmlWriterSettings
|
$settings2 = New-Object System.Xml.XmlWriterSettings
|
||||||
$settings2.Encoding = New-Object System.Text.UTF8Encoding($true)
|
$settings2.Encoding = New-Object System.Text.UTF8Encoding($true)
|
||||||
$settings2.Indent = $false
|
$settings2.Indent = $false
|
||||||
$settings2.NewLineHandling = [System.Xml.NewLineHandling]::None
|
$settings2.NewLineHandling = [System.Xml.NewLineHandling]::None
|
||||||
|
|
||||||
$memStream2 = New-Object System.IO.MemoryStream
|
$memStream2 = New-Object System.IO.MemoryStream
|
||||||
$writer2 = [System.Xml.XmlWriter]::Create($memStream2, $settings2)
|
$writer2 = [System.Xml.XmlWriter]::Create($memStream2, $settings2)
|
||||||
$objDoc.Save($writer2)
|
$objDoc.Save($writer2)
|
||||||
$writer2.Flush(); $writer2.Close()
|
$writer2.Flush(); $writer2.Close()
|
||||||
|
$text2 = [System.Text.Encoding]::UTF8.GetString($memStream2.ToArray())
|
||||||
$bytes2 = $memStream2.ToArray()
|
|
||||||
$memStream2.Close()
|
$memStream2.Close()
|
||||||
$text2 = [System.Text.Encoding]::UTF8.GetString($bytes2)
|
$text2 = Finalize-XmlText $text2 $style2
|
||||||
if ($text2.Length -gt 0 -and $text2[0] -eq [char]0xFEFF) { $text2 = $text2.Substring(1) }
|
$writeBom2 = ($null -eq $style2) -or $style2.bom
|
||||||
$text2 = $text2.Replace('encoding="utf-8"', 'encoding="UTF-8"')
|
[System.IO.File]::WriteAllText($objFile, $text2, (New-Object System.Text.UTF8Encoding($writeBom2)))
|
||||||
# Пустой элемент: XmlWriter отдаёт `<a />`, Конфигуратор пишет `<a/>`. Внутри
|
|
||||||
# CDATA/комментария ` />` может быть содержимым (там `>` не экранируется),
|
|
||||||
# поэтому они идут первыми ветками альтернации и возвращаются как есть.
|
|
||||||
$text2 = [regex]::Replace($text2, '(?s)<!\[CDATA\[.*?\]\]>|<!--.*?-->|(?<=\S) />', { param($m) if ($m.Value -eq ' />') { '/>' } else { $m.Value } })
|
|
||||||
|
|
||||||
$utf8Bom2 = New-Object System.Text.UTF8Encoding($true)
|
|
||||||
# Целевой перевод строки: стиль файла-назначения — правка наследует его (#44/#46/#47),
|
|
||||||
# новый файл получает канон выгрузки CRLF. Зеркало _detect_xml_style в py-порту.
|
|
||||||
$targetEol = if ((Test-Path -LiteralPath $objFile) -and ([System.IO.File]::ReadAllText($objFile) -notmatch "`r`n")) { "`n" } else { "`r`n" }
|
|
||||||
$text2 = ($text2 -replace "`r`n", "`n") -replace "`n", $targetEol
|
|
||||||
[System.IO.File]::WriteAllText($objFile, $text2, $utf8Bom2)
|
|
||||||
Info " Registered form in: $objFile"
|
Info " Registered form in: $objFile"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1885,6 +1875,9 @@ function Merge-AttributesIntoObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Save via text manipulation to avoid namespace issues with InnerXml
|
# Save via text manipulation to avoid namespace issues with InnerXml
|
||||||
|
# Стиль исходника снимаем ДО записи: правка чужого файла наследует его BOM/EOL/заголовок
|
||||||
|
# (#44/#46/#47), новый файл получает канон выгрузки. Зеркало _detect_xml_style в py-порту.
|
||||||
|
$style3 = Detect-XmlStyle $objFile
|
||||||
$settings3 = New-Object System.Xml.XmlWriterSettings
|
$settings3 = New-Object System.Xml.XmlWriterSettings
|
||||||
$settings3.Encoding = New-Object System.Text.UTF8Encoding($true)
|
$settings3.Encoding = New-Object System.Text.UTF8Encoding($true)
|
||||||
$settings3.Indent = $false
|
$settings3.Indent = $false
|
||||||
@@ -1893,28 +1886,15 @@ function Merge-AttributesIntoObject {
|
|||||||
$writer3 = [System.Xml.XmlWriter]::Create($memStream3, $settings3)
|
$writer3 = [System.Xml.XmlWriter]::Create($memStream3, $settings3)
|
||||||
$objDoc.Save($writer3)
|
$objDoc.Save($writer3)
|
||||||
$writer3.Flush(); $writer3.Close()
|
$writer3.Flush(); $writer3.Close()
|
||||||
$bytes3 = $memStream3.ToArray()
|
$text3 = [System.Text.Encoding]::UTF8.GetString($memStream3.ToArray())
|
||||||
$memStream3.Close()
|
$memStream3.Close()
|
||||||
$text3 = [System.Text.Encoding]::UTF8.GetString($bytes3)
|
|
||||||
if ($text3.Length -gt 0 -and $text3[0] -eq [char]0xFEFF) { $text3 = $text3.Substring(1) }
|
|
||||||
$text3 = $text3.Replace('encoding="utf-8"', 'encoding="UTF-8"')
|
|
||||||
|
|
||||||
# Самозакрытый элемент раскрывается текстом, а не пробельным узлом в DOM: тот давал
|
# Самозакрытый элемент раскрывается текстом, а не пробельным узлом в DOM: тот давал
|
||||||
# лишнюю строку с табуляцией перед первым <Attribute> (у Конфигуратора пустых строк нет).
|
# лишнюю строку с табуляцией перед первым <Attribute> (у Конфигуратора пустых строк нет).
|
||||||
|
# Стоит ДО Finalize-XmlText, чтобы схлопывание пустых тегов накрыло и вставленные реквизиты.
|
||||||
$text3 = Insert-IntoOwnChildObjects $text3 $allAttrXml
|
$text3 = Insert-IntoOwnChildObjects $text3 $allAttrXml
|
||||||
|
$text3 = Finalize-XmlText $text3 $style3
|
||||||
# Пустой элемент: XmlWriter отдаёт `<a />`, Конфигуратор пишет `<a/>`. Внутри
|
$writeBom3 = ($null -eq $style3) -or $style3.bom
|
||||||
# CDATA/комментария ` />` может быть содержимым (там `>` не экранируется),
|
[System.IO.File]::WriteAllText($objFile, $text3, (New-Object System.Text.UTF8Encoding($writeBom3)))
|
||||||
# поэтому они идут первыми ветками альтернации и возвращаются как есть.
|
|
||||||
# Стоит ПОСЛЕ вставки реквизитов, чтобы накрыть и их.
|
|
||||||
$text3 = [regex]::Replace($text3, '(?s)<!\[CDATA\[.*?\]\]>|<!--.*?-->|(?<=\S) />', { param($m) if ($m.Value -eq ' />') { '/>' } else { $m.Value } })
|
|
||||||
|
|
||||||
$utf8Bom3 = New-Object System.Text.UTF8Encoding($true)
|
|
||||||
# Целевой перевод строки: стиль файла-назначения — правка наследует его (#44/#46/#47),
|
|
||||||
# новый файл получает канон выгрузки CRLF. Зеркало _detect_xml_style в py-порту.
|
|
||||||
$targetEol = if ((Test-Path -LiteralPath $objFile) -and ([System.IO.File]::ReadAllText($objFile) -notmatch "`r`n")) { "`n" } else { "`r`n" }
|
|
||||||
$text3 = ($text3 -replace "`r`n", "`n") -replace "`n", $targetEol
|
|
||||||
[System.IO.File]::WriteAllText($objFile, $text3, $utf8Bom3)
|
|
||||||
Info " Merged $added attribute(s) into: $objFile"
|
Info " Merged $added attribute(s) into: $objFile"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2230,6 +2210,127 @@ function Build-BorrowedObjectXml {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# --- 13. Helper: add object to extension ChildObjects ---
|
# --- 13. Helper: add object to extension ChildObjects ---
|
||||||
|
# Стиль существующего файла для round-trip-сохранения: BOM / EOL / регистр encoding /
|
||||||
|
# финальный перенос. $null → файл новый (сохранить текущее поведение).
|
||||||
|
# Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
function Detect-XmlStyle([string]$path) {
|
||||||
|
if (-not (Test-Path -LiteralPath $path)) { return $null }
|
||||||
|
$raw = [System.IO.File]::ReadAllBytes($path)
|
||||||
|
$bom = ($raw.Length -ge 3 -and $raw[0] -eq 0xEF -and $raw[1] -eq 0xBB -and $raw[2] -eq 0xBF)
|
||||||
|
$body = if ($bom) { [System.Text.Encoding]::UTF8.GetString($raw, 3, $raw.Length - 3) } else { [System.Text.Encoding]::UTF8.GetString($raw) }
|
||||||
|
$head = if ($body.Length -gt 200) { $body.Substring(0, 200) } else { $body }
|
||||||
|
$m = [regex]::Match($head, 'encoding="([^"]+)"')
|
||||||
|
return @{
|
||||||
|
bom = $bom
|
||||||
|
crlf = $body.Contains("`r`n")
|
||||||
|
enc = $(if ($m.Success) { $m.Groups[1].Value } else { "utf-8" })
|
||||||
|
finalNl = $body.EndsWith("`n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Привести текст XmlWriter к стилю оригинала; для НОВОГО файла ($null) — к канону выгрузки
|
||||||
|
# Конфигуратора: encoding="UTF-8", CRLF, без перевода строки в конце.
|
||||||
|
# Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
function Finalize-XmlText([string]$text, $style) {
|
||||||
|
if ($text.Length -gt 0 -and $text[0] -eq [char]0xFEFF) { $text = $text.Substring(1) }
|
||||||
|
$encDecl = $(if ($style) { $style.enc } else { "UTF-8" })
|
||||||
|
$text = $text.Replace('encoding="utf-8"', 'encoding="' + $encDecl + '"')
|
||||||
|
# Пустой элемент: XmlWriter отдаёт `<a />`, Конфигуратор пишет `<a/>`. Внутри
|
||||||
|
# CDATA/комментария ` />` может быть содержимым (там `>` не экранируется),
|
||||||
|
# поэтому они идут первыми ветками альтернации и возвращаются как есть.
|
||||||
|
$text = [regex]::Replace($text, '(?s)<!\[CDATA\[.*?\]\]>|<!--.*?-->|(?<=\S) />', { param($m) if ($m.Value -eq ' />') { '/>' } else { $m.Value } })
|
||||||
|
$text = ($text -replace "`r`n", "`n").TrimEnd("`n")
|
||||||
|
if ($style -and $style.finalNl) { $text += "`n" }
|
||||||
|
if (-not $style -or $style.crlf) { $text = $text -replace "`n", "`r`n" }
|
||||||
|
return $text
|
||||||
|
}
|
||||||
|
|
||||||
|
function Find-V8Project([string]$startDir) {
|
||||||
|
$d = $startDir
|
||||||
|
for ($i = 0; $i -lt 20 -and $d; $i++) {
|
||||||
|
$pj = Join-Path $d ".v8-project.json"
|
||||||
|
if (Test-Path $pj) { return $pj }
|
||||||
|
$parent = [System.IO.Path]::GetDirectoryName($d)
|
||||||
|
if ($parent -eq $d) { break }
|
||||||
|
$d = $parent
|
||||||
|
}
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Куда навык ставит новую запись в <ChildObjects> — настройка newObjectPosition.
|
||||||
|
# databases[].newObjectPosition базы, чей configSrc охватывает каталог родительского XML,
|
||||||
|
# иначе корневое поле, иначе end. Значения: end — после последнего объекта того же вида
|
||||||
|
# (так дописывает Конфигуратор); byName — по имени среди объектов того же вида.
|
||||||
|
# Файл ищем от рабочего каталога вверх, каталог конфигурации — запасной путь: так же
|
||||||
|
# его ищут support-guard и группа db-*, а скрипт навыка зовут по абсолютному пути, и cwd
|
||||||
|
# остаётся рабочим каталогом проекта.
|
||||||
|
# configSrc считается от каталога .v8-project.json, как задокументировано в
|
||||||
|
# docs/v8-project-guide.md. Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
function Get-NewObjectPosition([string]$cfgDir) {
|
||||||
|
try {
|
||||||
|
if (-not $cfgDir) { $cfgDir = "." }
|
||||||
|
$pj = Find-V8Project (Get-Location).Path
|
||||||
|
if (-not $pj) { $pj = Find-V8Project ([System.IO.Path]::GetFullPath($cfgDir)) }
|
||||||
|
if (-not $pj) { return "end" }
|
||||||
|
$proj = Get-Content -Raw $pj | ConvertFrom-Json
|
||||||
|
$projDir = [System.IO.Path]::GetDirectoryName($pj)
|
||||||
|
$cfgFull = [System.IO.Path]::GetFullPath($cfgDir).TrimEnd('\', '/')
|
||||||
|
if ($proj.databases) {
|
||||||
|
foreach ($db in $proj.databases) {
|
||||||
|
if ($db.configSrc -and $db.newObjectPosition) {
|
||||||
|
$src = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($projDir, $db.configSrc)).TrimEnd('\', '/')
|
||||||
|
if ($cfgFull -eq $src -or $cfgFull.StartsWith($src + [System.IO.Path]::DirectorySeparatorChar)) {
|
||||||
|
if ("$($db.newObjectPosition)" -eq "byName") { return "byName" }
|
||||||
|
return "end"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("$($proj.newObjectPosition)" -eq "byName") { return "byName" }
|
||||||
|
return "end"
|
||||||
|
} catch { return "end" }
|
||||||
|
}
|
||||||
|
|
||||||
|
# Виды, у которых порядок в дереве несёт смысл: автоматически их не упорядочиваем.
|
||||||
|
# CommonAttribute — исключение самого стандарта (#std467): у общих реквизитов-разделителей
|
||||||
|
# порядок в дереве задаёт порядок установки параметров сеанса. Subsystem и CommandGroup:
|
||||||
|
# пока они не перечислены в <SubsystemsOrder> / <GroupsOrder> файла Ext/CommandInterface.xml,
|
||||||
|
# порядок дерева задаёт порядок в интерфейсе, а платформа эти списки сама не заводит
|
||||||
|
# (в выгрузке ACC вне GroupsOrder 15 живых групп из 39). Language исключён из осторожности,
|
||||||
|
# без замера: языков обычно один-два, и в типовых их порядок не алфавитный.
|
||||||
|
# Явно названный вид сортируется в любом случае.
|
||||||
|
# Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
function Test-OrderSensitiveType([string]$typeName) {
|
||||||
|
return @("CommonAttribute", "Subsystem", "CommandGroup", "Language") -ccontains $typeName
|
||||||
|
}
|
||||||
|
|
||||||
|
# Порядок имён объектов метаданных, как в дереве Конфигуратора.
|
||||||
|
# Ключ — пары «ранг+символ»: регистр не учитывается, подчёркивание раньше цифр, цифры раньше
|
||||||
|
# букв, буквы по кодам (латиница раньше кириллицы), ё на месте е. Культурные таблицы не
|
||||||
|
# используются — они разные на разных ОС и в разных рантаймах, а так оба порта сравнивают
|
||||||
|
# одинаково везде. Равные ключи разводит ordinal-сравнение исходных строк.
|
||||||
|
# Возвращает -1 | 0 | 1. Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
function Compare-MetadataNames([string]$a, [string]$b) {
|
||||||
|
$keys = @("", "")
|
||||||
|
$names = @($a, $b)
|
||||||
|
for ($i = 0; $i -lt 2; $i++) {
|
||||||
|
$sb = New-Object System.Text.StringBuilder
|
||||||
|
foreach ($ch in $names[$i].ToLowerInvariant().ToCharArray()) {
|
||||||
|
if ($ch -eq [char]0x0451) { $ch = [char]0x0435 }
|
||||||
|
if ([char]::IsDigit($ch)) { [void]$sb.Append('1') }
|
||||||
|
elseif ([char]::IsLetter($ch)) { [void]$sb.Append('2') }
|
||||||
|
else { [void]$sb.Append('0') }
|
||||||
|
[void]$sb.Append($ch)
|
||||||
|
}
|
||||||
|
$keys[$i] = $sb.ToString()
|
||||||
|
}
|
||||||
|
$r = [string]::CompareOrdinal($keys[0], $keys[1])
|
||||||
|
if ($r -eq 0) { $r = [string]::CompareOrdinal($a, $b) }
|
||||||
|
if ($r -lt 0) { return -1 }
|
||||||
|
if ($r -gt 0) { return 1 }
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
function Add-ToChildObjects {
|
function Add-ToChildObjects {
|
||||||
param([string]$typeName, [string]$objName)
|
param([string]$typeName, [string]$objName)
|
||||||
|
|
||||||
@@ -2255,7 +2356,12 @@ function Add-ToChildObjects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Find insertion point: after last element of same type, or before first element of later type
|
# Место вставки. Вид — по $script:typeOrder; внутри вида — по newObjectPosition: end
|
||||||
|
# (по умолчанию) кладёт после последнего объекта того же вида, byName — по имени. Так же
|
||||||
|
# заимствует Конфигуратор: в боевых выгрузках расширений ChildObjects не отсортирован.
|
||||||
|
# Subsystem по имени не упорядочиваем никогда: порядок подсистем в дереве задаёт порядок
|
||||||
|
# разделов в панели.
|
||||||
|
$byName = (-not (Test-OrderSensitiveType $typeName) -and (Get-NewObjectPosition $extDir) -eq "byName")
|
||||||
$insertBefore = $null
|
$insertBefore = $null
|
||||||
$lastSameType = $null
|
$lastSameType = $null
|
||||||
|
|
||||||
@@ -2265,8 +2371,7 @@ function Add-ToChildObjects {
|
|||||||
if ($childTypeIdx -lt 0) { continue }
|
if ($childTypeIdx -lt 0) { continue }
|
||||||
|
|
||||||
if ($child.LocalName -eq $typeName) {
|
if ($child.LocalName -eq $typeName) {
|
||||||
# Same type -- check alphabetical order
|
if ($byName -and -not $insertBefore -and (Compare-MetadataNames $child.InnerText $objName) -gt 0) {
|
||||||
if ($child.InnerText -gt $objName -and -not $insertBefore) {
|
|
||||||
$insertBefore = $child
|
$insertBefore = $child
|
||||||
}
|
}
|
||||||
$lastSameType = $child
|
$lastSameType = $child
|
||||||
@@ -2439,32 +2544,22 @@ while ($true) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# --- 15. Save modified Configuration.xml ---
|
# --- 15. Save modified Configuration.xml ---
|
||||||
|
# Стиль исходника снимаем ДО записи: правка чужого файла наследует его BOM/EOL/заголовок
|
||||||
|
# (#44/#46/#47), новый файл получает канон выгрузки. Зеркало _detect_xml_style в py-порту.
|
||||||
|
$style = Detect-XmlStyle $extResolvedPath
|
||||||
$settings = New-Object System.Xml.XmlWriterSettings
|
$settings = New-Object System.Xml.XmlWriterSettings
|
||||||
$settings.Encoding = New-Object System.Text.UTF8Encoding($true)
|
$settings.Encoding = New-Object System.Text.UTF8Encoding($true)
|
||||||
$settings.Indent = $false
|
$settings.Indent = $false
|
||||||
$settings.NewLineHandling = [System.Xml.NewLineHandling]::None
|
$settings.NewLineHandling = [System.Xml.NewLineHandling]::None
|
||||||
|
|
||||||
$memStream = New-Object System.IO.MemoryStream
|
$memStream = New-Object System.IO.MemoryStream
|
||||||
$writer = [System.Xml.XmlWriter]::Create($memStream, $settings)
|
$writer = [System.Xml.XmlWriter]::Create($memStream, $settings)
|
||||||
$script:xmlDoc.Save($writer)
|
$script:xmlDoc.Save($writer)
|
||||||
$writer.Flush(); $writer.Close()
|
$writer.Flush(); $writer.Close()
|
||||||
|
$text = [System.Text.Encoding]::UTF8.GetString($memStream.ToArray())
|
||||||
$bytes = $memStream.ToArray()
|
|
||||||
$memStream.Close()
|
$memStream.Close()
|
||||||
$text = [System.Text.Encoding]::UTF8.GetString($bytes)
|
$text = Finalize-XmlText $text $style
|
||||||
if ($text.Length -gt 0 -and $text[0] -eq [char]0xFEFF) { $text = $text.Substring(1) }
|
$writeBom = ($null -eq $style) -or $style.bom
|
||||||
$text = $text.Replace('encoding="utf-8"', 'encoding="UTF-8"')
|
[System.IO.File]::WriteAllText($extResolvedPath, $text, (New-Object System.Text.UTF8Encoding($writeBom)))
|
||||||
# Пустой элемент: XmlWriter отдаёт `<a />`, Конфигуратор пишет `<a/>`. Внутри
|
|
||||||
# CDATA/комментария ` />` может быть содержимым (там `>` не экранируется),
|
|
||||||
# поэтому они идут первыми ветками альтернации и возвращаются как есть.
|
|
||||||
$text = [regex]::Replace($text, '(?s)<!\[CDATA\[.*?\]\]>|<!--.*?-->|(?<=\S) />', { param($m) if ($m.Value -eq ' />') { '/>' } else { $m.Value } })
|
|
||||||
|
|
||||||
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
|
||||||
# Целевой перевод строки: стиль файла-назначения — правка наследует его (#44/#46/#47),
|
|
||||||
# новый файл получает канон выгрузки CRLF. Зеркало _detect_xml_style в py-порту.
|
|
||||||
$targetEol = if ((Test-Path -LiteralPath $extResolvedPath) -and ([System.IO.File]::ReadAllText($extResolvedPath) -notmatch "`r`n")) { "`n" } else { "`r`n" }
|
|
||||||
$text = ($text -replace "`r`n", "`n") -replace "`n", $targetEol
|
|
||||||
[System.IO.File]::WriteAllText($extResolvedPath, $text, $utf8Bom)
|
|
||||||
Info "Saved: $extResolvedPath"
|
Info "Saved: $extResolvedPath"
|
||||||
|
|
||||||
# --- 16. Summary ---
|
# --- 16. Summary ---
|
||||||
+105
-5
@@ -1,8 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# cfe-borrow v1.33 — Borrow objects from configuration into extension (CFE)
|
# cfe-borrow v1.36 — Borrow objects from configuration into extension (CFE)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
@@ -202,6 +203,97 @@ def decode_numeric_entities(s):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def _sg_find_v8project(start_dir):
|
||||||
|
d = start_dir
|
||||||
|
for _ in range(20):
|
||||||
|
if not d:
|
||||||
|
break
|
||||||
|
pj = os.path.join(d, ".v8-project.json")
|
||||||
|
if os.path.isfile(pj):
|
||||||
|
return pj
|
||||||
|
parent = os.path.dirname(d)
|
||||||
|
if parent == d:
|
||||||
|
break
|
||||||
|
d = parent
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_new_object_position(cfg_dir):
|
||||||
|
"""Куда навык ставит новую запись в <ChildObjects> — настройка newObjectPosition.
|
||||||
|
|
||||||
|
databases[].newObjectPosition базы, чей configSrc охватывает каталог родительского XML,
|
||||||
|
иначе корневое поле, иначе end. Значения: end — после последнего объекта того же вида
|
||||||
|
(так дописывает Конфигуратор); byName — по имени среди объектов того же вида.
|
||||||
|
Файл ищем от рабочего каталога вверх, каталог конфигурации — запасной путь: так же
|
||||||
|
его ищут support-guard и группа db-*, а скрипт навыка зовут по абсолютному пути, и cwd
|
||||||
|
остаётся рабочим каталогом проекта.
|
||||||
|
configSrc считается от каталога .v8-project.json, как задокументировано в
|
||||||
|
docs/v8-project-guide.md. Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
pj = _sg_find_v8project(os.getcwd()) or _sg_find_v8project(os.path.abspath(cfg_dir or "."))
|
||||||
|
if not pj:
|
||||||
|
return "end"
|
||||||
|
proj = json.loads(open(pj, encoding="utf-8-sig").read())
|
||||||
|
proj_dir = os.path.dirname(pj)
|
||||||
|
cfg_full = os.path.normcase(os.path.abspath(cfg_dir or ".")).rstrip("\\/")
|
||||||
|
for db in proj.get("databases", []):
|
||||||
|
src = db.get("configSrc")
|
||||||
|
if src and db.get("newObjectPosition"):
|
||||||
|
src_full = os.path.normcase(os.path.abspath(os.path.join(proj_dir, src))).rstrip("\\/")
|
||||||
|
if cfg_full == src_full or cfg_full.startswith(src_full + os.sep):
|
||||||
|
return "byName" if str(db["newObjectPosition"]).lower() == "byname" else "end"
|
||||||
|
if str(proj.get("newObjectPosition") or "").lower() == "byname":
|
||||||
|
return "byName"
|
||||||
|
return "end"
|
||||||
|
except Exception:
|
||||||
|
return "end"
|
||||||
|
|
||||||
|
|
||||||
|
def is_order_sensitive_type(type_name):
|
||||||
|
"""Виды, у которых порядок в дереве несёт смысл: автоматически их не упорядочиваем.
|
||||||
|
|
||||||
|
CommonAttribute — исключение самого стандарта (#std467): у общих реквизитов-разделителей
|
||||||
|
порядок в дереве задаёт порядок установки параметров сеанса. Subsystem и CommandGroup:
|
||||||
|
пока они не перечислены в <SubsystemsOrder> / <GroupsOrder> файла Ext/CommandInterface.xml,
|
||||||
|
порядок дерева задаёт порядок в интерфейсе, а платформа эти списки сама не заводит
|
||||||
|
(в выгрузке ACC вне GroupsOrder 15 живых групп из 39). Language исключён из осторожности,
|
||||||
|
без замера: языков обычно один-два, и в типовых их порядок не алфавитный.
|
||||||
|
Явно названный вид сортируется в любом случае.
|
||||||
|
Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
"""
|
||||||
|
return type_name in ("CommonAttribute", "Subsystem", "CommandGroup", "Language")
|
||||||
|
|
||||||
|
|
||||||
|
def compare_metadata_names(a, b):
|
||||||
|
"""Порядок имён объектов метаданных, как в дереве Конфигуратора.
|
||||||
|
|
||||||
|
Ключ — пары «ранг+символ»: регистр не учитывается, подчёркивание раньше цифр, цифры раньше
|
||||||
|
букв, буквы по кодам (латиница раньше кириллицы), ё на месте е. Культурные таблицы не
|
||||||
|
используются — они разные на разных ОС и в разных рантаймах, а так оба порта сравнивают
|
||||||
|
одинаково везде. Равные ключи разводит ordinal-сравнение исходных строк.
|
||||||
|
Возвращает -1 | 0 | 1. Реестр семьи: tests/skills/check-inline-drift.mjs.
|
||||||
|
"""
|
||||||
|
keys = []
|
||||||
|
for name in (a, b):
|
||||||
|
parts = []
|
||||||
|
for ch in name.lower():
|
||||||
|
if ch == "ё":
|
||||||
|
ch = "е"
|
||||||
|
if ch.isdigit():
|
||||||
|
parts.append("1" + ch)
|
||||||
|
elif ch.isalpha():
|
||||||
|
parts.append("2" + ch)
|
||||||
|
else:
|
||||||
|
parts.append("0" + ch)
|
||||||
|
keys.append("".join(parts))
|
||||||
|
if keys[0] != keys[1]:
|
||||||
|
return -1 if keys[0] < keys[1] else 1
|
||||||
|
if a != b:
|
||||||
|
return -1 if a < b else 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def localname(el):
|
def localname(el):
|
||||||
return etree.QName(el.tag).localname
|
return etree.QName(el.tag).localname
|
||||||
|
|
||||||
@@ -237,7 +329,7 @@ CHILD_TYPE_DIR_MAP = {
|
|||||||
"XDTOPackage": "XDTOPackages", "WebService": "WebServices",
|
"XDTOPackage": "XDTOPackages", "WebService": "WebServices",
|
||||||
"HTTPService": "HTTPServices", "WSReference": "WSReferences",
|
"HTTPService": "HTTPServices", "WSReference": "WSReferences",
|
||||||
"CommonAttribute": "CommonAttributes", "Style": "Styles",
|
"CommonAttribute": "CommonAttributes", "Style": "Styles",
|
||||||
"Bot": "Bots", "Language": "Languages",
|
"Bot": "Bots", "PaletteColor": "PaletteColors", "PaletteColor": "PaletteColors", "Language": "Languages",
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Модули заимствованных объектов ---
|
# --- Модули заимствованных объектов ---
|
||||||
@@ -307,10 +399,10 @@ SYNONYM_MAP = {
|
|||||||
TYPE_ORDER = [
|
TYPE_ORDER = [
|
||||||
"Language", "Subsystem", "StyleItem", "Style",
|
"Language", "Subsystem", "StyleItem", "Style",
|
||||||
"CommonPicture", "SessionParameter", "Role", "CommonTemplate",
|
"CommonPicture", "SessionParameter", "Role", "CommonTemplate",
|
||||||
"FilterCriterion", "CommonModule", "Bot", "CommonAttribute", "ExchangePlan",
|
"FilterCriterion", "CommonModule", "CommonAttribute", "ExchangePlan",
|
||||||
"XDTOPackage", "WebService", "HTTPService", "WSReference",
|
"XDTOPackage", "WebService", "HTTPService", "WSReference",
|
||||||
"EventSubscription", "ScheduledJob", "SettingsStorage", "FunctionalOption",
|
"EventSubscription", "ScheduledJob", "SettingsStorage", "FunctionalOption",
|
||||||
"FunctionalOptionsParameter", "DefinedType", "CommonCommand", "CommandGroup",
|
"FunctionalOptionsParameter", "DefinedType", "Bot", "PaletteColor", "CommonCommand", "CommandGroup",
|
||||||
"Constant", "CommonForm", "Catalog", "Document",
|
"Constant", "CommonForm", "Catalog", "Document",
|
||||||
"DocumentNumerator", "Sequence", "DocumentJournal", "Enum",
|
"DocumentNumerator", "Sequence", "DocumentJournal", "Enum",
|
||||||
"Report", "DataProcessor", "InformationRegister", "AccumulationRegister",
|
"Report", "DataProcessor", "InformationRegister", "AccumulationRegister",
|
||||||
@@ -1035,6 +1127,13 @@ def main():
|
|||||||
warn(f"Already in ChildObjects: {type_name}.{obj_name}")
|
warn(f"Already in ChildObjects: {type_name}.{obj_name}")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Место вставки. Вид — по TYPE_ORDER; внутри вида — по newObjectPosition:
|
||||||
|
# end (по умолчанию) кладёт после последнего объекта того же вида, byName — по имени.
|
||||||
|
# Так же, как заимствует Конфигуратор: в боевых выгрузках расширений ChildObjects
|
||||||
|
# не отсортирован. Subsystem по имени не упорядочиваем никогда: порядок подсистем
|
||||||
|
# в дереве задаёт порядок разделов в панели.
|
||||||
|
by_name = (not is_order_sensitive_type(type_name)
|
||||||
|
and get_new_object_position(ext_dir) == "byName")
|
||||||
insert_before = None
|
insert_before = None
|
||||||
for child in child_objs_el:
|
for child in child_objs_el:
|
||||||
if not isinstance(child.tag, str):
|
if not isinstance(child.tag, str):
|
||||||
@@ -1045,7 +1144,8 @@ def main():
|
|||||||
child_type_idx = TYPE_ORDER.index(child_type_name)
|
child_type_idx = TYPE_ORDER.index(child_type_name)
|
||||||
|
|
||||||
if child_type_name == type_name:
|
if child_type_name == type_name:
|
||||||
if (child.text or "") > obj_name and insert_before is None:
|
if (by_name and insert_before is None
|
||||||
|
and compare_metadata_names(child.text or "", obj_name) > 0):
|
||||||
insert_before = child
|
insert_before = child
|
||||||
elif child_type_idx > type_idx and insert_before is None:
|
elif child_type_idx > type_idx and insert_before is None:
|
||||||
insert_before = child
|
insert_before = child
|
||||||
@@ -23,7 +23,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-diff.ps1" -ExtensionPath src\cfe\extname -ConfigPath src\cf -Mode A
|
powershell.exe -NoProfile -File ".augment/skills/cfe-diff/scripts/cfe-diff.ps1" -ExtensionPath src\cfe\extname -ConfigPath src\cf -Mode A
|
||||||
```
|
```
|
||||||
|
|
||||||
## Mode A — обзор расширения
|
## Mode A — обзор расширения
|
||||||
+2
-1
@@ -1,4 +1,4 @@
|
|||||||
# cfe-diff v1.3 — Analyze and compare 1C configuration extension (CFE)
|
# cfe-diff v1.4 — Analyze and compare 1C configuration extension (CFE)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
[CmdletBinding(PositionalBinding=$false)]
|
[CmdletBinding(PositionalBinding=$false)]
|
||||||
param(
|
param(
|
||||||
@@ -53,6 +53,7 @@ $childTypeDirMap = @{
|
|||||||
"CommonAttribute"="CommonAttributes"; "Style"="Styles"; "XDTOPackage"="XDTOPackages"
|
"CommonAttribute"="CommonAttributes"; "Style"="Styles"; "XDTOPackage"="XDTOPackages"
|
||||||
"WebService"="WebServices"; "HTTPService"="HTTPServices"; "WSReference"="WSReferences"
|
"WebService"="WebServices"; "HTTPService"="HTTPServices"; "WSReference"="WSReferences"
|
||||||
"Bot"="Bots"
|
"Bot"="Bots"
|
||||||
|
"PaletteColor"="PaletteColors"
|
||||||
}
|
}
|
||||||
|
|
||||||
# --- Parse extension Configuration.xml ---
|
# --- Parse extension Configuration.xml ---
|
||||||
+2
-1
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# cfe-diff v1.3 — Analyze and compare 1C configuration extension (CFE)
|
# cfe-diff v1.4 — Analyze and compare 1C configuration extension (CFE)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -88,6 +88,7 @@ CHILD_TYPE_DIR_MAP = {
|
|||||||
"HTTPService": "HTTPServices",
|
"HTTPService": "HTTPServices",
|
||||||
"WSReference": "WSReferences",
|
"WSReference": "WSReferences",
|
||||||
"Bot": "Bots",
|
"Bot": "Bots",
|
||||||
|
"PaletteColor": "PaletteColors",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-init.ps1" -Name "МоёРасширение" -OutputDir "src\cfe\МоёРасширение" -ConfigPath "src\cf"
|
powershell.exe -NoProfile -File ".augment/skills/cfe-init/scripts/cfe-init.ps1" -Name "МоёРасширение" -OutputDir "src\cfe\МоёРасширение" -ConfigPath "src\cf"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
+2
-2
@@ -88,7 +88,7 @@ allowed-tools:
|
|||||||
|
|
||||||
Правила:
|
Правила:
|
||||||
- Маркеры — на **отдельной строке с 0-й колонки** (без отступа), даже внутри отступов и текста запроса (`|…`).
|
- Маркеры — на **отдельной строке с 0-й колонки** (без отступа), даже внутри отступов и текста запроса (`|…`).
|
||||||
- **Незамеченные (unmarked) строки должны совпадать с оригиналом дословно** — это и есть «контроль». Если оригинал в конфигурации-источнике изменится, unmarked-контекст разойдётся → метод потребует актуализации (см. ниже; проверить пачкой — `-Check`).
|
- **Незамеченные (unmarked) строки должны совпадать с оригиналом дословно** — это и есть «контроль». Дословно — включая комментарии, регистр и пробелы внутри строки (`Х = Х + 1` ≠ `Х=Х+1`); свободны только отступ и пустые строки. Если оригинал в конфигурации-источнике изменится, unmarked-контекст разойдётся → метод потребует актуализации (см. ниже; проверить пачкой — `-Check`).
|
||||||
- Меняешь только свои `#Вставка`/`#Удаление`; чужой оригинал не трогай.
|
- Меняешь только свои `#Вставка`/`#Удаление`; чужой оригинал не трогай.
|
||||||
|
|
||||||
## Актуализация
|
## Актуализация
|
||||||
@@ -110,7 +110,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-patch-method.ps1" -ExtensionPath src\cfe\extname -ConfigPath src\cf -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
|
powershell.exe -NoProfile -File ".augment/skills/cfe-patch-method/scripts/cfe-patch-method.ps1" -ExtensionPath src\cfe\extname -ConfigPath src\cf -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
|
||||||
```
|
```
|
||||||
|
|
||||||
## Примеры
|
## Примеры
|
||||||
+27
-2
@@ -1,4 +1,4 @@
|
|||||||
# cfe-patch-method v2.9 — Source-aware method interceptor for 1C extension (CFE)
|
# cfe-patch-method v2.11 — Source-aware method interceptor for 1C extension (CFE)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
[CmdletBinding(PositionalBinding=$false)]
|
[CmdletBinding(PositionalBinding=$false)]
|
||||||
param(
|
param(
|
||||||
@@ -362,6 +362,22 @@ function Get-Normalized {
|
|||||||
return (($line -replace '\s+', ' ').Trim())
|
return (($line -replace '\s+', ' ').Trim())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Control comparison key, as the platform compares a &ИзменениеИКонтроль copy with the original:
|
||||||
|
# each line trimmed, blank lines dropped, everything else byte-for-byte and case-sensitive
|
||||||
|
# (inner spaces, comments and letter case are significant). Measured on 8.3.24 and 8.3.27.
|
||||||
|
function Get-ControlKey {
|
||||||
|
param($lines)
|
||||||
|
return (@($lines | ForEach-Object { $_.Trim() } | Where-Object { $_ -ne '' }) -join "`n")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parameter count of a signature params text. The platform compares only the number of
|
||||||
|
# parameters of a &ИзменениеИКонтроль copy (names and default values it ignores).
|
||||||
|
function Get-ParamCount {
|
||||||
|
param([string]$paramsText)
|
||||||
|
if ([string]::IsNullOrWhiteSpace($paramsText)) { return 0 }
|
||||||
|
return @(Split-TopLevel $paramsText | Where-Object { $_.Trim() -ne '' }).Count
|
||||||
|
}
|
||||||
|
|
||||||
# Reconstruct v1 body and edit ops from a marked body
|
# Reconstruct v1 body and edit ops from a marked body
|
||||||
function Parse-MarkedBody {
|
function Parse-MarkedBody {
|
||||||
param($bodyLines)
|
param($bodyLines)
|
||||||
@@ -651,7 +667,14 @@ function Invoke-Resync {
|
|||||||
$v1norm = @($v1 | ForEach-Object { Get-Normalized $_ })
|
$v1norm = @($v1 | ForEach-Object { Get-Normalized $_ })
|
||||||
$v2norm = @($v2 | ForEach-Object { Get-Normalized $_ })
|
$v2norm = @($v2 | ForEach-Object { Get-Normalized $_ })
|
||||||
|
|
||||||
if (($v1norm -join "`n") -eq ($v2norm -join "`n")) {
|
# Signature: the platform rejects the interceptor when the parameter COUNT differs, so a
|
||||||
|
# body-only comparison would miss a vendor-added parameter. Names/defaults it ignores.
|
||||||
|
$extParamCount = Get-ParamCount $sig.ParamsText
|
||||||
|
$srcParamCount = Get-ParamCount $method.ParamsText
|
||||||
|
$paramsDrift = ($extParamCount -ne $srcParamCount)
|
||||||
|
$paramsReason = if ($paramsDrift) { "список параметров: в оригинале $srcParamCount, в перехватчике $extParamCount" } else { '' }
|
||||||
|
|
||||||
|
if (-not $paramsDrift -and [string]::Equals((Get-ControlKey $v1), (Get-ControlKey $v2), 'Ordinal')) {
|
||||||
return @{ Id = $methodId; Status = 'АКТУАЛЕН'; ExtBsl = $extBsl }
|
return @{ Id = $methodId; Status = 'АКТУАЛЕН'; ExtBsl = $extBsl }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,7 +724,9 @@ function Invoke-Resync {
|
|||||||
|
|
||||||
if ($ReportOnly) {
|
if ($ReportOnly) {
|
||||||
$st = if ($disputed.Count -gt 0) { 'КОНФЛИКТ' } elseif ($transferred.Count -eq 0 -and $absorbed.Count -gt 0) { 'ПЕРЕНЕСЕНО В ОСНОВНУЮ' } else { 'ДРЕЙФ' }
|
$st = if ($disputed.Count -gt 0) { 'КОНФЛИКТ' } elseif ($transferred.Count -eq 0 -and $absorbed.Count -gt 0) { 'ПЕРЕНЕСЕНО В ОСНОВНУЮ' } else { 'ДРЕЙФ' }
|
||||||
|
if ($paramsDrift -and $st -eq 'ПЕРЕНЕСЕНО В ОСНОВНУЮ') { $st = 'ДРЕЙФ' }
|
||||||
$rsn = if ($disputed.Count -gt 0) { Get-ResyncConflictReason $disputed } elseif ($st -eq 'ПЕРЕНЕСЕНО В ОСНОВНУЮ') { 'все правки уже в основной конфигурации' } else { '' }
|
$rsn = if ($disputed.Count -gt 0) { Get-ResyncConflictReason $disputed } elseif ($st -eq 'ПЕРЕНЕСЕНО В ОСНОВНУЮ') { 'все правки уже в основной конфигурации' } else { '' }
|
||||||
|
if ($paramsDrift) { $rsn = if ($rsn) { "$paramsReason; $rsn" } else { $paramsReason } }
|
||||||
return @{ Id = $methodId; Status = $st; ExtBsl = $extBsl; Transferred = $transferred.Count; Absorbed = $absorbed.Count; Disputed = $disputed.Count; Reason = $rsn; AbsorbedNotes = $absorbedNotes }
|
return @{ Id = $methodId; Status = $st; ExtBsl = $extBsl; Transferred = $transferred.Count; Absorbed = $absorbed.Count; Disputed = $disputed.Count; Reason = $rsn; AbsorbedNotes = $absorbedNotes }
|
||||||
}
|
}
|
||||||
|
|
||||||
+30
-3
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# cfe-patch-method v2.9 — Source-aware method interceptor for 1C extension (CFE)
|
# cfe-patch-method v2.11 — Source-aware method interceptor for 1C extension (CFE)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -491,6 +491,21 @@ def normalize(line):
|
|||||||
return re.sub(r'\s+', ' ', line).strip()
|
return re.sub(r'\s+', ' ', line).strip()
|
||||||
|
|
||||||
|
|
||||||
|
# Control comparison key, as the platform compares a &ИзменениеИКонтроль copy with the original:
|
||||||
|
# each line trimmed, blank lines dropped, everything else byte-for-byte and case-sensitive
|
||||||
|
# (inner spaces, comments and letter case are significant). Measured on 8.3.24 and 8.3.27.
|
||||||
|
def control_key(lines):
|
||||||
|
return "\n".join([k for k in (x.strip() for x in lines) if k != ""])
|
||||||
|
|
||||||
|
|
||||||
|
# Parameter count of a signature params text. The platform compares only the number of
|
||||||
|
# parameters of a &ИзменениеИКонтроль copy (names and default values it ignores).
|
||||||
|
def param_count(params_text):
|
||||||
|
if not params_text or not params_text.strip():
|
||||||
|
return 0
|
||||||
|
return len([p for p in split_top_level(params_text) if p.strip()])
|
||||||
|
|
||||||
|
|
||||||
def parse_marked_body(body_lines):
|
def parse_marked_body(body_lines):
|
||||||
v1 = []
|
v1 = []
|
||||||
ops = []
|
ops = []
|
||||||
@@ -1129,7 +1144,7 @@ def resync_one(ext_bsl, ext_lines, dup, method, logical_module, conflict_folder,
|
|||||||
sig = read_signature(ext_lines, sig_line_idx)
|
sig = read_signature(ext_lines, sig_line_idx)
|
||||||
if not sig:
|
if not sig:
|
||||||
return {"id": method_id, "status": "ОШИБКА", "ext_bsl": ext_bsl, "reason": "не разобрать сигнатуру"}
|
return {"id": method_id, "status": "ОШИБКА", "ext_bsl": ext_bsl, "reason": "не разобрать сигнатуру"}
|
||||||
_params, sig_end = sig
|
ext_params_text, sig_end = sig
|
||||||
is_func = bool(re.match(r'^\s*(?:Асинх\s+)?Функция\b', ext_lines[sig_line_idx], re.IGNORECASE))
|
is_func = bool(re.match(r'^\s*(?:Асинх\s+)?Функция\b', ext_lines[sig_line_idx], re.IGNORECASE))
|
||||||
end_re = re.compile(r'^\s*КонецФункции\b' if is_func else r'^\s*КонецПроцедуры\b', re.IGNORECASE)
|
end_re = re.compile(r'^\s*КонецФункции\b' if is_func else r'^\s*КонецПроцедуры\b', re.IGNORECASE)
|
||||||
block_end = -1
|
block_end = -1
|
||||||
@@ -1146,7 +1161,15 @@ def resync_one(ext_bsl, ext_lines, dup, method, logical_module, conflict_folder,
|
|||||||
v1norm = [normalize(x) for x in v1]
|
v1norm = [normalize(x) for x in v1]
|
||||||
v2norm = [normalize(x) for x in v2]
|
v2norm = [normalize(x) for x in v2]
|
||||||
|
|
||||||
if "\n".join(v1norm) == "\n".join(v2norm):
|
# Signature: the platform rejects the interceptor when the parameter COUNT differs, so a
|
||||||
|
# body-only comparison would miss a vendor-added parameter. Names/defaults it ignores.
|
||||||
|
ext_param_count = param_count(ext_params_text)
|
||||||
|
src_param_count = param_count(method["params_text"])
|
||||||
|
params_drift = ext_param_count != src_param_count
|
||||||
|
params_reason = ("список параметров: в оригинале %d, в перехватчике %d"
|
||||||
|
% (src_param_count, ext_param_count)) if params_drift else ""
|
||||||
|
|
||||||
|
if not params_drift and control_key(v1) == control_key(v2):
|
||||||
return {"id": method_id, "status": "АКТУАЛЕН", "ext_bsl": ext_bsl}
|
return {"id": method_id, "status": "АКТУАЛЕН", "ext_bsl": ext_bsl}
|
||||||
|
|
||||||
insert_top = []; insert_after = {}; del_start = set(); del_end = set(); disputed = []; transferred = 0; absorbed = 0; absorbed_notes = []
|
insert_top = []; insert_after = {}; del_start = set(); del_end = set(); disputed = []; transferred = 0; absorbed = 0; absorbed_notes = []
|
||||||
@@ -1208,7 +1231,11 @@ def resync_one(ext_bsl, ext_lines, dup, method, logical_module, conflict_folder,
|
|||||||
st = "ПЕРЕНЕСЕНО В ОСНОВНУЮ"
|
st = "ПЕРЕНЕСЕНО В ОСНОВНУЮ"
|
||||||
else:
|
else:
|
||||||
st = "ДРЕЙФ"
|
st = "ДРЕЙФ"
|
||||||
|
if params_drift and st == "ПЕРЕНЕСЕНО В ОСНОВНУЮ":
|
||||||
|
st = "ДРЕЙФ"
|
||||||
rsn = conflict_reason(disputed) if disputed else ("все правки уже в основной конфигурации" if st == "ПЕРЕНЕСЕНО В ОСНОВНУЮ" else "")
|
rsn = conflict_reason(disputed) if disputed else ("все правки уже в основной конфигурации" if st == "ПЕРЕНЕСЕНО В ОСНОВНУЮ" else "")
|
||||||
|
if params_drift:
|
||||||
|
rsn = ("%s; %s" % (params_reason, rsn)) if rsn else params_reason
|
||||||
return {"id": method_id, "status": st, "ext_bsl": ext_bsl, "transferred": transferred,
|
return {"id": method_id, "status": st, "ext_bsl": ext_bsl, "transferred": transferred,
|
||||||
"absorbed": absorbed, "disputed": len(disputed), "reason": rsn, "absorbed_notes": absorbed_notes}
|
"absorbed": absorbed, "disputed": len(disputed), "reason": rsn, "absorbed_notes": absorbed_notes}
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.ps1" -ExtensionPath "src\cfe\extname"
|
powershell.exe -NoProfile -File ".augment/skills/cfe-validate/scripts/cfe-validate.ps1" -ExtensionPath "src\cfe\extname"
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.ps1" -ExtensionPath "src\cfe\extname\Configuration.xml"
|
powershell.exe -NoProfile -File ".augment/skills/cfe-validate/scripts/cfe-validate.ps1" -ExtensionPath "src\cfe\extname\Configuration.xml"
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.ps1" -ExtensionPath "src\cfe\extname" -ConfigPath "src\cf"
|
powershell.exe -NoProfile -File ".augment/skills/cfe-validate/scripts/cfe-validate.ps1" -ExtensionPath "src\cfe\extname" -ConfigPath "src\cf"
|
||||||
```
|
```
|
||||||
+5
-5
@@ -1,4 +1,4 @@
|
|||||||
# cfe-validate v1.14 — Validate 1C configuration extension structure (CFE)
|
# cfe-validate v1.15 — Validate 1C configuration extension structure (CFE)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
[CmdletBinding(PositionalBinding=$false)]
|
[CmdletBinding(PositionalBinding=$false)]
|
||||||
param(
|
param(
|
||||||
@@ -143,14 +143,14 @@ $validClassIds = @(
|
|||||||
"fb282519-d103-4dd3-bc12-cb271d631dfc"
|
"fb282519-d103-4dd3-bc12-cb271d631dfc"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 44 types in canonical order
|
# 46 types in canonical order
|
||||||
$childObjectTypes = @(
|
$childObjectTypes = @(
|
||||||
"Language","Subsystem","StyleItem","Style",
|
"Language","Subsystem","StyleItem","Style",
|
||||||
"CommonPicture","SessionParameter","Role","CommonTemplate",
|
"CommonPicture","SessionParameter","Role","CommonTemplate",
|
||||||
"FilterCriterion","CommonModule","Bot","CommonAttribute","ExchangePlan",
|
"FilterCriterion","CommonModule","CommonAttribute","ExchangePlan",
|
||||||
"XDTOPackage","WebService","HTTPService","WSReference",
|
"XDTOPackage","WebService","HTTPService","WSReference",
|
||||||
"EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption",
|
"EventSubscription","ScheduledJob","SettingsStorage","FunctionalOption",
|
||||||
"FunctionalOptionsParameter","DefinedType","CommonCommand","CommandGroup",
|
"FunctionalOptionsParameter","DefinedType","Bot","PaletteColor","CommonCommand","CommandGroup",
|
||||||
"Constant","CommonForm","Catalog","Document",
|
"Constant","CommonForm","Catalog","Document",
|
||||||
"DocumentNumerator","Sequence","DocumentJournal","Enum",
|
"DocumentNumerator","Sequence","DocumentJournal","Enum",
|
||||||
"Report","DataProcessor","InformationRegister","AccumulationRegister",
|
"Report","DataProcessor","InformationRegister","AccumulationRegister",
|
||||||
@@ -161,7 +161,7 @@ $childObjectTypes = @(
|
|||||||
|
|
||||||
# Type -> directory mapping
|
# Type -> directory mapping
|
||||||
$childTypeDirMap = @{
|
$childTypeDirMap = @{
|
||||||
"Language"="Languages"; "Subsystem"="Subsystems"; "StyleItem"="StyleItems"; "Style"="Styles"; "Bot"="Bots"
|
"Language"="Languages"; "Subsystem"="Subsystems"; "StyleItem"="StyleItems"; "Style"="Styles"; "Bot"="Bots"; "PaletteColor"="PaletteColors"
|
||||||
"CommonPicture"="CommonPictures"; "SessionParameter"="SessionParameters"; "Role"="Roles"
|
"CommonPicture"="CommonPictures"; "SessionParameter"="SessionParameters"; "Role"="Roles"
|
||||||
"CommonTemplate"="CommonTemplates"; "FilterCriterion"="FilterCriteria"; "CommonModule"="CommonModules"
|
"CommonTemplate"="CommonTemplates"; "FilterCriterion"="FilterCriteria"; "CommonModule"="CommonModules"
|
||||||
"CommonAttribute"="CommonAttributes"; "ExchangePlan"="ExchangePlans"; "XDTOPackage"="XDTOPackages"
|
"CommonAttribute"="CommonAttributes"; "ExchangePlan"="ExchangePlans"; "XDTOPackage"="XDTOPackages"
|
||||||
+5
-5
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# cfe-validate v1.14 — Validate 1C configuration extension XML structure (CFE)
|
# cfe-validate v1.15 — Validate 1C configuration extension XML structure (CFE)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
"""Validates extension Configuration.xml: root, InternalInfo, extension properties, ChildObjects, borrowed objects."""
|
"""Validates extension Configuration.xml: root, InternalInfo, extension properties, ChildObjects, borrowed objects."""
|
||||||
import sys, os, argparse, re
|
import sys, os, argparse, re
|
||||||
@@ -55,14 +55,14 @@ VALID_CLASS_IDS = [
|
|||||||
'fb282519-d103-4dd3-bc12-cb271d631dfc',
|
'fb282519-d103-4dd3-bc12-cb271d631dfc',
|
||||||
]
|
]
|
||||||
|
|
||||||
# 44 types in canonical order
|
# 46 types in canonical order
|
||||||
CHILD_OBJECT_TYPES = [
|
CHILD_OBJECT_TYPES = [
|
||||||
'Language', 'Subsystem', 'StyleItem', 'Style',
|
'Language', 'Subsystem', 'StyleItem', 'Style',
|
||||||
'CommonPicture', 'SessionParameter', 'Role', 'CommonTemplate',
|
'CommonPicture', 'SessionParameter', 'Role', 'CommonTemplate',
|
||||||
'FilterCriterion', 'CommonModule', 'Bot', 'CommonAttribute', 'ExchangePlan',
|
'FilterCriterion', 'CommonModule', 'CommonAttribute', 'ExchangePlan',
|
||||||
'XDTOPackage', 'WebService', 'HTTPService', 'WSReference',
|
'XDTOPackage', 'WebService', 'HTTPService', 'WSReference',
|
||||||
'EventSubscription', 'ScheduledJob', 'SettingsStorage', 'FunctionalOption',
|
'EventSubscription', 'ScheduledJob', 'SettingsStorage', 'FunctionalOption',
|
||||||
'FunctionalOptionsParameter', 'DefinedType', 'CommonCommand', 'CommandGroup',
|
'FunctionalOptionsParameter', 'DefinedType', 'Bot', 'PaletteColor', 'CommonCommand', 'CommandGroup',
|
||||||
'Constant', 'CommonForm', 'Catalog', 'Document',
|
'Constant', 'CommonForm', 'Catalog', 'Document',
|
||||||
'DocumentNumerator', 'Sequence', 'DocumentJournal', 'Enum',
|
'DocumentNumerator', 'Sequence', 'DocumentJournal', 'Enum',
|
||||||
'Report', 'DataProcessor', 'InformationRegister', 'AccumulationRegister',
|
'Report', 'DataProcessor', 'InformationRegister', 'AccumulationRegister',
|
||||||
@@ -97,7 +97,7 @@ CHILD_TYPE_DIR_MAP = {
|
|||||||
'Language': 'Languages', 'Subsystem': 'Subsystems', 'StyleItem': 'StyleItems', 'Style': 'Styles',
|
'Language': 'Languages', 'Subsystem': 'Subsystems', 'StyleItem': 'StyleItems', 'Style': 'Styles',
|
||||||
'CommonPicture': 'CommonPictures', 'SessionParameter': 'SessionParameters', 'Role': 'Roles',
|
'CommonPicture': 'CommonPictures', 'SessionParameter': 'SessionParameters', 'Role': 'Roles',
|
||||||
'CommonTemplate': 'CommonTemplates', 'FilterCriterion': 'FilterCriteria', 'CommonModule': 'CommonModules',
|
'CommonTemplate': 'CommonTemplates', 'FilterCriterion': 'FilterCriteria', 'CommonModule': 'CommonModules',
|
||||||
'Bot': 'Bots',
|
'Bot': 'Bots', 'PaletteColor': 'PaletteColors',
|
||||||
'CommonAttribute': 'CommonAttributes', 'ExchangePlan': 'ExchangePlans', 'XDTOPackage': 'XDTOPackages',
|
'CommonAttribute': 'CommonAttributes', 'ExchangePlan': 'ExchangePlans', 'XDTOPackage': 'XDTOPackages',
|
||||||
'WebService': 'WebServices', 'HTTPService': 'HTTPServices', 'WSReference': 'WSReferences',
|
'WebService': 'WebServices', 'HTTPService': 'HTTPServices', 'WSReference': 'WSReferences',
|
||||||
'EventSubscription': 'EventSubscriptions', 'ScheduledJob': 'ScheduledJobs',
|
'EventSubscription': 'EventSubscriptions', 'ScheduledJob': 'ScheduledJobs',
|
||||||
@@ -31,7 +31,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/db-create/scripts/db-create.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -59,14 +59,14 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" <п
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Создать файловую базу
|
# Создать файловую базу
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB"
|
powershell.exe -NoProfile -File ".augment/skills/db-create/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB"
|
||||||
|
|
||||||
# Создать серверную базу
|
# Создать серверную базу
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test"
|
powershell.exe -NoProfile -File ".augment/skills/db-create/scripts/db-create.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test"
|
||||||
|
|
||||||
# Создать из шаблона CF
|
# Создать из шаблона CF
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -UseTemplate "C:\Templates\config.cf"
|
powershell.exe -NoProfile -File ".augment/skills/db-create/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -UseTemplate "C:\Templates\config.cf"
|
||||||
|
|
||||||
# Создать и добавить в список баз
|
# Создать и добавить в список баз
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -AddToList -ListName "Новая база"
|
powershell.exe -NoProfile -File ".augment/skills/db-create/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -AddToList -ListName "Новая база"
|
||||||
```
|
```
|
||||||
@@ -35,7 +35,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/db-dump-cf/scripts/db-dump-cf.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -60,11 +60,11 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" <п
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Выгрузка конфигурации (файловая база)
|
# Выгрузка конфигурации (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\config.cf"
|
powershell.exe -NoProfile -File ".augment/skills/db-dump-cf/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\config.cf"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "config.cf"
|
powershell.exe -NoProfile -File ".augment/skills/db-dump-cf/scripts/db-dump-cf.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "config.cf"
|
||||||
|
|
||||||
# Выгрузка расширения
|
# Выгрузка расширения
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "ext.cfe" -Extension "МоёРасширение"
|
powershell.exe -NoProfile -File ".augment/skills/db-dump-cf/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "ext.cfe" -Extension "МоёРасширение"
|
||||||
```
|
```
|
||||||
@@ -38,7 +38,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/db-dump-dt/scripts/db-dump-dt.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -61,10 +61,10 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" <п
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Выгрузка ИБ (файловая база)
|
# Выгрузка ИБ (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\base.dt"
|
powershell.exe -NoProfile -File ".augment/skills/db-dump-dt/scripts/db-dump-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\base.dt"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-dt.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "base.dt"
|
powershell.exe -NoProfile -File ".augment/skills/db-dump-dt/scripts/db-dump-dt.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "base.dt"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Связанные навыки
|
## Связанные навыки
|
||||||
@@ -38,7 +38,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/db-dump-xml/scripts/db-dump-xml.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -77,17 +77,17 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" <
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Полная выгрузка (файловая база)
|
# Полная выгрузка (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
powershell.exe -NoProfile -File ".augment/skills/db-dump-xml/scripts/db-dump-xml.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
||||||
|
|
||||||
# Инкрементальная выгрузка
|
# Инкрементальная выгрузка
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Changes
|
powershell.exe -NoProfile -File ".augment/skills/db-dump-xml/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Changes
|
||||||
|
|
||||||
# Частичная выгрузка
|
# Частичная выгрузка
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Partial -Objects "Справочник.Номенклатура,Документ.Заказ"
|
powershell.exe -NoProfile -File ".augment/skills/db-dump-xml/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Partial -Objects "Справочник.Номенклатура,Документ.Заказ"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
powershell.exe -NoProfile -File ".augment/skills/db-dump-xml/scripts/db-dump-xml.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
||||||
|
|
||||||
# Выгрузка расширения
|
# Выгрузка расширения
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
|
powershell.exe -NoProfile -File ".augment/skills/db-dump-xml/scripts/db-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
|
||||||
```
|
```
|
||||||
@@ -76,6 +76,7 @@ allowed-tools:
|
|||||||
| `v8path` | string | Каталог bin платформы 1С. Необязательный — если не задан, автоопределение |
|
| `v8path` | string | Каталог bin платформы 1С. Необязательный — если не задан, автоопределение |
|
||||||
| `v8args` | array | Доп. аргументы запуска `1cv8.exe` для всех навыков, напр. `["/UseHwLicenses+"]` |
|
| `v8args` | array | Доп. аргументы запуска `1cv8.exe` для всех навыков, напр. `["/UseHwLicenses+"]` |
|
||||||
| `ibcmdargs` | array | Доп. аргументы `ibcmd` (форма `--ключ=значение`) |
|
| `ibcmdargs` | array | Доп. аргументы `ibcmd` (форма `--ключ=значение`) |
|
||||||
|
| `newObjectPosition` | `"end"` / `"byName"` | Куда попадает новый объект в составе конфигурации: в конец своего вида (по умолчанию) или на место по имени. Переопределяется в `databases[]` |
|
||||||
| `databases` | array | Массив баз данных |
|
| `databases` | array | Массив баз данных |
|
||||||
| `default` | string | id базы по умолчанию |
|
| `default` | string | id базы по умолчанию |
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/db-load-cf/scripts/db-load-cf.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -65,11 +65,11 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" <п
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Файловая база
|
# Файловая база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\config.cf"
|
powershell.exe -NoProfile -File ".augment/skills/db-load-cf/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\config.cf"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "config.cf"
|
powershell.exe -NoProfile -File ".augment/skills/db-load-cf/scripts/db-load-cf.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "config.cf"
|
||||||
|
|
||||||
# Загрузка расширения
|
# Загрузка расширения
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "ext.cfe" -Extension "МоёРасширение"
|
powershell.exe -NoProfile -File ".augment/skills/db-load-cf/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "ext.cfe" -Extension "МоёРасширение"
|
||||||
```
|
```
|
||||||
@@ -52,7 +52,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/db-load-dt/scripts/db-load-dt.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -82,10 +82,10 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" <п
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Файловая база
|
# Файловая база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\base.dt"
|
powershell.exe -NoProfile -File ".augment/skills/db-load-dt/scripts/db-load-dt.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\base.dt"
|
||||||
|
|
||||||
# Серверная база с ускорением загрузки
|
# Серверная база с ускорением загрузки
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-dt.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "base.dt" -JobsCount 4
|
powershell.exe -NoProfile -File ".augment/skills/db-load-dt/scripts/db-load-dt.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "base.dt" -JobsCount 4
|
||||||
```
|
```
|
||||||
|
|
||||||
## Связанные навыки
|
## Связанные навыки
|
||||||
@@ -38,7 +38,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/db-load-git/scripts/db-load-git.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -72,8 +72,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" <
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Все незафиксированные изменения
|
# Все незафиксированные изменения
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source All -UpdateDB
|
powershell.exe -NoProfile -File ".augment/skills/db-load-git/scripts/db-load-git.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source All -UpdateDB
|
||||||
|
|
||||||
# Из диапазона коммитов
|
# Из диапазона коммитов
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source Commit -CommitRange "HEAD~3..HEAD"
|
powershell.exe -NoProfile -File ".augment/skills/db-load-git/scripts/db-load-git.ps1" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source Commit -CommitRange "HEAD~3..HEAD"
|
||||||
```
|
```
|
||||||
@@ -39,7 +39,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/db-load-xml/scripts/db-load-xml.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -91,14 +91,14 @@ Documents/Заказ/Forms/ФормаДокумента.xml
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Полная загрузка
|
# Полная загрузка
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
powershell.exe -NoProfile -File ".augment/skills/db-load-xml/scripts/db-load-xml.ps1" -V8Path "C:\Program Files\1cv8\8.3.25.1257\bin" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
||||||
|
|
||||||
# Частичная загрузка конкретных файлов
|
# Частичная загрузка конкретных файлов
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Partial -Files "Catalogs/Номенклатура.xml,Catalogs/Номенклатура/Ext/ObjectModule.bsl"
|
powershell.exe -NoProfile -File ".augment/skills/db-load-xml/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Partial -Files "Catalogs/Номенклатура.xml,Catalogs/Номенклатура/Ext/ObjectModule.bsl"
|
||||||
|
|
||||||
# Загрузка расширения
|
# Загрузка расширения
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
|
powershell.exe -NoProfile -File ".augment/skills/db-load-xml/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
|
||||||
|
|
||||||
# Загрузка + обновление БД в одном запуске
|
# Загрузка + обновление БД в одном запуске
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full -UpdateDB
|
powershell.exe -NoProfile -File ".augment/skills/db-load-xml/scripts/db-load-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full -UpdateDB
|
||||||
```
|
```
|
||||||
@@ -76,7 +76,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-repo.ps1" -Command <подкоманда> <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/db-repo/scripts/db-repo.ps1" -Command <подкоманда> <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Рабочий цикл
|
### Рабочий цикл
|
||||||
@@ -174,22 +174,22 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-repo.ps1" -Comma
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Захватить справочник вместе с подчинёнными объектами
|
# Захватить справочник вместе с подчинёнными объектами
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-repo.ps1" -Command lock -InfoBasePath "C:\Bases\MyDB" -Objects "Справочник.Номенклатура" -WithChildren
|
powershell.exe -NoProfile -File ".augment/skills/db-repo/scripts/db-repo.ps1" -Command lock -InfoBasePath "C:\Bases\MyDB" -Objects "Справочник.Номенклатура" -WithChildren
|
||||||
|
|
||||||
# Захватить корень — он нужен, чтобы добавить или удалить объект конфигурации
|
# Захватить корень — он нужен, чтобы добавить или удалить объект конфигурации
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-repo.ps1" -Command lock -InfoBasePath "C:\Bases\MyDB" -Objects "Конфигурация"
|
powershell.exe -NoProfile -File ".augment/skills/db-repo/scripts/db-repo.ps1" -Command lock -InfoBasePath "C:\Bases\MyDB" -Objects "Конфигурация"
|
||||||
|
|
||||||
# Поместить новый объект: он уже существует, поэтому называется вместе с корнем
|
# Поместить новый объект: он уже существует, поэтому называется вместе с корнем
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-repo.ps1" -Command commit -InfoBasePath "C:\Bases\MyDB" -Objects "Конфигурация,Справочник.Склады" -Comment "Добавлен справочник Склады"
|
powershell.exe -NoProfile -File ".augment/skills/db-repo/scripts/db-repo.ps1" -Command commit -InfoBasePath "C:\Bases\MyDB" -Objects "Конфигурация,Справочник.Склады" -Comment "Добавлен справочник Склады"
|
||||||
|
|
||||||
# Поместить с комментарием, оставив захват
|
# Поместить с комментарием, оставив захват
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-repo.ps1" -Command commit -InfoBasePath "C:\Bases\MyDB" -Objects "Справочник.Номенклатура" -Comment "Добавлен реквизит Артикул" -KeepLocked
|
powershell.exe -NoProfile -File ".augment/skills/db-repo/scripts/db-repo.ps1" -Command commit -InfoBasePath "C:\Bases\MyDB" -Objects "Справочник.Номенклатура" -Comment "Добавлен реквизит Артикул" -KeepLocked
|
||||||
|
|
||||||
# Получить изменения из хранилища
|
# Получить изменения из хранилища
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-repo.ps1" -Command update -InfoBasePath "C:\Bases\MyDB"
|
powershell.exe -NoProfile -File ".augment/skills/db-repo/scripts/db-repo.ps1" -Command update -InfoBasePath "C:\Bases\MyDB"
|
||||||
|
|
||||||
# Серверная база, расширение
|
# Серверная база, расширение
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-repo.ps1" -Command lock -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Extension "МоёРасширение" -Objects "Справочник.Номенклатура"
|
powershell.exe -NoProfile -File ".augment/skills/db-repo/scripts/db-repo.ps1" -Command lock -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Extension "МоёРасширение" -Objects "Справочник.Номенклатура"
|
||||||
```
|
```
|
||||||
|
|
||||||
## После выполнения
|
## После выполнения
|
||||||
@@ -36,7 +36,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/db-run/scripts/db-run.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -64,14 +64,14 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" <пар
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Простой запуск
|
# Простой запуск
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
powershell.exe -NoProfile -File ".augment/skills/db-run/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
||||||
|
|
||||||
# Запуск с обработкой
|
# Запуск с обработкой
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Execute "C:\epf\МояОбработка.epf"
|
powershell.exe -NoProfile -File ".augment/skills/db-run/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Execute "C:\epf\МояОбработка.epf"
|
||||||
|
|
||||||
# Открыть по навигационной ссылке
|
# Открыть по навигационной ссылке
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -URL "e1cib/data/Справочник.Номенклатура"
|
powershell.exe -NoProfile -File ".augment/skills/db-run/scripts/db-run.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -URL "e1cib/data/Справочник.Номенклатура"
|
||||||
|
|
||||||
# Серверная база с параметром запуска
|
# Серверная база с параметром запуска
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -CParam "ЗапуститьОбновление"
|
powershell.exe -NoProfile -File ".augment/skills/db-run/scripts/db-run.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -CParam "ЗапуститьОбновление"
|
||||||
```
|
```
|
||||||
@@ -35,7 +35,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/db-update/scripts/db-update.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -78,11 +78,11 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" <п
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Обычное обновление (файловая база)
|
# Обычное обновление (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
powershell.exe -NoProfile -File ".augment/skills/db-update/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
||||||
|
|
||||||
# Динамическое обновление (серверная база)
|
# Динамическое обновление (серверная база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -Dynamic "+"
|
powershell.exe -NoProfile -File ".augment/skills/db-update/scripts/db-update.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -Dynamic "+"
|
||||||
|
|
||||||
# Обновление расширения
|
# Обновление расширения
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Extension "МоёРасширение"
|
powershell.exe -NoProfile -File ".augment/skills/db-update/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Extension "МоёРасширение"
|
||||||
```
|
```
|
||||||
@@ -40,7 +40,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/epf-build/scripts/epf-build.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -64,8 +64,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" <п
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Сборка обработки (файловая база)
|
# Сборка обработки (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
|
powershell.exe -NoProfile -File ".augment/skills/epf-build/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
|
powershell.exe -NoProfile -File ".augment/skills/epf-build/scripts/epf-build.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
|
||||||
```
|
```
|
||||||
@@ -39,7 +39,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/epf-dump/scripts/epf-dump.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -64,8 +64,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" <па
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Разборка обработки (файловая база)
|
# Разборка обработки (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МояОбработка.epf" -OutputDir "src"
|
powershell.exe -NoProfile -File ".augment/skills/epf-dump/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МояОбработка.epf" -OutputDir "src"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МояОбработка.epf" -OutputDir "src"
|
powershell.exe -NoProfile -File ".augment/skills/epf-dump/scripts/epf-dump.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МояОбработка.epf" -OutputDir "src"
|
||||||
```
|
```
|
||||||
@@ -37,7 +37,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-FormatVersion "<версия>"]
|
powershell.exe -NoProfile -File ".augment/skills/epf-init/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-FormatVersion "<версия>"]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Дальнейшие шаги
|
## Дальнейшие шаги
|
||||||
@@ -24,7 +24,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка"
|
powershell.exe -NoProfile -File ".augment/skills/epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка"
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка/МояОбработка.xml"
|
powershell.exe -NoProfile -File ".augment/skills/epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка/МояОбработка.xml"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ allowed-tools:
|
|||||||
Используй общий скрипт из epf-build:
|
Используй общий скрипт из epf-build:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/epf-build/scripts/epf-build.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -66,8 +66,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-bu
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Сборка отчёта (файловая база)
|
# Сборка отчёта (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
|
powershell.exe -NoProfile -File ".augment/skills/epf-build/scripts/epf-build.ps1" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
|
powershell.exe -NoProfile -File ".augment/skills/epf-build/scripts/epf-build.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
|
||||||
```
|
```
|
||||||
@@ -41,7 +41,7 @@ allowed-tools:
|
|||||||
Используй общий скрипт из epf-dump:
|
Используй общий скрипт из epf-dump:
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" <параметры>
|
powershell.exe -NoProfile -File ".augment/skills/epf-dump/scripts/epf-dump.ps1" <параметры>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Параметры скрипта
|
### Параметры скрипта
|
||||||
@@ -66,8 +66,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dum
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Разборка отчёта (файловая база)
|
# Разборка отчёта (файловая база)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
|
powershell.exe -NoProfile -File ".augment/skills/epf-dump/scripts/epf-dump.ps1" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
|
||||||
|
|
||||||
# Серверная база
|
# Серверная база
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
|
powershell.exe -NoProfile -File ".augment/skills/epf-dump/scripts/epf-dump.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
|
||||||
```
|
```
|
||||||
@@ -38,7 +38,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-FormatVersion "<версия>"] [-WithSKD]
|
powershell.exe -NoProfile -File ".augment/skills/erf-init/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-FormatVersion "<версия>"] [-WithSKD]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Дальнейшие шаги
|
## Дальнейшие шаги
|
||||||
@@ -26,7 +26,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт"
|
powershell.exe -NoProfile -File ".augment/skills/epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт"
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт/МойОтчёт.xml"
|
powershell.exe -NoProfile -File ".augment/skills/epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт/МойОтчёт.xml"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ allowed-tools:
|
|||||||
## Команда
|
## Команда
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-add.ps1" -ObjectPath "<ObjectPath>" -FormName "<FormName>" [-Purpose "<Purpose>"] [-Synonym "<Synonym>"] [-SetDefault]
|
powershell.exe -NoProfile -File ".augment/skills/form-add/scripts/form-add.ps1" -ObjectPath "<ObjectPath>" -FormName "<FormName>" [-Purpose "<Purpose>"] [-Synonym "<Synonym>"] [-SetDefault]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Purpose — назначение формы
|
## Purpose — назначение формы
|
||||||
@@ -29,10 +29,10 @@ allowed-tools:
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Режим JSON DSL
|
# Режим JSON DSL
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-compile.ps1" -JsonPath "<json>" -OutputPath "<Form.xml>"
|
powershell.exe -NoProfile -File ".augment/skills/form-compile/scripts/form-compile.ps1" -JsonPath "<json>" -OutputPath "<Form.xml>"
|
||||||
|
|
||||||
# Режим from-object (объект и purpose выводятся из OutputPath; Document и Catalog)
|
# Режим from-object (объект и purpose выводятся из OutputPath; Document и Catalog)
|
||||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-compile.ps1" -FromObject -OutputPath "<.../TypePlural/ObjectName/Forms/FormName/Ext/Form.xml>"
|
powershell.exe -NoProfile -File ".augment/skills/form-compile/scripts/form-compile.ps1" -FromObject -OutputPath "<.../TypePlural/ObjectName/Forms/FormName/Ext/Form.xml>"
|
||||||
```
|
```
|
||||||
|
|
||||||
## JSON DSL — справка
|
## JSON DSL — справка
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user