mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-24 13:41:01 +03:00
Compare commits
36
Commits
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/claude-code-marketplace-manifest.json",
|
||||
"name": "cc-1c-skills",
|
||||
"description": "Маркетплейс навыков для разработки на платформе 1С:Предприятие",
|
||||
"owner": {
|
||||
"name": "Nikolay Shirokov"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "1c-skills",
|
||||
"source": "./",
|
||||
"description": "[PowerShell] Навыки для разработки на 1С:Предприятие 8.3 — абстракции над XML-форматами и CLI конфигуратора, плюс глаза и руки для тестирования через веб-клиент."
|
||||
},
|
||||
{
|
||||
"name": "1c-skills-py",
|
||||
"source": {
|
||||
"source": "github",
|
||||
"repo": "Nikolay-Shirokov/cc-1c-skills",
|
||||
"ref": "port-claude-code-py"
|
||||
},
|
||||
"description": "[Python] То же — для Linux/Mac или когда PowerShell недоступен."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
||||
"name": "1c-skills",
|
||||
"description": "[PowerShell] Навыки для разработки на 1С:Предприятие 8.3 — абстракции над XML-форматами и CLI конфигуратора, плюс глаза и руки для тестирования через веб-клиент.",
|
||||
"author": {
|
||||
"name": "Nikolay Shirokov"
|
||||
},
|
||||
"homepage": "https://github.com/Nikolay-Shirokov/cc-1c-skills",
|
||||
"repository": "https://github.com/Nikolay-Shirokov/cc-1c-skills",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"1c",
|
||||
"1c-dev",
|
||||
"cf",
|
||||
"cfe",
|
||||
"epf",
|
||||
"erf",
|
||||
"metadata",
|
||||
"configuration",
|
||||
"extension",
|
||||
"form",
|
||||
"report",
|
||||
"skd",
|
||||
"data-processor",
|
||||
"mxl",
|
||||
"web-client",
|
||||
"testing",
|
||||
"test-automation"
|
||||
],
|
||||
"skills": "./.claude/skills/"
|
||||
}
|
||||
@@ -24,7 +24,7 @@ allowed-tools:
|
||||
| `NoValidate` | Пропустить авто-валидацию |
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/cf-edit/scripts/cf-edit.ps1 -ConfigPath '<path>' -Operation modify-property -Value 'Version=1.0.0.1'
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-edit.ps1" -ConfigPath '<path>' -Operation modify-property -Value 'Version=1.0.0.1'
|
||||
```
|
||||
|
||||
## Операции
|
||||
|
||||
@@ -23,7 +23,7 @@ allowed-tools:
|
||||
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/cf-info/scripts/cf-info.ps1 -ConfigPath "<путь>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-info.ps1" -ConfigPath "<путь>"
|
||||
```
|
||||
|
||||
## Три режима
|
||||
|
||||
@@ -24,7 +24,7 @@ allowed-tools:
|
||||
| `CompatibilityMode` | Режим совместимости (default: `Version8_3_24`) |
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/cf-init/scripts/cf-init.ps1 -Name "МояКонфигурация"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-init.ps1" -Name "МояКонфигурация"
|
||||
```
|
||||
|
||||
## Примеры
|
||||
|
||||
@@ -24,6 +24,6 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/cf-validate/scripts/cf-validate.ps1 -ConfigPath "upload/cfempty"
|
||||
powershell.exe -NoProfile -File .claude/skills/cf-validate/scripts/cf-validate.ps1 -ConfigPath "upload/cfempty/Configuration.xml"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cf-validate.ps1" -ConfigPath "upload/cfempty/Configuration.xml"
|
||||
```
|
||||
|
||||
@@ -71,7 +71,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Контрагенты"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-borrow.ps1" -ExtensionPath src -ConfigPath C:\cfsrc\erp -Object "Catalog.Контрагенты"
|
||||
```
|
||||
|
||||
## Примеры
|
||||
|
||||
@@ -23,7 +23,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/cfe-diff/scripts/cfe-diff.ps1 -ExtensionPath src -ConfigPath C:\cfsrc\erp -Mode A
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-diff.ps1" -ExtensionPath src -ConfigPath C:\cfsrc\erp -Mode A
|
||||
```
|
||||
|
||||
## Mode A — обзор расширения
|
||||
|
||||
@@ -44,7 +44,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/cfe-init/scripts/cfe-init.ps1 -Name "МоёРасширение"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-init.ps1" -Name "МоёРасширение"
|
||||
```
|
||||
|
||||
## Примеры
|
||||
|
||||
@@ -51,7 +51,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/cfe-patch-method/scripts/cfe-patch-method.ps1 -ExtensionPath src -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-patch-method.ps1" -ExtensionPath src -ModulePath "Catalog.Контрагенты.ObjectModule" -MethodName "ПриЗаписи" -InterceptorType Before
|
||||
```
|
||||
|
||||
## Примеры
|
||||
|
||||
@@ -24,6 +24,6 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/cfe-validate/scripts/cfe-validate.ps1 -ExtensionPath "src"
|
||||
powershell.exe -NoProfile -File .claude/skills/cfe-validate/scripts/cfe-validate.ps1 -ExtensionPath "src/Configuration.xml"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.ps1" -ExtensionPath "src"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/cfe-validate.ps1" -ExtensionPath "src/Configuration.xml"
|
||||
```
|
||||
|
||||
@@ -31,7 +31,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/db-create/scripts/db-create.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -65,14 +65,14 @@ powershell.exe -NoProfile -File .claude/skills/db-create/scripts/db-create.ps1 <
|
||||
|
||||
```powershell
|
||||
# Создать файловую базу
|
||||
powershell.exe -NoProfile -File .claude/skills/db-create/scripts/db-create.ps1 -InfoBasePath "C:\Bases\NewDB"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB"
|
||||
|
||||
# Создать серверную базу
|
||||
powershell.exe -NoProfile -File .claude/skills/db-create/scripts/db-create.ps1 -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test"
|
||||
|
||||
# Создать из шаблона CF
|
||||
powershell.exe -NoProfile -File .claude/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" -UseTemplate "C:\Templates\config.cf"
|
||||
|
||||
# Создать и добавить в список баз
|
||||
powershell.exe -NoProfile -File .claude/skills/db-create/scripts/db-create.ps1 -InfoBasePath "C:\Bases\NewDB" -AddToList -ListName "Новая база"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-create.ps1" -InfoBasePath "C:\Bases\NewDB" -AddToList -ListName "Новая база"
|
||||
```
|
||||
|
||||
@@ -35,7 +35,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -69,11 +69,11 @@ powershell.exe -NoProfile -File .claude/skills/db-dump-cf/scripts/db-dump-cf.ps1
|
||||
|
||||
```powershell
|
||||
# Выгрузка конфигурации (файловая база)
|
||||
powershell.exe -NoProfile -File .claude/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" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "C:\backup\config.cf"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File .claude/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" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -OutputFile "config.cf"
|
||||
|
||||
# Выгрузка расширения
|
||||
powershell.exe -NoProfile -File .claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "ext.cfe" -Extension "МоёРасширение"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -OutputFile "ext.cfe" -Extension "МоёРасширение"
|
||||
```
|
||||
|
||||
@@ -37,7 +37,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-dump-xml.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -81,17 +81,17 @@ powershell.exe -NoProfile -File .claude/skills/db-dump-xml/scripts/db-dump-xml.p
|
||||
|
||||
```powershell
|
||||
# Полная выгрузка (файловая база)
|
||||
powershell.exe -NoProfile -File .claude/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" -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/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 Changes
|
||||
|
||||
# Частичная выгрузка
|
||||
powershell.exe -NoProfile -File .claude/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" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Partial -Objects "Справочник.Номенклатура,Документ.Заказ"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File .claude/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" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Dev" -UserName "Admin" -Password "secret" -ConfigDir "C:\WS\cfsrc" -Mode Full
|
||||
|
||||
# Выгрузка расширения
|
||||
powershell.exe -NoProfile -File .claude/skills/db-dump-xml/scripts/db-dump-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-dump-xml.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\ext_src" -Mode Full -Extension "МоёРасширение"
|
||||
```
|
||||
|
||||
@@ -36,7 +36,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/db-load-cf/scripts/db-load-cf.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -71,11 +71,11 @@ powershell.exe -NoProfile -File .claude/skills/db-load-cf/scripts/db-load-cf.ps1
|
||||
|
||||
```powershell
|
||||
# Файловая база
|
||||
powershell.exe -NoProfile -File .claude/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" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "C:\backup\config.cf"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File .claude/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" -InfoBaseServer "srv01" -InfoBaseRef "MyApp_Test" -UserName "Admin" -Password "secret" -InputFile "config.cf"
|
||||
|
||||
# Загрузка расширения
|
||||
powershell.exe -NoProfile -File .claude/skills/db-load-cf/scripts/db-load-cf.ps1 -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "ext.cfe" -Extension "МоёРасширение"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-cf.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -InputFile "ext.cfe" -Extension "МоёРасширение"
|
||||
```
|
||||
|
||||
@@ -1,78 +1,78 @@
|
||||
---
|
||||
name: db-load-git
|
||||
description: Загрузка изменений из Git в базу 1С. Используй когда нужно загрузить изменения из гита, обновить базу из репозитория, partial load из коммита
|
||||
argument-hint: "[database] [source]"
|
||||
allowed-tools:
|
||||
- Bash
|
||||
- Read
|
||||
- Glob
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
# /db-load-git — Загрузка изменений из Git
|
||||
|
||||
Определяет изменённые файлы конфигурации по данным Git и выполняет частичную загрузку в информационную базу.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/db-load-git [database]
|
||||
/db-load-git dev — все незафиксированные изменения
|
||||
/db-load-git dev -Source Staged — только staged
|
||||
/db-load-git dev -Source Commit -CommitRange "HEAD~3..HEAD"
|
||||
/db-load-git dev -DryRun — только показать что будет загружено
|
||||
```
|
||||
|
||||
## Параметры подключения
|
||||
|
||||
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
||||
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||
4. Если ветка не совпала — используй `default`
|
||||
Если `v8path` не задан — автоопределение: `Get-ChildItem "C:\Program Files\1cv8\*\bin\1cv8.exe" | Sort -Desc | Select -First 1`
|
||||
Если файла нет — предложи `/db-list add`.
|
||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||
Если в записи базы указан `configSrc` — используй как каталог конфигурации.
|
||||
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/db-load-git/scripts/db-load-git.ps1 <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
|
||||
| Параметр | Обязательный | Описание |
|
||||
|----------|:------------:|----------|
|
||||
| `-V8Path <путь>` | нет | Каталог bin платформы (или полный путь к 1cv8.exe) |
|
||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||
| `-UserName <имя>` | нет | Имя пользователя |
|
||||
| `-Password <пароль>` | нет | Пароль |
|
||||
| `-ConfigDir <путь>` | да | Каталог XML-выгрузки (git-репозиторий) |
|
||||
| `-Source <источник>` | нет | `All` (по умолч.) / `Staged` / `Unstaged` / `Commit` |
|
||||
| `-CommitRange <range>` | для Commit | Диапазон коммитов (напр. `HEAD~3..HEAD`) |
|
||||
| `-Extension <имя>` | нет | Загрузить в расширение |
|
||||
| `-AllExtensions` | нет | Загрузить все расширения |
|
||||
| `-Format <формат>` | нет | `Hierarchical` (по умолч.) / `Plain` |
|
||||
| `-DryRun` | нет | Только показать что будет загружено (без загрузки) |
|
||||
| `-UpdateDB` | нет | После загрузки сразу обновить конфигурацию БД (`/UpdateDBCfg`) |
|
||||
|
||||
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
||||
|
||||
## После выполнения
|
||||
|
||||
1. Показать список загруженных файлов и результат из лога
|
||||
2. Если `-UpdateDB` не был указан — **предложить `/db-update`** для применения изменений к БД
|
||||
|
||||
## Примеры
|
||||
|
||||
```powershell
|
||||
# Все незафиксированные изменения
|
||||
powershell.exe -NoProfile -File .claude/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/skills/db-load-git/scripts/db-load-git.ps1 -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source Commit -CommitRange "HEAD~3..HEAD"
|
||||
```
|
||||
---
|
||||
name: db-load-git
|
||||
description: Загрузка изменений из Git в базу 1С. Используй когда нужно загрузить изменения из гита, обновить базу из репозитория, partial load из коммита
|
||||
argument-hint: "[database] [source]"
|
||||
allowed-tools:
|
||||
- Bash
|
||||
- Read
|
||||
- Glob
|
||||
- AskUserQuestion
|
||||
---
|
||||
|
||||
# /db-load-git — Загрузка изменений из Git
|
||||
|
||||
Определяет изменённые файлы конфигурации по данным Git и выполняет частичную загрузку в информационную базу.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/db-load-git [database]
|
||||
/db-load-git dev — все незафиксированные изменения
|
||||
/db-load-git dev -Source Staged — только staged
|
||||
/db-load-git dev -Source Commit -CommitRange "HEAD~3..HEAD"
|
||||
/db-load-git dev -DryRun — только показать что будет загружено
|
||||
```
|
||||
|
||||
## Параметры подключения
|
||||
|
||||
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу:
|
||||
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
|
||||
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
|
||||
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
|
||||
4. Если ветка не совпала — используй `default`
|
||||
Если `v8path` не задан — автоопределение: `Get-ChildItem "C:\Program Files\1cv8\*\bin\1cv8.exe" | Sort -Desc | Select -First 1`
|
||||
Если файла нет — предложи `/db-list add`.
|
||||
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
|
||||
Если в записи базы указан `configSrc` — используй как каталог конфигурации.
|
||||
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
|
||||
| Параметр | Обязательный | Описание |
|
||||
|----------|:------------:|----------|
|
||||
| `-V8Path <путь>` | нет | Каталог bin платформы (или полный путь к 1cv8.exe) |
|
||||
| `-InfoBasePath <путь>` | * | Файловая база |
|
||||
| `-InfoBaseServer <сервер>` | * | Сервер 1С (для серверной базы) |
|
||||
| `-InfoBaseRef <имя>` | * | Имя базы на сервере |
|
||||
| `-UserName <имя>` | нет | Имя пользователя |
|
||||
| `-Password <пароль>` | нет | Пароль |
|
||||
| `-ConfigDir <путь>` | да | Каталог XML-выгрузки (git-репозиторий) |
|
||||
| `-Source <источник>` | нет | `All` (по умолч.) / `Staged` / `Unstaged` / `Commit` |
|
||||
| `-CommitRange <range>` | для Commit | Диапазон коммитов (напр. `HEAD~3..HEAD`) |
|
||||
| `-Extension <имя>` | нет | Загрузить в расширение |
|
||||
| `-AllExtensions` | нет | Загрузить все расширения |
|
||||
| `-Format <формат>` | нет | `Hierarchical` (по умолч.) / `Plain` |
|
||||
| `-DryRun` | нет | Только показать что будет загружено (без загрузки) |
|
||||
| `-UpdateDB` | нет | После загрузки сразу обновить конфигурацию БД (`/UpdateDBCfg`) |
|
||||
|
||||
> `*` — нужен либо `-InfoBasePath`, либо пара `-InfoBaseServer` + `-InfoBaseRef`
|
||||
|
||||
## После выполнения
|
||||
|
||||
1. Показать список загруженных файлов и результат из лога
|
||||
2. Если `-UpdateDB` не был указан — **предложить `/db-update`** для применения изменений к БД
|
||||
|
||||
## Примеры
|
||||
|
||||
```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 "${CLAUDE_SKILL_DIR}/scripts/db-load-git.ps1" -InfoBasePath "C:\Bases\MyDB" -ConfigDir "C:\WS\cfsrc" -Source Commit -CommitRange "HEAD~3..HEAD"
|
||||
```
|
||||
|
||||
@@ -38,7 +38,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/db-load-xml/scripts/db-load-xml.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-load-xml.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -96,14 +96,14 @@ Documents/Заказ/Forms/ФормаДокумента.xml
|
||||
|
||||
```powershell
|
||||
# Полная загрузка
|
||||
powershell.exe -NoProfile -File .claude/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" -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/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\cfsrc" -Mode Partial -Files "Catalogs/Номенклатура.xml,Catalogs/Номенклатура/Ext/ObjectModule.bsl"
|
||||
|
||||
# Загрузка расширения
|
||||
powershell.exe -NoProfile -File .claude/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\ext_src" -Mode Full -Extension "МоёРасширение"
|
||||
|
||||
# Загрузка + обновление БД в одном запуске
|
||||
powershell.exe -NoProfile -File .claude/skills/db-load-xml/scripts/db-load-xml.ps1 -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -ConfigDir "C:\WS\cfsrc" -Mode Full -UpdateDB
|
||||
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
|
||||
```
|
||||
|
||||
@@ -36,7 +36,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/db-run/scripts/db-run.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -63,14 +63,14 @@ powershell.exe -NoProfile -File .claude/skills/db-run/scripts/db-run.ps1 <пар
|
||||
|
||||
```powershell
|
||||
# Простой запуск
|
||||
powershell.exe -NoProfile -File .claude/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"
|
||||
|
||||
# Запуск с обработкой
|
||||
powershell.exe -NoProfile -File .claude/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" -Execute "C:\epf\МояОбработка.epf"
|
||||
|
||||
# Открыть по навигационной ссылке
|
||||
powershell.exe -NoProfile -File .claude/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" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -URL "e1cib/data/Справочник.Номенклатура"
|
||||
|
||||
# Серверная база с параметром запуска
|
||||
powershell.exe -NoProfile -File .claude/skills/db-run/scripts/db-run.ps1 -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -CParam "ЗапуститьОбновление"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-run.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -CParam "ЗапуститьОбновление"
|
||||
```
|
||||
|
||||
@@ -35,7 +35,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/db-update/scripts/db-update.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -83,11 +83,11 @@ powershell.exe -NoProfile -File .claude/skills/db-update/scripts/db-update.ps1 <
|
||||
|
||||
```powershell
|
||||
# Обычное обновление (файловая база)
|
||||
powershell.exe -NoProfile -File .claude/skills/db-update/scripts/db-update.ps1 -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
||||
|
||||
# Динамическое обновление (серверная база)
|
||||
powershell.exe -NoProfile -File .claude/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" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -Dynamic "+"
|
||||
|
||||
# Обновление расширения
|
||||
powershell.exe -NoProfile -File .claude/skills/db-update/scripts/db-update.ps1 -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Extension "МоёРасширение"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/db-update.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin" -Extension "МоёРасширение"
|
||||
```
|
||||
|
||||
@@ -40,7 +40,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/epf-build/scripts/epf-build.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-build.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -62,8 +62,8 @@ powershell.exe -NoProfile -File .claude/skills/epf-build/scripts/epf-build.ps1 <
|
||||
|
||||
```powershell
|
||||
# Сборка обработки (файловая база)
|
||||
powershell.exe -NoProfile -File .claude/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" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МояОбработка.xml" -OutputFile "build/МояОбработка.epf"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File .claude/skills/epf-build/scripts/epf-build.ps1 -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -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"
|
||||
```
|
||||
|
||||
@@ -39,7 +39,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/epf-dump/scripts/epf-dump.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-dump.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -62,8 +62,8 @@ powershell.exe -NoProfile -File .claude/skills/epf-dump/scripts/epf-dump.ps1 <п
|
||||
|
||||
```powershell
|
||||
# Разборка обработки (файловая база)
|
||||
powershell.exe -NoProfile -File .claude/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" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МояОбработка.epf" -OutputDir "src"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File .claude/skills/epf-dump/scripts/epf-dump.ps1 -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -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"
|
||||
```
|
||||
|
||||
@@ -30,7 +30,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/epf-init/scripts/init.ps1 -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"]
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"]
|
||||
```
|
||||
|
||||
## Дальнейшие шаги
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# epf-init v1.0 — Init 1C external data processor scaffold
|
||||
# epf-init v1.1 — Init 1C external data processor scaffold
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -10,6 +10,8 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
$uuid1 = [guid]::NewGuid().ToString()
|
||||
$uuid2 = [guid]::NewGuid().ToString()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# epf-init v1.0 — Init 1C external data processor scaffold
|
||||
# epf-init v1.1 — Init 1C external data processor scaffold
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
"""Generates minimal XML source files for a 1C external data processor."""
|
||||
import sys, os, argparse, uuid
|
||||
|
||||
@@ -24,7 +24,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/epf-validate/scripts/epf-validate.ps1 -ObjectPath "src/МояОбработка"
|
||||
powershell.exe -NoProfile -File .claude/skills/epf-validate/scripts/epf-validate.ps1 -ObjectPath "src/МояОбработка/МояОбработка.xml"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/epf-validate.ps1" -ObjectPath "src/МояОбработка/МояОбработка.xml"
|
||||
```
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ allowed-tools:
|
||||
Используй общий скрипт из epf-build:
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/epf-build/scripts/epf-build.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-build/scripts/epf-build.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -64,8 +64,8 @@ powershell.exe -NoProfile -File .claude/skills/epf-build/scripts/epf-build.ps1 <
|
||||
|
||||
```powershell
|
||||
# Сборка отчёта (файловая база)
|
||||
powershell.exe -NoProfile -File .claude/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" -InfoBasePath "C:\Bases\MyDB" -SourceFile "src/МойОтчёт.xml" -OutputFile "build/МойОтчёт.erf"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File .claude/skills/epf-build/scripts/epf-build.ps1 -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -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"
|
||||
```
|
||||
|
||||
@@ -41,7 +41,7 @@ allowed-tools:
|
||||
Используй общий скрипт из epf-dump:
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/epf-dump/scripts/epf-dump.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-dump/scripts/epf-dump.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -64,8 +64,8 @@ powershell.exe -NoProfile -File .claude/skills/epf-dump/scripts/epf-dump.ps1 <п
|
||||
|
||||
```powershell
|
||||
# Разборка отчёта (файловая база)
|
||||
powershell.exe -NoProfile -File .claude/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" -InfoBasePath "C:\Bases\MyDB" -InputFile "build/МойОтчёт.erf" -OutputDir "src"
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File .claude/skills/epf-dump/scripts/epf-dump.ps1 -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret" -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"
|
||||
```
|
||||
|
||||
@@ -31,7 +31,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/erf-init/scripts/init.ps1 -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-WithSKD]
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/init.ps1" -Name "<Name>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-WithSKD]
|
||||
```
|
||||
|
||||
## Дальнейшие шаги
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# erf-init v1.0 — Init 1C external report scaffold
|
||||
# erf-init v1.1 — Init 1C external report scaffold
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -12,6 +12,8 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
$uuid1 = [guid]::NewGuid().ToString()
|
||||
$uuid2 = [guid]::NewGuid().ToString()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# erf-init v1.0 — Init 1C external report scaffold
|
||||
# erf-init v1.1 — Init 1C external report scaffold
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
"""Generates minimal XML source files for a 1C external report."""
|
||||
import sys, os, argparse, uuid
|
||||
|
||||
@@ -26,7 +26,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/epf-validate/scripts/epf-validate.ps1 -ObjectPath "src/МойОтчёт"
|
||||
powershell.exe -NoProfile -File .claude/skills/epf-validate/scripts/epf-validate.ps1 -ObjectPath "src/МойОтчёт/МойОтчёт.xml"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/../epf-validate/scripts/epf-validate.ps1" -ObjectPath "src/МойОтчёт/МойОтчёт.xml"
|
||||
```
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/form-add/scripts/form-add.ps1 -ObjectPath "<ObjectPath>" -FormName "<FormName>" [-Purpose "<Purpose>"] [-Synonym "<Synonym>"] [-SetDefault]
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-add.ps1" -ObjectPath "<ObjectPath>" -FormName "<FormName>" [-Purpose "<Purpose>"] [-Synonym "<Synonym>"] [-SetDefault]
|
||||
```
|
||||
|
||||
## Purpose — назначение формы
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# form-add v1.4 — Add managed form to 1C config object
|
||||
# form-add v1.5 — Add managed form to 1C config object
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -15,6 +15,8 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
# --- Detect XML format version ---
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# form-add v1.4 — Add managed form to 1C config object
|
||||
# form-add v1.5 — Add managed form to 1C config object
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
|
||||
@@ -29,10 +29,10 @@ allowed-tools:
|
||||
|
||||
```powershell
|
||||
# Режим JSON DSL
|
||||
powershell.exe -NoProfile -File .claude/skills/form-compile/scripts/form-compile.ps1 -JsonPath "<json>" -OutputPath "<Form.xml>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-compile.ps1" -JsonPath "<json>" -OutputPath "<Form.xml>"
|
||||
|
||||
# Режим from-object (объект и purpose выводятся из OutputPath; Document и Catalog)
|
||||
powershell.exe -NoProfile -File .claude/skills/form-compile/scripts/form-compile.ps1 -FromObject -OutputPath "<.../TypePlural/ObjectName/Forms/FormName/Ext/Form.xml>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-compile.ps1" -FromObject -OutputPath "<.../TypePlural/ObjectName/Forms/FormName/Ext/Form.xml>"
|
||||
```
|
||||
|
||||
## JSON DSL — справка
|
||||
@@ -62,8 +62,10 @@ powershell.exe -NoProfile -File .claude/skills/form-compile/scripts/form-compile
|
||||
| DSL ключ | XML элемент | Значение ключа |
|
||||
|--------------|-------------------|---------------------------------------------------|
|
||||
| `"group"` | UsualGroup | `"horizontal"` / `"vertical"` / `"alwaysHorizontal"` / `"alwaysVertical"` / `"collapsible"` |
|
||||
| `"columnGroup"` | ColumnGroup | `"horizontal"` / `"vertical"` / `"inCell"` — только внутри `columns` таблицы |
|
||||
| `"input"` | InputField | имя элемента |
|
||||
| `"check"` | CheckBoxField | имя |
|
||||
| `"radio"` | RadioButtonField | имя |
|
||||
| `"label"` | LabelDecoration | имя (текст задаётся через `title`) |
|
||||
| `"labelField"` | LabelField | имя |
|
||||
| `"table"` | Table | имя |
|
||||
@@ -97,7 +99,7 @@ powershell.exe -NoProfile -File .claude/skills/form-compile/scripts/form-compile
|
||||
|
||||
**input / picField**: `OnChange`, `StartChoice`, `ChoiceProcessing`, `AutoComplete`, `TextEditEnd`, `Clearing`, `Creating`, `EditTextChange`
|
||||
|
||||
**check**: `OnChange`
|
||||
**check / radio**: `OnChange`
|
||||
|
||||
**table**: `OnStartEdit`, `OnEditEnd`, `OnChange`, `Selection`, `ValueChoice`, `BeforeAddRow`, `BeforeDeleteRow`, `AfterDeleteRow`, `BeforeRowChange`, `BeforeEditEnd`, `OnActivateRow`, `OnActivateCell`, `Drag`, `DragStart`, `DragCheck`, `DragEnd`
|
||||
|
||||
@@ -125,7 +127,8 @@ powershell.exe -NoProfile -File .claude/skills/form-compile/scripts/form-compile
|
||||
| `skipOnInput: true` | Пропускать при обходе Tab | |
|
||||
| `inputHint` | Подсказка в пустом поле | `"Введите наименование..."` |
|
||||
| `width` / `height` | Размер | числа |
|
||||
| `autoMaxWidth: false` | Отключить авто-ширину | для фиксированных полей |
|
||||
| `autoMaxWidth: false` | Снять авто-ограничение ширины (поле растянется) | |
|
||||
| `maxWidth` / `maxHeight` | Жёсткое ограничение размера | числа; обычно вместе с `autoMaxWidth: false` |
|
||||
| `horizontalStretch: true` | Растягивать по ширине | |
|
||||
|
||||
### Чекбокс (check)
|
||||
@@ -135,6 +138,37 @@ powershell.exe -NoProfile -File .claude/skills/form-compile/scripts/form-compile
|
||||
| `path` | DataPath |
|
||||
| `titleLocation` | Размещение заголовка |
|
||||
|
||||
### Поле переключателя (radio)
|
||||
|
||||
Радиокнопки или тумблер для выбора одного значения из списка.
|
||||
|
||||
| Ключ | Описание | Пример |
|
||||
|------|----------|--------|
|
||||
| `path` | DataPath — привязка к реквизиту | `"СпособКурса"` |
|
||||
| `radioButtonType` | Вид переключателя | `"Auto"` (по умолчанию), `"RadioButtons"`, `"Tumbler"` |
|
||||
| `columnsCount` | Число колонок раскладки | `1`, `2`, ... |
|
||||
| `titleLocation` | Размещение заголовка | по умолчанию `"none"` |
|
||||
| `choiceList` | Список вариантов: массив `{value, presentation}` | см. ниже |
|
||||
|
||||
`choiceList[*]`:
|
||||
|
||||
| Ключ | Описание |
|
||||
|------|----------|
|
||||
| `value` | Значение варианта. Строка/число/булево; для перечисления — `"Enum.ИмяТипа.EnumValue.ИмяЗначения"` |
|
||||
| `presentation` | Текст рядом с переключателем. Строка (русский) либо объект `{ru, en, ...}` для мультиязычности |
|
||||
|
||||
```json
|
||||
{
|
||||
"radio": "СпособКурса",
|
||||
"path": "Объект.СпособУстановкиКурса",
|
||||
"radioButtonType": "Auto",
|
||||
"choiceList": [
|
||||
{ "value": "Enum.СпособыКурса.EnumValue.Авто", "presentation": { "ru": "Автоматически", "en": "Automatic" } },
|
||||
{ "value": "Enum.СпособыКурса.EnumValue.Ручной", "presentation": "вручную" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Надпись-декорация (label)
|
||||
|
||||
| Ключ | Описание |
|
||||
@@ -150,7 +184,8 @@ powershell.exe -NoProfile -File .claude/skills/form-compile/scripts/form-compile
|
||||
| Ключ | Описание |
|
||||
|------|----------|
|
||||
| `showTitle: true` | Показывать заголовок группы |
|
||||
| `united: false` | Не объединять рамку |
|
||||
| `united: false` | Левый край полей ввода выравнивается только в пределах этой группы (по умолчанию `true` — сквозное выравнивание по самому длинному заголовку, в т.ч. с соседними группами) |
|
||||
| `collapsed: true` | Только для `"group": "collapsible"` — группа создаётся свёрнутой |
|
||||
| `representation` | `"none"`, `"normal"`, `"weak"`, `"strong"` |
|
||||
| `children: [...]` | Вложенные элементы |
|
||||
|
||||
@@ -176,6 +211,35 @@ powershell.exe -NoProfile -File .claude/skills/form-compile/scripts/form-compile
|
||||
| `rowPictureDataPath` | Путь к картинке строки (напр. `"Список.DefaultPicture"`) |
|
||||
| `tableAutofill: false` | Управление Autofill внутреннего AutoCommandBar |
|
||||
|
||||
Колонки можно группировать через `columnGroup` (см. ниже).
|
||||
|
||||
### Группа колонок (columnGroup)
|
||||
|
||||
Используется только внутри `columns` таблицы. Значение ключа задаёт ориентацию: `"horizontal"`, `"vertical"`, `"inCell"` (склеивает колонки в одну ячейку шапки). Допускается вложение `columnGroup` в `columnGroup`.
|
||||
|
||||
| Ключ | Описание |
|
||||
|------|----------|
|
||||
| `name` | Имя элемента (рекомендуется задавать явно) |
|
||||
| `title` | Заголовок группы |
|
||||
| `showTitle: false` | Скрыть заголовок |
|
||||
| `showInHeader: true/false` | Показывать ли группу в шапке таблицы |
|
||||
| `width` | Ширина |
|
||||
| `horizontalStretch: false` | Растягивание |
|
||||
| `children: [...]` | Колонки внутри группы (`input`, `labelField`, `picField`, вложенный `columnGroup` …) |
|
||||
|
||||
```json
|
||||
{ "table": "Список", "path": "Список", "columns": [
|
||||
{ "columnGroup": "horizontal", "name": "ГруппаДата", "title": "Срок", "children": [
|
||||
{ "input": "СрокИсполнения", "path": "Список.СрокИсполнения" },
|
||||
{ "labelField": "Просрочено", "path": "Список.Просрочено" }
|
||||
]},
|
||||
{ "columnGroup": "inCell", "name": "ГруппаИсполнитель", "showInHeader": true, "children": [
|
||||
{ "input": "Исполнитель", "path": "Список.Исполнитель" }
|
||||
]},
|
||||
{ "input": "Комментарий", "path": "Список.Комментарий" }
|
||||
]}
|
||||
```
|
||||
|
||||
### Страницы (pages + page)
|
||||
|
||||
| Ключ (pages) | Описание |
|
||||
@@ -196,7 +260,7 @@ powershell.exe -NoProfile -File .claude/skills/form-compile/scripts/form-compile
|
||||
| `command` | Имя команды формы → `Form.Command.Имя` |
|
||||
| `stdCommand` | Стандартная команда: `"Close"` → `Form.StandardCommand.Close`; с точкой: `"Товары.Add"` → `Form.Item.Товары.StandardCommand.Add` |
|
||||
| `defaultButton: true` | Кнопка по умолчанию |
|
||||
| `type` | `"usual"`, `"hyperlink"`, `"commandBar"` |
|
||||
| `type` | `"usual"`, `"hyperlink"`. По умолчанию `"usual"`. Конкретный XML-вид (UsualButton/Hyperlink/CommandBarButton/CommandBarHyperlink) подставляется автоматически по контексту |
|
||||
| `picture` | Картинка кнопки |
|
||||
| `representation` | `"Auto"`, `"Text"`, `"Picture"`, `"PictureAndText"` |
|
||||
| `locationInCommandBar` | `"Auto"`, `"InCommandBar"`, `"InAdditionalSubmenu"` |
|
||||
@@ -227,6 +291,8 @@ powershell.exe -NoProfile -File .claude/skills/form-compile/scripts/form-compile
|
||||
]}
|
||||
```
|
||||
|
||||
Кнопки основных действий формы и подменю размещают здесь, а не в отдельной группе на форме. Отдельной кнопкой в layout — только если она логически привязана к конкретному полю или группе.
|
||||
|
||||
### Выпадающее меню (popup)
|
||||
|
||||
| Ключ | Описание |
|
||||
@@ -369,9 +435,9 @@ powershell.exe -NoProfile -File .claude/skills/form-compile/scripts/form-compile
|
||||
{ "check": "ПерваяСтрокаЗаголовок", "path": "ПерваяСтрокаЗаголовок" }
|
||||
]},
|
||||
{ "input": "Результат", "path": "Результат", "multiLine": true, "height": 8, "readOnly": true, "title": "Лог" },
|
||||
{ "group": "horizontal", "name": "ГруппаКнопок", "children": [
|
||||
{ "autoCmdBar": "ФормаКоманднаяПанель", "children": [
|
||||
{ "button": "Загрузить", "command": "Загрузить", "defaultButton": true },
|
||||
{ "button": "Закрыть", "stdCommand": "Close" }
|
||||
{ "button": "Закрыть", "stdCommand": "Close" }
|
||||
]}
|
||||
],
|
||||
"attributes": [
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# form-compile v1.9 — Compile 1C managed form from JSON or object metadata
|
||||
# form-compile v1.20 — Compile 1C managed form from JSON or object metadata
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[string]$JsonPath,
|
||||
@@ -668,6 +668,7 @@ function Generate-DocumentListDSL($meta, [hashtable]$p) {
|
||||
|
||||
$tableEl = [ordered]@{
|
||||
table = "Список"; path = "Список"
|
||||
rowPictureDataPath = "Список.DefaultPicture"
|
||||
commandBarLocation = "None"
|
||||
tableAutofill = $false
|
||||
columns = $columns
|
||||
@@ -1003,6 +1004,7 @@ function Generate-InformationRegisterListDSL($meta, [hashtable]$p) {
|
||||
|
||||
$tableEl = [ordered]@{
|
||||
table = "Список"; path = "Список"
|
||||
rowPictureDataPath = "Список.DefaultPicture"
|
||||
commandBarLocation = "None"
|
||||
tableAutofill = $false
|
||||
columns = $columns
|
||||
@@ -1060,6 +1062,7 @@ function Generate-AccumulationRegisterListDSL($meta, [hashtable]$p) {
|
||||
|
||||
$tableEl = [ordered]@{
|
||||
table = "Список"; path = "Список"
|
||||
rowPictureDataPath = "Список.DefaultPicture"
|
||||
commandBarLocation = "None"
|
||||
tableAutofill = $false
|
||||
columns = $columns
|
||||
@@ -1771,6 +1774,7 @@ function Get-ElementName {
|
||||
$script:knownEvents = @{
|
||||
"input" = @("OnChange","StartChoice","ChoiceProcessing","AutoComplete","TextEditEnd","Clearing","Creating","EditTextChange")
|
||||
"check" = @("OnChange")
|
||||
"radio" = @("OnChange")
|
||||
"label" = @("Click","URLProcessing")
|
||||
"labelField"= @("OnChange","StartChoice","ChoiceProcessing","Click","URLProcessing","Clearing")
|
||||
"table" = @("Selection","BeforeAddRow","AfterDeleteRow","BeforeDeleteRow","OnActivateRow","OnEditEnd","OnStartEdit","BeforeRowChange","BeforeEditEnd","ValueChoice","OnActivateCell","OnActivateField","Drag","DragStart","DragCheck","DragEnd","OnGetDataAtServer","BeforeLoadUserSettingsAtServer","OnUpdateUserSettingSetAtServer","OnChange")
|
||||
@@ -1821,11 +1825,47 @@ function Emit-Companion {
|
||||
}
|
||||
|
||||
function Emit-Element {
|
||||
param($el, [string]$indent)
|
||||
param($el, [string]$indent, [bool]$inCmdBar = $false)
|
||||
|
||||
# Silent synonyms: commandBar -> cmdBar, autoCommandBar -> autoCmdBar
|
||||
# (autoCmdBar inside def.elements is normally extracted in pre-pass; this is a safety net for nested cases)
|
||||
$synonyms = @{ "commandBar" = "cmdBar"; "autoCommandBar" = "autoCmdBar" }
|
||||
# Silent synonyms: model often writes XML name or Russian (ПолеПереключателя/RadioButtonField → radio).
|
||||
# Maps any synonym to canonical short DSL key.
|
||||
$synonyms = @{
|
||||
"commandBar" = "cmdBar"
|
||||
"autoCommandBar" = "autoCmdBar"
|
||||
"КоманднаяПанель" = "cmdBar"
|
||||
"InputField" = "input"
|
||||
"ПолеВвода" = "input"
|
||||
"CheckBoxField" = "check"
|
||||
"ПолеФлажка" = "check"
|
||||
"RadioButtonField" = "radio"
|
||||
"ПолеПереключателя" = "radio"
|
||||
"radioButton" = "radio"
|
||||
"PictureField" = "picField"
|
||||
"ПолеКартинки" = "picField"
|
||||
"LabelField" = "labelField"
|
||||
"ПолеНадписи" = "labelField"
|
||||
"CalendarField" = "calendar"
|
||||
"ПолеКалендаря" = "calendar"
|
||||
"LabelDecoration" = "label"
|
||||
"Надпись" = "label"
|
||||
"PictureDecoration" = "picture"
|
||||
"Картинка" = "picture"
|
||||
"UsualGroup" = "group"
|
||||
"Группа" = "group"
|
||||
"ОбычнаяГруппа" = "group"
|
||||
"ColumnGroup" = "columnGroup"
|
||||
"ГруппаКолонок" = "columnGroup"
|
||||
"Pages" = "pages"
|
||||
"ГруппаСтраниц" = "pages"
|
||||
"Page" = "page"
|
||||
"Страница" = "page"
|
||||
"Table" = "table"
|
||||
"Таблица" = "table"
|
||||
"Button" = "button"
|
||||
"Кнопка" = "button"
|
||||
"Popup" = "popup"
|
||||
"ВсплывающееМеню" = "popup"
|
||||
}
|
||||
foreach ($pair in $synonyms.GetEnumerator()) {
|
||||
if ($null -ne $el.PSObject.Properties[$pair.Key] -and $null -eq $el.PSObject.Properties[$pair.Value]) {
|
||||
$val = $el.($pair.Key)
|
||||
@@ -1838,7 +1878,7 @@ function Emit-Element {
|
||||
$typeKey = $null
|
||||
$xmlTag = $null
|
||||
|
||||
foreach ($key in @("group","input","check","label","labelField","table","pages","page","button","picture","picField","calendar","cmdBar","popup")) {
|
||||
foreach ($key in @("columnGroup","group","input","check","radio","label","labelField","table","pages","page","button","picture","picField","calendar","cmdBar","popup")) {
|
||||
if ($el.$key -ne $null) {
|
||||
$typeKey = $key
|
||||
break
|
||||
@@ -1853,8 +1893,12 @@ function Emit-Element {
|
||||
# Validate known keys — warn about typos and unknown properties
|
||||
$knownKeys = @{
|
||||
# type keys
|
||||
"group"=1;"input"=1;"check"=1;"label"=1;"labelField"=1;"table"=1;"pages"=1;"page"=1
|
||||
"group"=1;"columnGroup"=1;"input"=1;"check"=1;"radio"=1;"label"=1;"labelField"=1;"table"=1;"pages"=1;"page"=1
|
||||
"button"=1;"picture"=1;"picField"=1;"calendar"=1;"cmdBar"=1;"popup"=1
|
||||
# columnGroup-specific
|
||||
"showInHeader"=1
|
||||
# radio-specific
|
||||
"radioButtonType"=1;"choiceList"=1;"columnsCount"=1
|
||||
# naming & binding
|
||||
"name"=1;"path"=1;"title"=1
|
||||
# visibility & state
|
||||
@@ -1864,13 +1908,14 @@ function Emit-Element {
|
||||
# layout
|
||||
"titleLocation"=1;"representation"=1;"width"=1;"height"=1
|
||||
"horizontalStretch"=1;"verticalStretch"=1;"autoMaxWidth"=1;"autoMaxHeight"=1
|
||||
"maxWidth"=1;"maxHeight"=1
|
||||
# input-specific
|
||||
"multiLine"=1;"passwordMode"=1;"choiceButton"=1;"clearButton"=1
|
||||
"spinButton"=1;"dropListButton"=1;"markIncomplete"=1;"skipOnInput"=1;"inputHint"=1
|
||||
# label/hyperlink
|
||||
"hyperlink"=1
|
||||
# group-specific
|
||||
"showTitle"=1;"united"=1
|
||||
"showTitle"=1;"united"=1;"collapsed"=1
|
||||
# hierarchy
|
||||
"children"=1;"columns"=1
|
||||
# table-specific
|
||||
@@ -1898,14 +1943,16 @@ function Emit-Element {
|
||||
|
||||
switch ($typeKey) {
|
||||
"group" { Emit-Group -el $el -name $name -id $id -indent $indent }
|
||||
"columnGroup" { Emit-ColumnGroup -el $el -name $name -id $id -indent $indent }
|
||||
"input" { Emit-Input -el $el -name $name -id $id -indent $indent }
|
||||
"check" { Emit-Check -el $el -name $name -id $id -indent $indent }
|
||||
"radio" { Emit-Radio -el $el -name $name -id $id -indent $indent }
|
||||
"label" { Emit-Label -el $el -name $name -id $id -indent $indent }
|
||||
"labelField" { Emit-LabelField -el $el -name $name -id $id -indent $indent }
|
||||
"table" { Emit-Table -el $el -name $name -id $id -indent $indent }
|
||||
"pages" { Emit-Pages -el $el -name $name -id $id -indent $indent }
|
||||
"page" { Emit-Page -el $el -name $name -id $id -indent $indent }
|
||||
"button" { Emit-Button -el $el -name $name -id $id -indent $indent }
|
||||
"button" { Emit-Button -el $el -name $name -id $id -indent $indent -inCmdBar $inCmdBar }
|
||||
"picture" { Emit-PictureDecoration -el $el -name $name -id $id -indent $indent }
|
||||
"picField" { Emit-PictureField -el $el -name $name -id $id -indent $indent }
|
||||
"calendar" { Emit-Calendar -el $el -name $name -id $id -indent $indent }
|
||||
@@ -1926,10 +1973,34 @@ function Emit-CommonFlags {
|
||||
if ($el.readOnly -eq $true) { X "$indent<ReadOnly>true</ReadOnly>" }
|
||||
}
|
||||
|
||||
function Title-FromName {
|
||||
param([string]$name)
|
||||
if (-not $name) { return '' }
|
||||
$s = [regex]::Replace($name, '([А-ЯA-Z])([А-ЯA-Z][а-яa-z])', '$1 $2')
|
||||
$s = [regex]::Replace($s, '([а-яa-z0-9])([А-ЯA-Z])', '$1 $2')
|
||||
$parts = $s -split ' '
|
||||
if ($parts.Count -eq 0) { return $s }
|
||||
$out = New-Object System.Collections.ArrayList
|
||||
[void]$out.Add($parts[0])
|
||||
for ($i = 1; $i -lt $parts.Count; $i++) {
|
||||
$p = $parts[$i]
|
||||
if ($p.Length -gt 1 -and $p -ceq $p.ToUpper()) {
|
||||
[void]$out.Add($p)
|
||||
} else {
|
||||
[void]$out.Add($p.ToLower())
|
||||
}
|
||||
}
|
||||
return ($out -join ' ')
|
||||
}
|
||||
|
||||
function Emit-Title {
|
||||
param($el, [string]$name, [string]$indent)
|
||||
if ($el.title) {
|
||||
Emit-MLText -tag "Title" -text "$($el.title)" -indent $indent
|
||||
param($el, [string]$name, [string]$indent, [switch]$auto)
|
||||
$title = $el.title
|
||||
if (-not $title -and $auto -and $name) {
|
||||
$title = Title-FromName -name $name
|
||||
}
|
||||
if ($title) {
|
||||
Emit-MLText -tag "Title" -text "$title" -indent $indent
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1956,6 +2027,7 @@ function Emit-Group {
|
||||
if ($groupVal -eq "collapsible") {
|
||||
X "$inner<Group>Vertical</Group>"
|
||||
X "$inner<Behavior>Collapsible</Behavior>"
|
||||
if ($el.collapsed -eq $true) { X "$inner<Collapsed>true</Collapsed>" }
|
||||
}
|
||||
|
||||
# Representation
|
||||
@@ -1993,6 +2065,48 @@ function Emit-Group {
|
||||
X "$indent</UsualGroup>"
|
||||
}
|
||||
|
||||
function Emit-ColumnGroup {
|
||||
param($el, [string]$name, [int]$id, [string]$indent)
|
||||
|
||||
X "$indent<ColumnGroup name=`"$name`" id=`"$id`">"
|
||||
$inner = "$indent`t"
|
||||
|
||||
Emit-Title -el $el -name $name -indent $inner
|
||||
|
||||
# Group orientation (horizontal / vertical / inCell — последнее только здесь)
|
||||
$groupVal = "$($el.columnGroup)"
|
||||
$orientation = switch ($groupVal) {
|
||||
"horizontal" { "Horizontal" }
|
||||
"vertical" { "Vertical" }
|
||||
"inCell" { "InCell" }
|
||||
default { $null }
|
||||
}
|
||||
if ($orientation) { X "$inner<Group>$orientation</Group>" }
|
||||
|
||||
if ($el.showTitle -eq $false) { X "$inner<ShowTitle>false</ShowTitle>" }
|
||||
if ($null -ne $el.showInHeader) {
|
||||
$shVal = if ($el.showInHeader) { "true" } else { "false" }
|
||||
X "$inner<ShowInHeader>$shVal</ShowInHeader>"
|
||||
}
|
||||
if ($el.width) { X "$inner<Width>$($el.width)</Width>" }
|
||||
|
||||
Emit-CommonFlags -el $el -indent $inner
|
||||
|
||||
# Companion: ExtendedTooltip
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
|
||||
# Children
|
||||
if ($el.children -and $el.children.Count -gt 0) {
|
||||
X "$inner<ChildItems>"
|
||||
foreach ($child in $el.children) {
|
||||
Emit-Element -el $child -indent "$inner`t"
|
||||
}
|
||||
X "$inner</ChildItems>"
|
||||
}
|
||||
|
||||
X "$indent</ColumnGroup>"
|
||||
}
|
||||
|
||||
function Emit-Input {
|
||||
param($el, [string]$name, [int]$id, [string]$indent)
|
||||
|
||||
@@ -2001,7 +2115,7 @@ function Emit-Input {
|
||||
|
||||
if ($el.path) { X "$inner<DataPath>$($el.path)</DataPath>" }
|
||||
|
||||
Emit-Title -el $el -name $name -indent $inner
|
||||
Emit-Title -el $el -name $name -indent $inner -auto:(-not $el.path)
|
||||
Emit-CommonFlags -el $el -indent $inner
|
||||
|
||||
if ($el.titleLocation) {
|
||||
@@ -2024,8 +2138,15 @@ function Emit-Input {
|
||||
if ($el.dropListButton -eq $true) { X "$inner<DropListButton>true</DropListButton>" }
|
||||
if ($el.markIncomplete -eq $true) { X "$inner<AutoMarkIncomplete>true</AutoMarkIncomplete>" }
|
||||
if ($el.skipOnInput -eq $true) { X "$inner<SkipOnInput>true</SkipOnInput>" }
|
||||
if ($el.autoMaxWidth -eq $false) { X "$inner<AutoMaxWidth>false</AutoMaxWidth>" }
|
||||
$hasAmw = $el.PSObject.Properties.Name -contains 'autoMaxWidth'
|
||||
if ($hasAmw) {
|
||||
if ($el.autoMaxWidth -eq $false) { X "$inner<AutoMaxWidth>false</AutoMaxWidth>" }
|
||||
} elseif ($el.multiLine -eq $true) {
|
||||
X "$inner<AutoMaxWidth>false</AutoMaxWidth>"
|
||||
}
|
||||
if ($null -ne $el.maxWidth) { X "$inner<MaxWidth>$($el.maxWidth)</MaxWidth>" }
|
||||
if ($el.autoMaxHeight -eq $false) { X "$inner<AutoMaxHeight>false</AutoMaxHeight>" }
|
||||
if ($null -ne $el.maxHeight) { X "$inner<MaxHeight>$($el.maxHeight)</MaxHeight>" }
|
||||
if ($el.width) { X "$inner<Width>$($el.width)</Width>" }
|
||||
if ($el.height) { X "$inner<Height>$($el.height)</Height>" }
|
||||
if ($el.horizontalStretch -eq $true) { X "$inner<HorizontalStretch>true</HorizontalStretch>" }
|
||||
@@ -2052,12 +2173,11 @@ function Emit-Check {
|
||||
|
||||
if ($el.path) { X "$inner<DataPath>$($el.path)</DataPath>" }
|
||||
|
||||
Emit-Title -el $el -name $name -indent $inner
|
||||
Emit-Title -el $el -name $name -indent $inner -auto:(-not $el.path)
|
||||
Emit-CommonFlags -el $el -indent $inner
|
||||
|
||||
if ($el.titleLocation) {
|
||||
X "$inner<TitleLocation>$($el.titleLocation)</TitleLocation>"
|
||||
}
|
||||
$tl = if ($el.titleLocation) { "$($el.titleLocation)" } else { "Right" }
|
||||
X "$inner<TitleLocation>$tl</TitleLocation>"
|
||||
|
||||
# Companions
|
||||
Emit-Companion -tag "ContextMenu" -name "${name}КонтекстноеМеню" -indent $inner
|
||||
@@ -2068,18 +2188,237 @@ function Emit-Check {
|
||||
X "$indent</CheckBoxField>"
|
||||
}
|
||||
|
||||
# Maps Russian/English root of a typed reference path to canonical English root.
|
||||
# Used to normalize ChoiceList values like "Перечисление.X.Y" → "Enum.X.EnumValue.Y".
|
||||
$script:refRootSynonyms = @{
|
||||
"Перечисление" = "Enum"
|
||||
"Справочник" = "Catalog"
|
||||
"Документ" = "Document"
|
||||
"ПланСчетов" = "ChartOfAccounts"
|
||||
"ПланВидовХарактеристик" = "ChartOfCharacteristicTypes"
|
||||
"ПланВидовРасчета" = "ChartOfCalculationTypes"
|
||||
"ПланВидовРасчёта" = "ChartOfCalculationTypes"
|
||||
"ПланОбмена" = "ExchangePlan"
|
||||
"БизнесПроцесс" = "BusinessProcess"
|
||||
"Задача" = "Task"
|
||||
"РегистрСведений" = "InformationRegister"
|
||||
"РегистрНакопления" = "AccumulationRegister"
|
||||
"РегистрБухгалтерии" = "AccountingRegister"
|
||||
"РегистрРасчета" = "CalculationRegister"
|
||||
"РегистрРасчёта" = "CalculationRegister"
|
||||
}
|
||||
$script:enumValueSynonyms = @("EnumValue","ЗначениеПеречисления")
|
||||
|
||||
# Normalize a choiceList item value: returns @{ XsiType = "..."; Text = "..." }
|
||||
function Normalize-ChoiceValue {
|
||||
param($value)
|
||||
|
||||
# Booleans
|
||||
if ($value -is [bool]) {
|
||||
return @{ XsiType = "xs:boolean"; Text = if ($value) { "true" } else { "false" } }
|
||||
}
|
||||
# Numbers (int / decimal / double)
|
||||
if ($value -is [int] -or $value -is [long] -or $value -is [double] -or $value -is [decimal]) {
|
||||
return @{ XsiType = "xs:decimal"; Text = "$value" }
|
||||
}
|
||||
|
||||
$s = "$value"
|
||||
if ([string]::IsNullOrEmpty($s)) {
|
||||
return @{ XsiType = "xs:string"; Text = "" }
|
||||
}
|
||||
|
||||
# Try to detect typed reference path: "<Root>.<Type>[.<Member>.<Value>]"
|
||||
$parts = $s -split '\.'
|
||||
if ($parts.Count -ge 2) {
|
||||
$root = $parts[0]
|
||||
$canonRoot = $null
|
||||
if ($script:refRootSynonyms.ContainsKey($root)) { $canonRoot = $script:refRootSynonyms[$root] }
|
||||
elseif ($script:refRootSynonyms.Values -contains $root) { $canonRoot = $root }
|
||||
|
||||
if ($canonRoot) {
|
||||
$typeName = $parts[1]
|
||||
$normalized = $null
|
||||
|
||||
if ($canonRoot -eq "Enum") {
|
||||
if ($parts.Count -eq 2) {
|
||||
# "Enum.X" alone — not a value, treat as string
|
||||
} elseif ($parts.Count -eq 3) {
|
||||
# "Enum.X.Y" — insert .EnumValue.
|
||||
$normalized = "Enum.$typeName.EnumValue.$($parts[2])"
|
||||
} else {
|
||||
# "Enum.X.<member>.Y..." — replace member with EnumValue (handles ЗначениеПеречисления too)
|
||||
$member = $parts[2]
|
||||
if ($script:enumValueSynonyms -contains $member) {
|
||||
$rest = $parts[3..($parts.Count-1)] -join '.'
|
||||
$normalized = "Enum.$typeName.EnumValue.$rest"
|
||||
} else {
|
||||
$rest = $parts[2..($parts.Count-1)] -join '.'
|
||||
$normalized = "Enum.$typeName.EnumValue.$rest"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# Other ref roots: just translate root, keep tail as-is
|
||||
if ($parts.Count -ge 3) {
|
||||
$tail = $parts[1..($parts.Count-1)] -join '.'
|
||||
$normalized = "$canonRoot.$tail"
|
||||
}
|
||||
}
|
||||
|
||||
if ($normalized) {
|
||||
return @{ XsiType = "xr:DesignTimeRef"; Text = $normalized }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return @{ XsiType = "xs:string"; Text = $s }
|
||||
}
|
||||
|
||||
# Emit Presentation block for a choiceList item.
|
||||
# Accepts string (ru only), or hashtable/PSCustomObject {ru, en, ...}.
|
||||
# Empty/null → emits empty <Presentation/>.
|
||||
function Emit-ChoicePresentation {
|
||||
param($pres, [string]$indent)
|
||||
if ($null -eq $pres -or ($pres -is [string] -and [string]::IsNullOrEmpty($pres))) {
|
||||
X "$indent<Presentation/>"
|
||||
return
|
||||
}
|
||||
|
||||
$pairs = @()
|
||||
if ($pres -is [string]) {
|
||||
$pairs += ,@("ru", $pres)
|
||||
} elseif ($pres -is [hashtable] -or $pres -is [System.Collections.IDictionary]) {
|
||||
foreach ($k in $pres.Keys) { $pairs += ,@("$k", "$($pres[$k])") }
|
||||
} elseif ($pres.PSObject -and $pres.PSObject.Properties) {
|
||||
foreach ($p in $pres.PSObject.Properties) { $pairs += ,@("$($p.Name)", "$($p.Value)") }
|
||||
} else {
|
||||
$pairs += ,@("ru", "$pres")
|
||||
}
|
||||
|
||||
X "$indent<Presentation>"
|
||||
foreach ($pair in $pairs) {
|
||||
X "$indent`t<v8:item>"
|
||||
X "$indent`t`t<v8:lang>$($pair[0])</v8:lang>"
|
||||
X "$indent`t`t<v8:content>$(Esc-Xml $pair[1])</v8:content>"
|
||||
X "$indent`t</v8:item>"
|
||||
}
|
||||
X "$indent</Presentation>"
|
||||
}
|
||||
|
||||
function Emit-Radio {
|
||||
param($el, [string]$name, [int]$id, [string]$indent)
|
||||
|
||||
X "$indent<RadioButtonField name=`"$name`" id=`"$id`">"
|
||||
$inner = "$indent`t"
|
||||
|
||||
if ($el.path) { X "$inner<DataPath>$($el.path)</DataPath>" }
|
||||
|
||||
Emit-Title -el $el -name $name -indent $inner -auto:(-not $el.path)
|
||||
Emit-CommonFlags -el $el -indent $inner
|
||||
|
||||
# TitleLocation default is None for radio (matches typical configurator behavior)
|
||||
$tl = if ($el.titleLocation) {
|
||||
switch ("$($el.titleLocation)") {
|
||||
"none" { "None" }
|
||||
"left" { "Left" }
|
||||
"right" { "Right" }
|
||||
"top" { "Top" }
|
||||
"bottom" { "Bottom" }
|
||||
default { "$($el.titleLocation)" }
|
||||
}
|
||||
} else { "None" }
|
||||
X "$inner<TitleLocation>$tl</TitleLocation>"
|
||||
|
||||
# RadioButtonType: Auto | RadioButtons | Tumbler. Accept synonyms.
|
||||
$rbtRaw = if ($el.radioButtonType) { "$($el.radioButtonType)".Trim() } else { "Auto" }
|
||||
$rbt = switch -Regex ($rbtRaw.ToLower()) {
|
||||
'^(auto|авто)$' { "Auto"; break }
|
||||
'^(radiobuttons?|переключатель|радио)$' { "RadioButtons"; break }
|
||||
'^(tumbler|тумблер)$' { "Tumbler"; break }
|
||||
default { $rbtRaw }
|
||||
}
|
||||
X "$inner<RadioButtonType>$rbt</RadioButtonType>"
|
||||
|
||||
if ($null -ne $el.columnsCount) {
|
||||
X "$inner<ColumnsCount>$($el.columnsCount)</ColumnsCount>"
|
||||
}
|
||||
|
||||
# ChoiceList
|
||||
if ($el.choiceList -and $el.choiceList.Count -gt 0) {
|
||||
X "$inner<ChoiceList>"
|
||||
$itemIndent = "$inner`t"
|
||||
foreach ($item in $el.choiceList) {
|
||||
# Pull value (and tolerate Russian synonym "значение")
|
||||
$valRaw = $null
|
||||
if ($item -is [hashtable] -or $item -is [System.Collections.IDictionary]) {
|
||||
if ($item.Contains("value")) { $valRaw = $item["value"] }
|
||||
elseif ($item.Contains("значение")) { $valRaw = $item["значение"] }
|
||||
} else {
|
||||
if ($item.PSObject.Properties["value"]) { $valRaw = $item.value }
|
||||
elseif ($item.PSObject.Properties["значение"]) { $valRaw = $item."значение" }
|
||||
}
|
||||
|
||||
# Pull presentation (presentation OR title synonym)
|
||||
$presRaw = $null
|
||||
$hasPres = $false
|
||||
if ($item -is [hashtable] -or $item -is [System.Collections.IDictionary]) {
|
||||
if ($item.Contains("presentation")) { $presRaw = $item["presentation"]; $hasPres = $true }
|
||||
elseif ($item.Contains("представление")) { $presRaw = $item["представление"]; $hasPres = $true }
|
||||
elseif ($item.Contains("title")) { $presRaw = $item["title"]; $hasPres = $true }
|
||||
} else {
|
||||
if ($item.PSObject.Properties["presentation"]) { $presRaw = $item.presentation; $hasPres = $true }
|
||||
elseif ($item.PSObject.Properties["представление"]) { $presRaw = $item."представление"; $hasPres = $true }
|
||||
elseif ($item.PSObject.Properties["title"]) { $presRaw = $item.title; $hasPres = $true }
|
||||
}
|
||||
|
||||
$norm = Normalize-ChoiceValue -value $valRaw
|
||||
|
||||
# Auto-derive presentation if missing
|
||||
if (-not $hasPres) {
|
||||
if ($norm.XsiType -eq "xr:DesignTimeRef") {
|
||||
$tail = ($norm.Text -split '\.')[-1]
|
||||
$presRaw = Title-FromName -name $tail
|
||||
} elseif ($norm.XsiType -eq "xs:string") {
|
||||
$presRaw = $norm.Text
|
||||
} else {
|
||||
$presRaw = $norm.Text
|
||||
}
|
||||
}
|
||||
|
||||
X "$itemIndent<xr:Item>"
|
||||
$valIndent = "$itemIndent`t"
|
||||
X "$valIndent<xr:Presentation/>"
|
||||
X "$valIndent<xr:CheckState>0</xr:CheckState>"
|
||||
X "$valIndent<xr:Value xsi:type=`"FormChoiceListDesTimeValue`">"
|
||||
Emit-ChoicePresentation -pres $presRaw -indent "$valIndent`t"
|
||||
X "$valIndent`t<Value xsi:type=`"$($norm.XsiType)`">$(Esc-Xml $norm.Text)</Value>"
|
||||
X "$valIndent</xr:Value>"
|
||||
X "$itemIndent</xr:Item>"
|
||||
}
|
||||
X "$inner</ChoiceList>"
|
||||
}
|
||||
|
||||
# Companions
|
||||
Emit-Companion -tag "ContextMenu" -name "${name}КонтекстноеМеню" -indent $inner
|
||||
Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner
|
||||
|
||||
Emit-Events -el $el -elementName $name -indent $inner -typeKey "radio"
|
||||
|
||||
X "$indent</RadioButtonField>"
|
||||
}
|
||||
|
||||
function Emit-Label {
|
||||
param($el, [string]$name, [int]$id, [string]$indent)
|
||||
|
||||
X "$indent<LabelDecoration name=`"$name`" id=`"$id`">"
|
||||
$inner = "$indent`t"
|
||||
|
||||
if ($el.title) {
|
||||
$labelTitle = if ($el.title) { "$($el.title)" } else { Title-FromName -name $name }
|
||||
if ($labelTitle) {
|
||||
$formatted = if ($el.hyperlink -eq $true) { "true" } else { "false" }
|
||||
X "$inner<Title formatted=`"$formatted`">"
|
||||
X "$inner`t<v8:item>"
|
||||
X "$inner`t`t<v8:lang>ru</v8:lang>"
|
||||
X "$inner`t`t<v8:content>$(Esc-Xml "$($el.title)")</v8:content>"
|
||||
X "$inner`t`t<v8:content>$(Esc-Xml "$labelTitle")</v8:content>"
|
||||
X "$inner`t</v8:item>"
|
||||
X "$inner</Title>"
|
||||
}
|
||||
@@ -2088,7 +2427,9 @@ function Emit-Label {
|
||||
|
||||
if ($el.hyperlink -eq $true) { X "$inner<Hyperlink>true</Hyperlink>" }
|
||||
if ($el.autoMaxWidth -eq $false) { X "$inner<AutoMaxWidth>false</AutoMaxWidth>" }
|
||||
if ($null -ne $el.maxWidth) { X "$inner<MaxWidth>$($el.maxWidth)</MaxWidth>" }
|
||||
if ($el.autoMaxHeight -eq $false) { X "$inner<AutoMaxHeight>false</AutoMaxHeight>" }
|
||||
if ($null -ne $el.maxHeight) { X "$inner<MaxHeight>$($el.maxHeight)</MaxHeight>" }
|
||||
if ($el.width) { X "$inner<Width>$($el.width)</Width>" }
|
||||
if ($el.height) { X "$inner<Height>$($el.height)</Height>" }
|
||||
|
||||
@@ -2109,7 +2450,7 @@ function Emit-LabelField {
|
||||
|
||||
if ($el.path) { X "$inner<DataPath>$($el.path)</DataPath>" }
|
||||
|
||||
Emit-Title -el $el -name $name -indent $inner
|
||||
Emit-Title -el $el -name $name -indent $inner -auto:(-not $el.path)
|
||||
Emit-CommonFlags -el $el -indent $inner
|
||||
|
||||
if ($el.hyperlink -eq $true) { X "$inner<Hyperlink>true</Hyperlink>" }
|
||||
@@ -2131,7 +2472,7 @@ function Emit-Table {
|
||||
|
||||
if ($el.path) { X "$inner<DataPath>$($el.path)</DataPath>" }
|
||||
|
||||
Emit-Title -el $el -name $name -indent $inner
|
||||
Emit-Title -el $el -name $name -indent $inner -auto:(-not $el.path)
|
||||
Emit-CommonFlags -el $el -indent $inner
|
||||
|
||||
if ($el.representation) {
|
||||
@@ -2220,7 +2561,7 @@ function Emit-Page {
|
||||
X "$indent<Page name=`"$name`" id=`"$id`">"
|
||||
$inner = "$indent`t"
|
||||
|
||||
Emit-Title -el $el -name $name -indent $inner
|
||||
Emit-Title -el $el -name $name -indent $inner -auto
|
||||
Emit-CommonFlags -el $el -indent $inner
|
||||
|
||||
if ($el.group) {
|
||||
@@ -2250,19 +2591,48 @@ function Emit-Page {
|
||||
}
|
||||
|
||||
function Emit-Button {
|
||||
param($el, [string]$name, [int]$id, [string]$indent)
|
||||
param($el, [string]$name, [int]$id, [string]$indent, [bool]$inCmdBar = $false)
|
||||
|
||||
X "$indent<Button name=`"$name`" id=`"$id`">"
|
||||
$inner = "$indent`t"
|
||||
|
||||
# Type
|
||||
# Type — context-aware:
|
||||
# Inside command bar (cmdBar/autoCmdBar/popup) only CommandBarButton/CommandBarHyperlink are valid.
|
||||
# UsualButton/Hyperlink would be silently ignored by 1C.
|
||||
$btnType = $null
|
||||
if ($el.type) {
|
||||
$btnType = switch ("$($el.type)") {
|
||||
"usual" { "UsualButton" }
|
||||
"hyperlink" { "Hyperlink" }
|
||||
"commandBar" { "CommandBarButton" }
|
||||
default { "$($el.type)" }
|
||||
$rawType = "$($el.type)"
|
||||
if ($inCmdBar) {
|
||||
# Be forgiving: any "ordinary button" hint resolves to CommandBarButton,
|
||||
# any "hyperlink" hint resolves to CommandBarHyperlink. The model can pass
|
||||
# either DSL ("usual"/"hyperlink") or XML names — all map to the right kind.
|
||||
switch ($rawType) {
|
||||
"usual" { $btnType = "CommandBarButton" }
|
||||
"UsualButton" { $btnType = "CommandBarButton" }
|
||||
"commandBar" { $btnType = "CommandBarButton" }
|
||||
"CommandBarButton" { $btnType = "CommandBarButton" }
|
||||
"hyperlink" { $btnType = "CommandBarHyperlink" }
|
||||
"Hyperlink" { $btnType = "CommandBarHyperlink" }
|
||||
"CommandBarHyperlink" { $btnType = "CommandBarHyperlink" }
|
||||
default { $btnType = $rawType }
|
||||
}
|
||||
} else {
|
||||
# Symmetric: any "ordinary button" hint → UsualButton, any "hyperlink" → Hyperlink.
|
||||
switch ($rawType) {
|
||||
"usual" { $btnType = "UsualButton" }
|
||||
"UsualButton" { $btnType = "UsualButton" }
|
||||
"commandBar" { $btnType = "UsualButton" }
|
||||
"CommandBarButton" { $btnType = "UsualButton" }
|
||||
"hyperlink" { $btnType = "Hyperlink" }
|
||||
"Hyperlink" { $btnType = "Hyperlink" }
|
||||
"CommandBarHyperlink" { $btnType = "Hyperlink" }
|
||||
default { $btnType = $rawType }
|
||||
}
|
||||
}
|
||||
} elseif ($inCmdBar) {
|
||||
$btnType = "CommandBarButton"
|
||||
}
|
||||
if ($btnType) {
|
||||
X "$inner<Type>$btnType</Type>"
|
||||
}
|
||||
|
||||
@@ -2279,7 +2649,8 @@ function Emit-Button {
|
||||
}
|
||||
}
|
||||
|
||||
Emit-Title -el $el -name $name -indent $inner
|
||||
$btnAuto = -not ($el.command -or $el.stdCommand)
|
||||
Emit-Title -el $el -name $name -indent $inner -auto:$btnAuto
|
||||
Emit-CommonFlags -el $el -indent $inner
|
||||
|
||||
if ($el.defaultButton -eq $true) { X "$inner<DefaultButton>true</DefaultButton>" }
|
||||
@@ -2369,7 +2740,7 @@ function Emit-Calendar {
|
||||
|
||||
if ($el.path) { X "$inner<DataPath>$($el.path)</DataPath>" }
|
||||
|
||||
Emit-Title -el $el -name $name -indent $inner
|
||||
Emit-Title -el $el -name $name -indent $inner -auto:(-not $el.path)
|
||||
Emit-CommonFlags -el $el -indent $inner
|
||||
|
||||
# Companions
|
||||
@@ -2395,7 +2766,7 @@ function Emit-CommandBar {
|
||||
if ($el.children -and $el.children.Count -gt 0) {
|
||||
X "$inner<ChildItems>"
|
||||
foreach ($child in $el.children) {
|
||||
Emit-Element -el $child -indent "$inner`t"
|
||||
Emit-Element -el $child -indent "$inner`t" -inCmdBar $true
|
||||
}
|
||||
X "$inner</ChildItems>"
|
||||
}
|
||||
@@ -2409,7 +2780,7 @@ function Emit-Popup {
|
||||
X "$indent<Popup name=`"$name`" id=`"$id`">"
|
||||
$inner = "$indent`t"
|
||||
|
||||
Emit-Title -el $el -name $name -indent $inner
|
||||
Emit-Title -el $el -name $name -indent $inner -auto
|
||||
Emit-CommonFlags -el $el -indent $inner
|
||||
|
||||
if ($el.picture) {
|
||||
@@ -2427,7 +2798,7 @@ function Emit-Popup {
|
||||
if ($el.children -and $el.children.Count -gt 0) {
|
||||
X "$inner<ChildItems>"
|
||||
foreach ($child in $el.children) {
|
||||
Emit-Element -el $child -indent "$inner`t"
|
||||
Emit-Element -el $child -indent "$inner`t" -inCmdBar $true
|
||||
}
|
||||
X "$inner</ChildItems>"
|
||||
}
|
||||
@@ -2450,8 +2821,9 @@ function Emit-Attributes {
|
||||
X "$indent`t<Attribute name=`"$attrName`" id=`"$attrId`">"
|
||||
$inner = "$indent`t`t"
|
||||
|
||||
if ($attr.title) {
|
||||
Emit-MLText -tag "Title" -text "$($attr.title)" -indent $inner
|
||||
$attrTitle = if ($attr.title) { "$($attr.title)" } elseif ($attr.main -ne $true) { Title-FromName -name $attrName } else { '' }
|
||||
if ($attrTitle) {
|
||||
Emit-MLText -tag "Title" -text "$attrTitle" -indent $inner
|
||||
}
|
||||
|
||||
# Type
|
||||
@@ -2464,7 +2836,11 @@ function Emit-Attributes {
|
||||
if ($attr.main -eq $true) {
|
||||
X "$inner<MainAttribute>true</MainAttribute>"
|
||||
}
|
||||
if ($attr.savedData -eq $true) {
|
||||
$mainSaved = $false
|
||||
if ($attr.main -eq $true -and $attr.type) {
|
||||
$mainSaved = ("$($attr.type)") -match '^(CatalogObject|DocumentObject|ChartOfAccountsObject|ChartOfCalculationTypesObject|ChartOfCharacteristicTypesObject|ExchangePlanObject|BusinessProcessObject|TaskObject)\.' -or ("$($attr.type)") -match 'RecordManager\.'
|
||||
}
|
||||
if ($attr.savedData -eq $true -or $mainSaved) {
|
||||
X "$inner<SavedData>true</SavedData>"
|
||||
}
|
||||
if ($attr.fillChecking) {
|
||||
@@ -2539,8 +2915,9 @@ function Emit-Commands {
|
||||
X "$indent`t<Command name=`"$($cmd.name)`" id=`"$cmdId`">"
|
||||
$inner = "$indent`t`t"
|
||||
|
||||
if ($cmd.title) {
|
||||
Emit-MLText -tag "Title" -text "$($cmd.title)" -indent $inner
|
||||
$cmdTitle = if ($cmd.title) { "$($cmd.title)" } else { Title-FromName -name "$($cmd.name)" }
|
||||
if ($cmdTitle) {
|
||||
Emit-MLText -tag "Title" -text "$cmdTitle" -indent $inner
|
||||
}
|
||||
|
||||
if ($cmd.action) {
|
||||
@@ -2649,7 +3026,7 @@ function HasCmdBarRecursive {
|
||||
}
|
||||
|
||||
function ApplyDynamicListTableHeuristic {
|
||||
param($el, [string]$listName)
|
||||
param($el, [string]$listName, [bool]$hasMainTable)
|
||||
if ($null -eq $el) { return }
|
||||
if ($el.PSObject.Properties["table"] -and $null -ne $el.table -and "$($el.path)" -eq $listName) {
|
||||
if ($null -eq $el.PSObject.Properties["tableAutofill"]) {
|
||||
@@ -2658,9 +3035,13 @@ function ApplyDynamicListTableHeuristic {
|
||||
if ($null -eq $el.PSObject.Properties["commandBarLocation"]) {
|
||||
$el | Add-Member -NotePropertyName "commandBarLocation" -NotePropertyValue "None" -Force
|
||||
}
|
||||
# DefaultPicture доступен только если у DynamicList есть основная таблица
|
||||
if ($hasMainTable -and ($null -eq $el.PSObject.Properties["rowPictureDataPath"] -or [string]::IsNullOrEmpty("$($el.rowPictureDataPath)"))) {
|
||||
$el | Add-Member -NotePropertyName "rowPictureDataPath" -NotePropertyValue "$listName.DefaultPicture" -Force
|
||||
}
|
||||
}
|
||||
if ($el.PSObject.Properties["children"] -and $el.children) {
|
||||
foreach ($child in $el.children) { ApplyDynamicListTableHeuristic $child $listName }
|
||||
foreach ($child in $el.children) { ApplyDynamicListTableHeuristic $child $listName $hasMainTable }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2749,8 +3130,17 @@ if ($def.attributes -and $def.elements) {
|
||||
if ($attr.main -eq $true) { $mainAttr = $attr; break }
|
||||
}
|
||||
if ($mainAttr -and "$($mainAttr.type)" -eq "DynamicList") {
|
||||
$mt = $null
|
||||
if ($mainAttr.PSObject.Properties["settings"] -and $null -ne $mainAttr.settings) {
|
||||
if ($mainAttr.settings -is [hashtable]) {
|
||||
if ($mainAttr.settings.ContainsKey("mainTable")) { $mt = $mainAttr.settings["mainTable"] }
|
||||
} elseif ($mainAttr.settings.PSObject.Properties["mainTable"]) {
|
||||
$mt = $mainAttr.settings.mainTable
|
||||
}
|
||||
}
|
||||
$hasMt = -not [string]::IsNullOrEmpty("$mt")
|
||||
foreach ($el in $def.elements) {
|
||||
ApplyDynamicListTableHeuristic $el $mainAttr.name
|
||||
ApplyDynamicListTableHeuristic $el $mainAttr.name $hasMt
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2802,17 +3192,26 @@ if ($formTitle) {
|
||||
}
|
||||
|
||||
# 12b. Properties (skip 'title' — handled above as multilingual)
|
||||
# When form-level Title is set, default autoTitle=false (≈95% of ERP forms do this;
|
||||
# otherwise platform appends synonym → "Title: Synonym" double-titles).
|
||||
$propsClone = New-Object PSObject
|
||||
$hasAutoTitle = $false
|
||||
if ($def.properties) {
|
||||
foreach ($p in $def.properties.PSObject.Properties) {
|
||||
if ($p.Name -eq "autoTitle") { $hasAutoTitle = $true }
|
||||
}
|
||||
}
|
||||
if ($formTitle -and -not $hasAutoTitle) {
|
||||
$propsClone | Add-Member -NotePropertyName "autoTitle" -NotePropertyValue $false
|
||||
}
|
||||
if ($def.properties) {
|
||||
$propsClone = New-Object PSObject
|
||||
foreach ($p in $def.properties.PSObject.Properties) {
|
||||
if ($p.Name -ne "title") {
|
||||
$propsClone | Add-Member -NotePropertyName $p.Name -NotePropertyValue $p.Value
|
||||
}
|
||||
}
|
||||
Emit-Properties -props $propsClone -indent "`t"
|
||||
} else {
|
||||
Emit-Properties -props $null -indent "`t"
|
||||
}
|
||||
Emit-Properties -props $propsClone -indent "`t"
|
||||
|
||||
# 12c. CommandSet (excluded commands)
|
||||
if ($def.excludedCommands -and $def.excludedCommands.Count -gt 0) {
|
||||
@@ -2847,7 +3246,7 @@ if ($acbHasInner) {
|
||||
if ($hasAcbChildren) {
|
||||
X "`t`t<ChildItems>"
|
||||
foreach ($child in $script:mainAcbDef.children) {
|
||||
Emit-Element -el $child -indent "`t`t`t"
|
||||
Emit-Element -el $child -indent "`t`t`t" -inCmdBar $true
|
||||
}
|
||||
X "`t`t</ChildItems>"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# form-compile v1.9 — Compile 1C managed form from JSON or object metadata
|
||||
# form-compile v1.20 — Compile 1C managed form from JSON or object metadata
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import copy
|
||||
@@ -625,6 +625,7 @@ def generate_document_list_dsl(meta, p):
|
||||
|
||||
table_el = OrderedDict([
|
||||
('table', '\u0421\u043f\u0438\u0441\u043e\u043a'), ('path', '\u0421\u043f\u0438\u0441\u043e\u043a'),
|
||||
('rowPictureDataPath', '\u0421\u043f\u0438\u0441\u043e\u043a.DefaultPicture'),
|
||||
('commandBarLocation', 'None'),
|
||||
('tableAutofill', False),
|
||||
('columns', columns),
|
||||
@@ -938,6 +939,7 @@ def generate_information_register_list_dsl(meta, p):
|
||||
table_el = OrderedDict([
|
||||
('table', '\u0421\u043f\u0438\u0441\u043e\u043a'),
|
||||
('path', '\u0421\u043f\u0438\u0441\u043e\u043a'),
|
||||
('rowPictureDataPath', '\u0421\u043f\u0438\u0441\u043e\u043a.DefaultPicture'),
|
||||
('commandBarLocation', 'None'),
|
||||
('tableAutofill', False),
|
||||
('columns', columns_list),
|
||||
@@ -996,6 +998,7 @@ def generate_accumulation_register_list_dsl(meta, p):
|
||||
table_el = OrderedDict([
|
||||
('table', '\u0421\u043f\u0438\u0441\u043e\u043a'),
|
||||
('path', '\u0421\u043f\u0438\u0441\u043e\u043a'),
|
||||
('rowPictureDataPath', '\u0421\u043f\u0438\u0441\u043e\u043a.DefaultPicture'),
|
||||
('commandBarLocation', 'None'),
|
||||
('tableAutofill', False),
|
||||
('columns', columns_list),
|
||||
@@ -1311,6 +1314,7 @@ EVENT_SUFFIX_MAP = {
|
||||
KNOWN_EVENTS = {
|
||||
"input": ["OnChange", "StartChoice", "ChoiceProcessing", "AutoComplete", "TextEditEnd", "Clearing", "Creating", "EditTextChange"],
|
||||
"check": ["OnChange"],
|
||||
"radio": ["OnChange"],
|
||||
"label": ["Click", "URLProcessing"],
|
||||
"labelField": ["OnChange", "StartChoice", "ChoiceProcessing", "Click", "URLProcessing", "Clearing"],
|
||||
"table": ["Selection", "BeforeAddRow", "AfterDeleteRow", "BeforeDeleteRow", "OnActivateRow", "OnEditEnd", "OnStartEdit", "BeforeRowChange", "BeforeEditEnd", "ValueChoice", "OnActivateCell", "OnActivateField", "Drag", "DragStart", "DragCheck", "DragEnd", "OnGetDataAtServer", "BeforeLoadUserSettingsAtServer", "OnUpdateUserSettingSetAtServer", "OnChange"],
|
||||
@@ -1334,17 +1338,20 @@ KNOWN_FORM_EVENTS = [
|
||||
]
|
||||
|
||||
KNOWN_KEYS = {
|
||||
"group", "input", "check", "label", "labelField", "table", "pages", "page",
|
||||
"group", "columnGroup", "input", "check", "radio", "label", "labelField", "table", "pages", "page",
|
||||
"button", "picture", "picField", "calendar", "cmdBar", "popup",
|
||||
"showInHeader",
|
||||
"radioButtonType", "choiceList", "columnsCount",
|
||||
"name", "path", "title",
|
||||
"visible", "hidden", "enabled", "disabled", "readOnly", "userVisible",
|
||||
"on", "handlers",
|
||||
"titleLocation", "representation", "width", "height",
|
||||
"horizontalStretch", "verticalStretch", "autoMaxWidth", "autoMaxHeight",
|
||||
"maxWidth", "maxHeight",
|
||||
"multiLine", "passwordMode", "choiceButton", "clearButton",
|
||||
"spinButton", "dropListButton", "markIncomplete", "skipOnInput", "inputHint",
|
||||
"hyperlink",
|
||||
"showTitle", "united",
|
||||
"showTitle", "united", "collapsed",
|
||||
"children", "columns",
|
||||
"changeRowSet", "changeRowOrder", "header", "footer",
|
||||
"commandBarLocation", "searchStringLocation",
|
||||
@@ -1356,9 +1363,147 @@ KNOWN_KEYS = {
|
||||
"rowPictureDataPath", "tableAutofill",
|
||||
}
|
||||
|
||||
TYPE_KEYS = ["group", "input", "check", "label", "labelField", "table", "pages", "page",
|
||||
TYPE_KEYS = ["columnGroup", "group", "input", "check", "radio", "label", "labelField", "table", "pages", "page",
|
||||
"button", "picture", "picField", "calendar", "cmdBar", "popup"]
|
||||
|
||||
# Synonyms: model often writes XML name or Russian (ПолеПереключателя/RadioButtonField → radio)
|
||||
ELEMENT_TYPE_SYNONYMS = {
|
||||
"commandBar": "cmdBar",
|
||||
"autoCommandBar": "autoCmdBar",
|
||||
"КоманднаяПанель": "cmdBar",
|
||||
"InputField": "input",
|
||||
"ПолеВвода": "input",
|
||||
"CheckBoxField": "check",
|
||||
"ПолеФлажка": "check",
|
||||
"RadioButtonField": "radio",
|
||||
"ПолеПереключателя": "radio",
|
||||
"radioButton": "radio",
|
||||
"PictureField": "picField",
|
||||
"ПолеКартинки": "picField",
|
||||
"LabelField": "labelField",
|
||||
"ПолеНадписи": "labelField",
|
||||
"CalendarField": "calendar",
|
||||
"ПолеКалендаря": "calendar",
|
||||
"LabelDecoration": "label",
|
||||
"Надпись": "label",
|
||||
"PictureDecoration": "picture",
|
||||
"Картинка": "picture",
|
||||
"UsualGroup": "group",
|
||||
"Группа": "group",
|
||||
"ОбычнаяГруппа": "group",
|
||||
"ColumnGroup": "columnGroup",
|
||||
"ГруппаКолонок": "columnGroup",
|
||||
"Pages": "pages",
|
||||
"ГруппаСтраниц": "pages",
|
||||
"Page": "page",
|
||||
"Страница": "page",
|
||||
"Table": "table",
|
||||
"Таблица": "table",
|
||||
"Button": "button",
|
||||
"Кнопка": "button",
|
||||
"Popup": "popup",
|
||||
"ВсплывающееМеню": "popup",
|
||||
}
|
||||
|
||||
# Maps Russian/English root of typed reference path to canonical English root
|
||||
REF_ROOT_SYNONYMS = {
|
||||
"Перечисление": "Enum",
|
||||
"Справочник": "Catalog",
|
||||
"Документ": "Document",
|
||||
"ПланСчетов": "ChartOfAccounts",
|
||||
"ПланВидовХарактеристик": "ChartOfCharacteristicTypes",
|
||||
"ПланВидовРасчета": "ChartOfCalculationTypes",
|
||||
"ПланВидовРасчёта": "ChartOfCalculationTypes",
|
||||
"ПланОбмена": "ExchangePlan",
|
||||
"БизнесПроцесс": "BusinessProcess",
|
||||
"Задача": "Task",
|
||||
"РегистрСведений": "InformationRegister",
|
||||
"РегистрНакопления": "AccumulationRegister",
|
||||
"РегистрБухгалтерии": "AccountingRegister",
|
||||
"РегистрРасчета": "CalculationRegister",
|
||||
"РегистрРасчёта": "CalculationRegister",
|
||||
}
|
||||
ENUM_VALUE_SYNONYMS = {"EnumValue", "ЗначениеПеречисления"}
|
||||
|
||||
|
||||
def normalize_choice_value(value):
|
||||
"""Returns dict {xsi_type, text} for a choiceList item value."""
|
||||
if isinstance(value, bool):
|
||||
return {"xsi_type": "xs:boolean", "text": "true" if value else "false"}
|
||||
if isinstance(value, (int, float)):
|
||||
return {"xsi_type": "xs:decimal", "text": str(value)}
|
||||
|
||||
s = "" if value is None else str(value)
|
||||
if not s:
|
||||
return {"xsi_type": "xs:string", "text": ""}
|
||||
|
||||
parts = s.split(".")
|
||||
if len(parts) >= 2:
|
||||
root = parts[0]
|
||||
canon_root = None
|
||||
if root in REF_ROOT_SYNONYMS:
|
||||
canon_root = REF_ROOT_SYNONYMS[root]
|
||||
elif root in REF_ROOT_SYNONYMS.values():
|
||||
canon_root = root
|
||||
|
||||
if canon_root:
|
||||
type_name = parts[1]
|
||||
normalized = None
|
||||
if canon_root == "Enum":
|
||||
if len(parts) == 3:
|
||||
normalized = f"Enum.{type_name}.EnumValue.{parts[2]}"
|
||||
elif len(parts) >= 4:
|
||||
member = parts[2]
|
||||
if member in ENUM_VALUE_SYNONYMS:
|
||||
rest = ".".join(parts[3:])
|
||||
else:
|
||||
rest = ".".join(parts[2:])
|
||||
normalized = f"Enum.{type_name}.EnumValue.{rest}"
|
||||
else:
|
||||
if len(parts) >= 3:
|
||||
tail = ".".join(parts[1:])
|
||||
normalized = f"{canon_root}.{tail}"
|
||||
|
||||
if normalized:
|
||||
return {"xsi_type": "xr:DesignTimeRef", "text": normalized}
|
||||
|
||||
return {"xsi_type": "xs:string", "text": s}
|
||||
|
||||
|
||||
def emit_choice_presentation(lines, pres, indent):
|
||||
"""Accepts None/empty → <Presentation/>; str → ru only; dict → multi-lang."""
|
||||
if pres is None or (isinstance(pres, str) and pres == ""):
|
||||
lines.append(f"{indent}<Presentation/>")
|
||||
return
|
||||
|
||||
if isinstance(pres, str):
|
||||
pairs = [("ru", pres)]
|
||||
elif isinstance(pres, dict):
|
||||
pairs = [(str(k), str(v)) for k, v in pres.items()]
|
||||
else:
|
||||
pairs = [("ru", str(pres))]
|
||||
|
||||
lines.append(f"{indent}<Presentation>")
|
||||
for lang, content in pairs:
|
||||
lines.append(f"{indent}\t<v8:item>")
|
||||
lines.append(f"{indent}\t\t<v8:lang>{lang}</v8:lang>")
|
||||
lines.append(f"{indent}\t\t<v8:content>{esc_xml(content)}</v8:content>")
|
||||
lines.append(f"{indent}\t</v8:item>")
|
||||
lines.append(f"{indent}</Presentation>")
|
||||
|
||||
|
||||
def normalize_radio_button_type(raw):
|
||||
if not raw:
|
||||
return "Auto"
|
||||
s = str(raw).strip().lower()
|
||||
if s in ("auto", "авто"):
|
||||
return "Auto"
|
||||
if s in ("radiobutton", "radiobuttons", "переключатель", "радио"):
|
||||
return "RadioButtons"
|
||||
if s in ("tumbler", "тумблер"):
|
||||
return "Tumbler"
|
||||
return str(raw).strip()
|
||||
|
||||
|
||||
def get_handler_name(element_name, event_name):
|
||||
suffix = EVENT_SUFFIX_MAP.get(event_name)
|
||||
@@ -1414,9 +1559,27 @@ def emit_common_flags(lines, el, indent):
|
||||
lines.append(f"{indent}<ReadOnly>true</ReadOnly>")
|
||||
|
||||
|
||||
def emit_title(lines, el, name, indent):
|
||||
if el.get('title'):
|
||||
emit_mltext(lines, indent, 'Title', str(el['title']))
|
||||
def title_from_name(name):
|
||||
"""СуммаДокумента → 'Сумма документа'. НДСВключен → 'НДС включен'."""
|
||||
if not name:
|
||||
return ''
|
||||
s = re.sub(r'([А-ЯA-Z])([А-ЯA-Z][а-яa-z])', r'\1 \2', name)
|
||||
s = re.sub(r'([а-яa-z0-9])([А-ЯA-Z])', r'\1 \2', s)
|
||||
parts = s.split(' ')
|
||||
if not parts:
|
||||
return s
|
||||
out = [parts[0]]
|
||||
for p in parts[1:]:
|
||||
out.append(p if (len(p) > 1 and p.isupper()) else p.lower())
|
||||
return ' '.join(out)
|
||||
|
||||
|
||||
def emit_title(lines, el, name, indent, auto=False):
|
||||
title = el.get('title')
|
||||
if not title and auto and name:
|
||||
title = title_from_name(name)
|
||||
if title:
|
||||
emit_mltext(lines, indent, 'Title', str(title))
|
||||
|
||||
|
||||
# --- Type emitter ---
|
||||
@@ -1601,10 +1764,9 @@ def emit_type(lines, type_str, indent):
|
||||
|
||||
# --- Element emitters ---
|
||||
|
||||
def emit_element(lines, el, indent):
|
||||
# Silent synonyms (safety net; top-level autoCmdBar is normally extracted in pre-pass)
|
||||
_synonyms = {'commandBar': 'cmdBar', 'autoCommandBar': 'autoCmdBar'}
|
||||
for src, dst in _synonyms.items():
|
||||
def emit_element(lines, el, indent, in_cmd_bar=False):
|
||||
# Silent synonyms: model often writes XML name or Russian (ПолеПереключателя/RadioButtonField → radio)
|
||||
for src, dst in ELEMENT_TYPE_SYNONYMS.items():
|
||||
if src in el and dst not in el:
|
||||
el[dst] = el.pop(src)
|
||||
|
||||
@@ -1628,8 +1790,10 @@ def emit_element(lines, el, indent):
|
||||
|
||||
emitters = {
|
||||
'group': emit_group,
|
||||
'columnGroup': emit_column_group,
|
||||
'input': emit_input,
|
||||
'check': emit_check,
|
||||
'radio': emit_radio_button_field,
|
||||
'label': emit_label,
|
||||
'labelField': emit_label_field,
|
||||
'table': emit_table,
|
||||
@@ -1645,7 +1809,10 @@ def emit_element(lines, el, indent):
|
||||
|
||||
emitter = emitters.get(type_key)
|
||||
if emitter:
|
||||
emitter(lines, el, name, eid, indent)
|
||||
if type_key == 'button':
|
||||
emitter(lines, el, name, eid, indent, in_cmd_bar=in_cmd_bar)
|
||||
else:
|
||||
emitter(lines, el, name, eid, indent)
|
||||
|
||||
|
||||
def emit_group(lines, el, name, eid, indent):
|
||||
@@ -1670,6 +1837,8 @@ def emit_group(lines, el, name, eid, indent):
|
||||
if group_val == 'collapsible':
|
||||
lines.append(f'{inner}<Group>Vertical</Group>')
|
||||
lines.append(f'{inner}<Behavior>Collapsible</Behavior>')
|
||||
if el.get('collapsed') is True:
|
||||
lines.append(f'{inner}<Collapsed>true</Collapsed>')
|
||||
|
||||
# Representation
|
||||
if el.get('representation'):
|
||||
@@ -1705,6 +1874,43 @@ def emit_group(lines, el, name, eid, indent):
|
||||
lines.append(f'{indent}</UsualGroup>')
|
||||
|
||||
|
||||
def emit_column_group(lines, el, name, eid, indent):
|
||||
lines.append(f'{indent}<ColumnGroup name="{name}" id="{eid}">')
|
||||
inner = f'{indent}\t'
|
||||
|
||||
emit_title(lines, el, name, inner)
|
||||
|
||||
group_val = str(el.get('columnGroup', ''))
|
||||
orientation_map = {
|
||||
'horizontal': 'Horizontal',
|
||||
'vertical': 'Vertical',
|
||||
'inCell': 'InCell',
|
||||
}
|
||||
orientation = orientation_map.get(group_val)
|
||||
if orientation:
|
||||
lines.append(f'{inner}<Group>{orientation}</Group>')
|
||||
|
||||
if el.get('showTitle') is False:
|
||||
lines.append(f'{inner}<ShowTitle>false</ShowTitle>')
|
||||
if el.get('showInHeader') is not None:
|
||||
sh_val = 'true' if el['showInHeader'] else 'false'
|
||||
lines.append(f'{inner}<ShowInHeader>{sh_val}</ShowInHeader>')
|
||||
if el.get('width'):
|
||||
lines.append(f'{inner}<Width>{el["width"]}</Width>')
|
||||
|
||||
emit_common_flags(lines, el, inner)
|
||||
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}РасширеннаяПодсказка', inner)
|
||||
|
||||
if el.get('children') and len(el['children']) > 0:
|
||||
lines.append(f'{inner}<ChildItems>')
|
||||
for child in el['children']:
|
||||
emit_element(lines, child, f'{inner}\t')
|
||||
lines.append(f'{inner}</ChildItems>')
|
||||
|
||||
lines.append(f'{indent}</ColumnGroup>')
|
||||
|
||||
|
||||
def emit_input(lines, el, name, eid, indent):
|
||||
lines.append(f'{indent}<InputField name="{name}" id="{eid}">')
|
||||
inner = f'{indent}\t'
|
||||
@@ -1712,7 +1918,7 @@ def emit_input(lines, el, name, eid, indent):
|
||||
if el.get('path'):
|
||||
lines.append(f'{inner}<DataPath>{el["path"]}</DataPath>')
|
||||
|
||||
emit_title(lines, el, name, inner)
|
||||
emit_title(lines, el, name, inner, auto=not el.get('path'))
|
||||
emit_common_flags(lines, el, inner)
|
||||
|
||||
if el.get('titleLocation'):
|
||||
@@ -1736,10 +1942,17 @@ def emit_input(lines, el, name, eid, indent):
|
||||
lines.append(f'{inner}<AutoMarkIncomplete>true</AutoMarkIncomplete>')
|
||||
if el.get('skipOnInput') is True:
|
||||
lines.append(f'{inner}<SkipOnInput>true</SkipOnInput>')
|
||||
if el.get('autoMaxWidth') is False:
|
||||
if 'autoMaxWidth' in el:
|
||||
if el['autoMaxWidth'] is False:
|
||||
lines.append(f'{inner}<AutoMaxWidth>false</AutoMaxWidth>')
|
||||
elif el.get('multiLine') is True:
|
||||
lines.append(f'{inner}<AutoMaxWidth>false</AutoMaxWidth>')
|
||||
if el.get('maxWidth') is not None:
|
||||
lines.append(f'{inner}<MaxWidth>{el["maxWidth"]}</MaxWidth>')
|
||||
if el.get('autoMaxHeight') is False:
|
||||
lines.append(f'{inner}<AutoMaxHeight>false</AutoMaxHeight>')
|
||||
if el.get('maxHeight') is not None:
|
||||
lines.append(f'{inner}<MaxHeight>{el["maxHeight"]}</MaxHeight>')
|
||||
if el.get('width'):
|
||||
lines.append(f'{inner}<Width>{el["width"]}</Width>')
|
||||
if el.get('height'):
|
||||
@@ -1768,11 +1981,11 @@ def emit_check(lines, el, name, eid, indent):
|
||||
if el.get('path'):
|
||||
lines.append(f'{inner}<DataPath>{el["path"]}</DataPath>')
|
||||
|
||||
emit_title(lines, el, name, inner)
|
||||
emit_title(lines, el, name, inner, auto=not el.get('path'))
|
||||
emit_common_flags(lines, el, inner)
|
||||
|
||||
if el.get('titleLocation'):
|
||||
lines.append(f'{inner}<TitleLocation>{el["titleLocation"]}</TitleLocation>')
|
||||
tl = el.get('titleLocation') or 'Right'
|
||||
lines.append(f'{inner}<TitleLocation>{tl}</TitleLocation>')
|
||||
|
||||
# Companions
|
||||
emit_companion(lines, 'ContextMenu', f'{name}\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u043e\u0435\u041c\u0435\u043d\u044e', inner)
|
||||
@@ -1783,16 +1996,80 @@ def emit_check(lines, el, name, eid, indent):
|
||||
lines.append(f'{indent}</CheckBoxField>')
|
||||
|
||||
|
||||
def emit_radio_button_field(lines, el, name, eid, indent):
|
||||
lines.append(f'{indent}<RadioButtonField name="{name}" id="{eid}">')
|
||||
inner = f'{indent}\t'
|
||||
|
||||
if el.get('path'):
|
||||
lines.append(f'{inner}<DataPath>{el["path"]}</DataPath>')
|
||||
|
||||
emit_title(lines, el, name, inner, auto=not el.get('path'))
|
||||
emit_common_flags(lines, el, inner)
|
||||
|
||||
tl_raw = el.get('titleLocation')
|
||||
if tl_raw:
|
||||
loc_map = {'none': 'None', 'left': 'Left', 'right': 'Right', 'top': 'Top', 'bottom': 'Bottom'}
|
||||
tl = loc_map.get(str(tl_raw), str(tl_raw))
|
||||
else:
|
||||
tl = 'None'
|
||||
lines.append(f'{inner}<TitleLocation>{tl}</TitleLocation>')
|
||||
|
||||
rbt = normalize_radio_button_type(el.get('radioButtonType'))
|
||||
lines.append(f'{inner}<RadioButtonType>{rbt}</RadioButtonType>')
|
||||
|
||||
if el.get('columnsCount') is not None:
|
||||
lines.append(f'{inner}<ColumnsCount>{el["columnsCount"]}</ColumnsCount>')
|
||||
|
||||
choice_list = el.get('choiceList') or []
|
||||
if choice_list:
|
||||
lines.append(f'{inner}<ChoiceList>')
|
||||
item_indent = f'{inner}\t'
|
||||
for item in choice_list:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
val_raw = item.get('value', item.get('значение'))
|
||||
has_pres = any(k in item for k in ('presentation', 'представление', 'title'))
|
||||
pres_raw = item.get('presentation', item.get('представление', item.get('title')))
|
||||
|
||||
norm = normalize_choice_value(val_raw)
|
||||
|
||||
if not has_pres:
|
||||
if norm['xsi_type'] == 'xr:DesignTimeRef':
|
||||
tail = norm['text'].split('.')[-1]
|
||||
pres_raw = title_from_name(tail)
|
||||
else:
|
||||
pres_raw = norm['text']
|
||||
|
||||
lines.append(f'{item_indent}<xr:Item>')
|
||||
val_indent = f'{item_indent}\t'
|
||||
lines.append(f'{val_indent}<xr:Presentation/>')
|
||||
lines.append(f'{val_indent}<xr:CheckState>0</xr:CheckState>')
|
||||
lines.append(f'{val_indent}<xr:Value xsi:type="FormChoiceListDesTimeValue">')
|
||||
emit_choice_presentation(lines, pres_raw, f'{val_indent}\t')
|
||||
lines.append(f'{val_indent}\t<Value xsi:type="{norm["xsi_type"]}">{esc_xml(norm["text"])}</Value>')
|
||||
lines.append(f'{val_indent}</xr:Value>')
|
||||
lines.append(f'{item_indent}</xr:Item>')
|
||||
lines.append(f'{inner}</ChoiceList>')
|
||||
|
||||
emit_companion(lines, 'ContextMenu', f'{name}КонтекстноеМеню', inner)
|
||||
emit_companion(lines, 'ExtendedTooltip', f'{name}РасширеннаяПодсказка', inner)
|
||||
|
||||
emit_events(lines, el, name, inner, 'radio')
|
||||
|
||||
lines.append(f'{indent}</RadioButtonField>')
|
||||
|
||||
|
||||
def emit_label(lines, el, name, eid, indent):
|
||||
lines.append(f'{indent}<LabelDecoration name="{name}" id="{eid}">')
|
||||
inner = f'{indent}\t'
|
||||
|
||||
if el.get('title'):
|
||||
label_title = el.get('title') or title_from_name(name)
|
||||
if label_title:
|
||||
formatted = 'true' if el.get('hyperlink') is True else 'false'
|
||||
lines.append(f'{inner}<Title formatted="{formatted}">')
|
||||
lines.append(f'{inner}\t<v8:item>')
|
||||
lines.append(f'{inner}\t\t<v8:lang>ru</v8:lang>')
|
||||
lines.append(f'{inner}\t\t<v8:content>{esc_xml(str(el["title"]))}</v8:content>')
|
||||
lines.append(f'{inner}\t\t<v8:content>{esc_xml(str(label_title))}</v8:content>')
|
||||
lines.append(f'{inner}\t</v8:item>')
|
||||
lines.append(f'{inner}</Title>')
|
||||
|
||||
@@ -1802,8 +2079,12 @@ def emit_label(lines, el, name, eid, indent):
|
||||
lines.append(f'{inner}<Hyperlink>true</Hyperlink>')
|
||||
if el.get('autoMaxWidth') is False:
|
||||
lines.append(f'{inner}<AutoMaxWidth>false</AutoMaxWidth>')
|
||||
if el.get('maxWidth') is not None:
|
||||
lines.append(f'{inner}<MaxWidth>{el["maxWidth"]}</MaxWidth>')
|
||||
if el.get('autoMaxHeight') is False:
|
||||
lines.append(f'{inner}<AutoMaxHeight>false</AutoMaxHeight>')
|
||||
if el.get('maxHeight') is not None:
|
||||
lines.append(f'{inner}<MaxHeight>{el["maxHeight"]}</MaxHeight>')
|
||||
if el.get('width'):
|
||||
lines.append(f'{inner}<Width>{el["width"]}</Width>')
|
||||
if el.get('height'):
|
||||
@@ -1825,7 +2106,7 @@ def emit_label_field(lines, el, name, eid, indent):
|
||||
if el.get('path'):
|
||||
lines.append(f'{inner}<DataPath>{el["path"]}</DataPath>')
|
||||
|
||||
emit_title(lines, el, name, inner)
|
||||
emit_title(lines, el, name, inner, auto=not el.get('path'))
|
||||
emit_common_flags(lines, el, inner)
|
||||
|
||||
if el.get('hyperlink') is True:
|
||||
@@ -1847,7 +2128,7 @@ def emit_table(lines, el, name, eid, indent):
|
||||
if el.get('path'):
|
||||
lines.append(f'{inner}<DataPath>{el["path"]}</DataPath>')
|
||||
|
||||
emit_title(lines, el, name, inner)
|
||||
emit_title(lines, el, name, inner, auto=not el.get('path'))
|
||||
emit_common_flags(lines, el, inner)
|
||||
|
||||
if el.get('representation'):
|
||||
@@ -1935,7 +2216,7 @@ def emit_page(lines, el, name, eid, indent):
|
||||
lines.append(f'{indent}<Page name="{name}" id="{eid}">')
|
||||
inner = f'{indent}\t'
|
||||
|
||||
emit_title(lines, el, name, inner)
|
||||
emit_title(lines, el, name, inner, auto=True)
|
||||
emit_common_flags(lines, el, inner)
|
||||
|
||||
if el.get('group'):
|
||||
@@ -1962,14 +2243,42 @@ def emit_page(lines, el, name, eid, indent):
|
||||
lines.append(f'{indent}</Page>')
|
||||
|
||||
|
||||
def emit_button(lines, el, name, eid, indent):
|
||||
def emit_button(lines, el, name, eid, indent, in_cmd_bar=False):
|
||||
lines.append(f'{indent}<Button name="{name}" id="{eid}">')
|
||||
inner = f'{indent}\t'
|
||||
|
||||
# Type
|
||||
# Type — context-aware. Inside command bars (cmdBar/autoCmdBar/popup) only
|
||||
# CommandBarButton/CommandBarHyperlink are valid; UsualButton/Hyperlink would be ignored.
|
||||
# Forgiving resolver: any "ordinary button" hint resolves to UsualButton/CommandBarButton,
|
||||
# any "hyperlink" hint resolves to Hyperlink/CommandBarHyperlink — depending on context.
|
||||
btn_type = None
|
||||
if el.get('type'):
|
||||
btn_type_map = {'usual': 'UsualButton', 'hyperlink': 'Hyperlink', 'commandBar': 'CommandBarButton'}
|
||||
btn_type = btn_type_map.get(str(el['type']), str(el['type']))
|
||||
raw = str(el['type'])
|
||||
if in_cmd_bar:
|
||||
cmd_bar_map = {
|
||||
'usual': 'CommandBarButton',
|
||||
'UsualButton': 'CommandBarButton',
|
||||
'commandBar': 'CommandBarButton',
|
||||
'CommandBarButton': 'CommandBarButton',
|
||||
'hyperlink': 'CommandBarHyperlink',
|
||||
'Hyperlink': 'CommandBarHyperlink',
|
||||
'CommandBarHyperlink': 'CommandBarHyperlink',
|
||||
}
|
||||
btn_type = cmd_bar_map.get(raw, raw)
|
||||
else:
|
||||
normal_map = {
|
||||
'usual': 'UsualButton',
|
||||
'UsualButton': 'UsualButton',
|
||||
'commandBar': 'UsualButton',
|
||||
'CommandBarButton': 'UsualButton',
|
||||
'hyperlink': 'Hyperlink',
|
||||
'Hyperlink': 'Hyperlink',
|
||||
'CommandBarHyperlink': 'Hyperlink',
|
||||
}
|
||||
btn_type = normal_map.get(raw, raw)
|
||||
elif in_cmd_bar:
|
||||
btn_type = 'CommandBarButton'
|
||||
if btn_type:
|
||||
lines.append(f'{inner}<Type>{btn_type}</Type>')
|
||||
|
||||
# CommandName
|
||||
@@ -1983,7 +2292,7 @@ def emit_button(lines, el, name, eid, indent):
|
||||
else:
|
||||
lines.append(f'{inner}<CommandName>Form.StandardCommand.{sc}</CommandName>')
|
||||
|
||||
emit_title(lines, el, name, inner)
|
||||
emit_title(lines, el, name, inner, auto=not (el.get('command') or el.get('stdCommand')))
|
||||
emit_common_flags(lines, el, inner)
|
||||
|
||||
if el.get('defaultButton') is True:
|
||||
@@ -2071,7 +2380,7 @@ def emit_calendar(lines, el, name, eid, indent):
|
||||
if el.get('path'):
|
||||
lines.append(f'{inner}<DataPath>{el["path"]}</DataPath>')
|
||||
|
||||
emit_title(lines, el, name, inner)
|
||||
emit_title(lines, el, name, inner, auto=not el.get('path'))
|
||||
emit_common_flags(lines, el, inner)
|
||||
|
||||
# Companions
|
||||
@@ -2096,7 +2405,7 @@ def emit_command_bar(lines, el, name, eid, indent):
|
||||
if el.get('children') and len(el['children']) > 0:
|
||||
lines.append(f'{inner}<ChildItems>')
|
||||
for child in el['children']:
|
||||
emit_element(lines, child, f'{inner}\t')
|
||||
emit_element(lines, child, f'{inner}\t', in_cmd_bar=True)
|
||||
lines.append(f'{inner}</ChildItems>')
|
||||
|
||||
lines.append(f'{indent}</CommandBar>')
|
||||
@@ -2106,7 +2415,7 @@ def emit_popup(lines, el, name, eid, indent):
|
||||
lines.append(f'{indent}<Popup name="{name}" id="{eid}">')
|
||||
inner = f'{indent}\t'
|
||||
|
||||
emit_title(lines, el, name, inner)
|
||||
emit_title(lines, el, name, inner, auto=True)
|
||||
emit_common_flags(lines, el, inner)
|
||||
|
||||
if el.get('picture'):
|
||||
@@ -2122,7 +2431,7 @@ def emit_popup(lines, el, name, eid, indent):
|
||||
if el.get('children') and len(el['children']) > 0:
|
||||
lines.append(f'{inner}<ChildItems>')
|
||||
for child in el['children']:
|
||||
emit_element(lines, child, f'{inner}\t')
|
||||
emit_element(lines, child, f'{inner}\t', in_cmd_bar=True)
|
||||
lines.append(f'{inner}</ChildItems>')
|
||||
|
||||
lines.append(f'{indent}</Popup>')
|
||||
@@ -2142,8 +2451,11 @@ def emit_attributes(lines, attrs, indent):
|
||||
lines.append(f'{indent}\t<Attribute name="{attr_name}" id="{attr_id}">')
|
||||
inner = f'{indent}\t\t'
|
||||
|
||||
if attr.get('title'):
|
||||
emit_mltext(lines, inner, 'Title', str(attr['title']))
|
||||
attr_title = attr.get('title')
|
||||
if not attr_title and attr.get('main') is not True:
|
||||
attr_title = title_from_name(attr_name)
|
||||
if attr_title:
|
||||
emit_mltext(lines, inner, 'Title', str(attr_title))
|
||||
|
||||
# Type
|
||||
if attr.get('type'):
|
||||
@@ -2153,7 +2465,11 @@ def emit_attributes(lines, attrs, indent):
|
||||
|
||||
if attr.get('main') is True:
|
||||
lines.append(f'{inner}<MainAttribute>true</MainAttribute>')
|
||||
if attr.get('savedData') is True:
|
||||
main_saved = False
|
||||
if attr.get('main') is True and attr.get('type'):
|
||||
t = str(attr['type'])
|
||||
main_saved = bool(re.match(r'^(CatalogObject|DocumentObject|ChartOfAccountsObject|ChartOfCalculationTypesObject|ChartOfCharacteristicTypesObject|ExchangePlanObject|BusinessProcessObject|TaskObject)\.', t)) or ('RecordManager.' in t)
|
||||
if attr.get('savedData') is True or main_saved:
|
||||
lines.append(f'{inner}<SavedData>true</SavedData>')
|
||||
if attr.get('fillChecking'):
|
||||
lines.append(f'{inner}<FillChecking>{attr["fillChecking"]}</FillChecking>')
|
||||
@@ -2219,8 +2535,9 @@ def emit_commands(lines, cmds, indent):
|
||||
lines.append(f'{indent}\t<Command name="{cmd["name"]}" id="{cmd_id}">')
|
||||
inner = f'{indent}\t\t'
|
||||
|
||||
if cmd.get('title'):
|
||||
emit_mltext(lines, inner, 'Title', str(cmd['title']))
|
||||
cmd_title = cmd.get('title') or title_from_name(str(cmd['name']))
|
||||
if cmd_title:
|
||||
emit_mltext(lines, inner, 'Title', str(cmd_title))
|
||||
|
||||
if cmd.get('action'):
|
||||
lines.append(f'{inner}<Action>{cmd["action"]}</Action>')
|
||||
@@ -2572,7 +2889,7 @@ def main():
|
||||
return True
|
||||
return False
|
||||
|
||||
def _apply_dlist_table_heuristic(el, list_name):
|
||||
def _apply_dlist_table_heuristic(el, list_name, has_main_table):
|
||||
if not isinstance(el, dict):
|
||||
return
|
||||
if el.get('table') is not None and str(el.get('path', '')) == list_name:
|
||||
@@ -2580,9 +2897,12 @@ def main():
|
||||
el['tableAutofill'] = False
|
||||
if 'commandBarLocation' not in el:
|
||||
el['commandBarLocation'] = 'None'
|
||||
# DefaultPicture доступен только если у DynamicList есть основная таблица
|
||||
if has_main_table and not el.get('rowPictureDataPath'):
|
||||
el['rowPictureDataPath'] = f'{list_name}.DefaultPicture'
|
||||
if isinstance(el.get('children'), list):
|
||||
for child in el['children']:
|
||||
_apply_dlist_table_heuristic(child, list_name)
|
||||
_apply_dlist_table_heuristic(child, list_name, has_main_table)
|
||||
|
||||
def _is_object_like_type(t):
|
||||
if not t:
|
||||
@@ -2647,8 +2967,10 @@ def main():
|
||||
if isinstance(defn.get('attributes'), list) and isinstance(defn.get('elements'), list):
|
||||
main_attr = next((a for a in defn['attributes'] if isinstance(a, dict) and a.get('main') is True), None)
|
||||
if main_attr and str(main_attr.get('type', '')) == 'DynamicList':
|
||||
settings = main_attr.get('settings') or {}
|
||||
has_mt = bool(isinstance(settings, dict) and settings.get('mainTable'))
|
||||
for el in defn['elements']:
|
||||
_apply_dlist_table_heuristic(el, main_attr.get('name', ''))
|
||||
_apply_dlist_table_heuristic(el, main_attr.get('name', ''), has_mt)
|
||||
|
||||
# 1b.5: Compute main AutoCommandBar Autofill (B3)
|
||||
def _compute_main_acb_autofill():
|
||||
@@ -2677,9 +2999,16 @@ def main():
|
||||
emit_mltext(lines, '\t', 'Title', str(form_title))
|
||||
|
||||
# Properties (skip 'title' — handled above)
|
||||
if defn.get('properties'):
|
||||
props_clone = {k: v for k, v in defn['properties'].items() if k != 'title'}
|
||||
emit_properties(lines, props_clone, '\t')
|
||||
# When form-level Title is set, default autoTitle=false (≈95% of ERP forms do this;
|
||||
# otherwise platform appends synonym → "Title: Synonym" double-titles).
|
||||
props_src = defn.get('properties') or {}
|
||||
props_clone = OrderedDict()
|
||||
if form_title and 'autoTitle' not in props_src:
|
||||
props_clone['autoTitle'] = False
|
||||
for k, v in props_src.items():
|
||||
if k != 'title':
|
||||
props_clone[k] = v
|
||||
emit_properties(lines, props_clone, '\t')
|
||||
|
||||
# CommandSet (excluded commands)
|
||||
if defn.get('excludedCommands') and len(defn['excludedCommands']) > 0:
|
||||
@@ -2711,7 +3040,7 @@ def main():
|
||||
if has_acb_children:
|
||||
lines.append('\t\t<ChildItems>')
|
||||
for child in main_acb_def['children']:
|
||||
emit_element(lines, child, '\t\t\t')
|
||||
emit_element(lines, child, '\t\t\t', in_cmd_bar=True)
|
||||
lines.append('\t\t</ChildItems>')
|
||||
lines.append('\t</AutoCommandBar>')
|
||||
else:
|
||||
|
||||
@@ -29,7 +29,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/form-edit/scripts/form-edit.ps1 -FormPath "<путь>" -JsonPath "<путь>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-edit.ps1" -FormPath "<путь>" -JsonPath "<путь>"
|
||||
```
|
||||
|
||||
## JSON формат
|
||||
|
||||
@@ -15,7 +15,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/form-info/scripts/form-info.ps1 -FormPath "<путь к Form.xml>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-info.ps1" -FormPath "<путь к Form.xml>"
|
||||
```
|
||||
|
||||
## Параметры
|
||||
|
||||
@@ -41,9 +41,9 @@ allowed-tools: []
|
||||
├─ Информационные надписи (label, hyperlink)
|
||||
Рабочая область
|
||||
├─ Таблица данных или Pages с вкладками
|
||||
Кнопки действий
|
||||
├─ Выполнить / Применить (defaultButton)
|
||||
├─ Закрыть (stdCommand: Close)
|
||||
Главная АКП формы (autoCmdBar)
|
||||
├─ Выполнить / Применить (defaultButton: true)
|
||||
└─ Закрыть (stdCommand: Close)
|
||||
```
|
||||
|
||||
**События:** OnCreateAtServer, OnOpen, NotificationProcessing
|
||||
@@ -90,12 +90,12 @@ allowed-tools: []
|
||||
├─ Шаг1: описание + параметры
|
||||
├─ Шаг2: основная работа
|
||||
└─ Шаг3: результат
|
||||
Кнопки (horizontal)
|
||||
├─ Назад (command), Далее (command, defaultButton), Выполнить (command)
|
||||
Главная АКП формы (autoCmdBar)
|
||||
├─ Назад, Далее (defaultButton: true), Выполнить
|
||||
└─ Закрыть (stdCommand: Close)
|
||||
```
|
||||
|
||||
**Свойства:** windowOpeningMode=LockOwnerWindow, commandBarLocation=None
|
||||
**Свойства:** windowOpeningMode=LockOwnerWindow
|
||||
|
||||
---
|
||||
|
||||
@@ -111,7 +111,7 @@ allowed-tools: []
|
||||
| Номер+Дата | `ГруппаНомерДата` | horizontal |
|
||||
| Подвал | `ГруппаПодвал` | vertical |
|
||||
| Итоги | `ГруппаИтоги` | horizontal |
|
||||
| Кнопки | `ГруппаКнопок` | horizontal |
|
||||
| Главная АКП формы | `ФормаКоманднаяПанель` | autoCmdBar |
|
||||
| Страницы | `ГруппаСтраницы` / `Страницы` | pages |
|
||||
| Предупреждение | `ГруппаПредупреждение` | horizontal, visible:false |
|
||||
| Доп. секция | `ГруппаДополнительно` / `ГруппаПрочее` | vertical, collapse |
|
||||
@@ -150,7 +150,7 @@ allowed-tools: []
|
||||
|
||||
1. **Порядок чтения.** Сверху вниз, слева направо. Самое важное — вверху.
|
||||
2. **Двухколоночная шапка.** Основные реквизиты слева (контрагент, склад), организационные справа (организация, подразделение).
|
||||
3. **Кнопки действий внизу.** Главная кнопка — `defaultButton: true`. Закрыть — всегда последняя.
|
||||
3. **Кнопки действий — на главной АКП формы** (`autoCmdBar`), не в отдельной группе на форме. Главная кнопка — `defaultButton: true`. Закрыть — всегда последняя.
|
||||
4. **Таблицы — основная область.** Табличные части занимают большую часть формы, обычно на Pages.
|
||||
5. **Итоги рядом с таблицей.** В подвале, горизонтальная группа, все поля readOnly.
|
||||
6. **Фильтры — отдельная зона.** Над списком, alwaysHorizontal, пара «флажок + поле» на каждый фильтр.
|
||||
@@ -166,8 +166,8 @@ allowed-tools: []
|
||||
Для необязательных секций (подписи, дополнительно, прочее):
|
||||
|
||||
```json
|
||||
{ "group": "vertical", "name": "ГруппаПодписи", "title": "Подписи",
|
||||
"behavior": "Collapsible", "collapsed": true, "children": [...] }
|
||||
{ "group": "collapsible", "name": "ГруппаПодписи", "title": "Подписи",
|
||||
"collapsed": true, "children": [...] }
|
||||
```
|
||||
|
||||
### Баннер-предупреждение
|
||||
@@ -233,7 +233,7 @@ allowed-tools: []
|
||||
{ "input": "ДанныеКоличество", "path": "Объект.Данные.Количество", "on": ["OnChange"] },
|
||||
{ "input": "ДанныеСумма", "path": "Объект.Данные.Сумма", "readOnly": true }
|
||||
]},
|
||||
{ "group": "horizontal", "name": "ГруппаКнопок", "children": [
|
||||
{ "autoCmdBar": "ФормаКоманднаяПанель", "children": [
|
||||
{ "button": "Загрузить", "command": "Загрузить", "title": "Загрузить из файла", "defaultButton": true },
|
||||
{ "button": "Очистить", "command": "Очистить", "title": "Очистить таблицу" },
|
||||
{ "button": "Закрыть", "stdCommand": "Close" }
|
||||
|
||||
@@ -31,7 +31,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/form-remove/scripts/remove-form.ps1 -ObjectName "<ObjectName>" -FormName "<FormName>" [-SrcDir "<SrcDir>"]
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/remove-form.ps1" -ObjectName "<ObjectName>" -FormName "<FormName>" [-SrcDir "<SrcDir>"]
|
||||
```
|
||||
|
||||
## Что удаляется
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# form-remove v1.1 — Remove form from 1C object
|
||||
# form-remove v1.2 — Remove form from 1C object
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -12,6 +12,8 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
# --- Проверки ---
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# remove-form v1.0 — Remove form from 1C object
|
||||
# remove-form v1.1 — Remove form from 1C object
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
|
||||
@@ -23,7 +23,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/form-validate/scripts/form-validate.ps1 -FormPath "Catalogs/Номенклатура/Forms/ФормаЭлемента"
|
||||
powershell.exe -NoProfile -File .claude/skills/form-validate/scripts/form-validate.ps1 -FormPath "src/МояОбработка/Forms/Форма/Ext/Form.xml"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-validate.ps1" -FormPath "Catalogs/Номенклатура/Forms/ФормаЭлемента"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/form-validate.ps1" -FormPath "src/МояОбработка/Forms/Форма/Ext/Form.xml"
|
||||
```
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/help-add/scripts/add-help.ps1 -ObjectName "<ObjectName>" [-Lang "<Lang>"] [-SrcDir "<SrcDir>"]
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/add-help.ps1" -ObjectName "<ObjectName>" [-Lang "<Lang>"] [-SrcDir "<SrcDir>"]
|
||||
```
|
||||
|
||||
## Что делает скрипт
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# help-add v1.3 — Add built-in help to 1C object
|
||||
# help-add v1.4 — Add built-in help to 1C object
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -10,6 +10,8 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
# --- Detect format version ---
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# add-help v1.3 — Add built-in help to 1C object
|
||||
# add-help v1.4 — Add built-in help to 1C object
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
|
||||
@@ -29,7 +29,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```bash
|
||||
python .claude/skills/img-grid/scripts/overlay-grid.py "<ImagePath>" [-c 50] [-o "<OutputPath>"]
|
||||
python "${CLAUDE_SKILL_DIR}/scripts/overlay-grid.py" "<ImagePath>" [-c 50] [-o "<OutputPath>"]
|
||||
```
|
||||
|
||||
Требуется Python 3 с библиотекой Pillow (`pip install Pillow`).
|
||||
|
||||
@@ -29,13 +29,13 @@ allowed-tools:
|
||||
### Inline mode
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File '.claude/skills/interface-edit/scripts/interface-edit.ps1' -CIPath '<path>' -Operation hide -Value '<cmd>'
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-edit.ps1" -CIPath '<path>' -Operation hide -Value '<cmd>'
|
||||
```
|
||||
|
||||
### JSON mode
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File '.claude/skills/interface-edit/scripts/interface-edit.ps1' -CIPath '<path>' -DefinitionFile '<json>'
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-edit.ps1" -CIPath '<path>' -DefinitionFile '<json>'
|
||||
```
|
||||
|
||||
## Операции
|
||||
|
||||
@@ -24,6 +24,6 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File ".claude/skills/interface-validate/scripts/interface-validate.ps1" -CIPath "Subsystems/Продажи"
|
||||
powershell.exe -NoProfile -File ".claude/skills/interface-validate/scripts/interface-validate.ps1" -CIPath "Subsystems/Продажи/Ext/CommandInterface.xml"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-validate.ps1" -CIPath "Subsystems/Продажи"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/interface-validate.ps1" -CIPath "Subsystems/Продажи/Ext/CommandInterface.xml"
|
||||
```
|
||||
|
||||
@@ -23,7 +23,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/meta-compile/scripts/meta-compile.ps1 -JsonPath "<json>" -OutputDir "<ConfigDir>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-compile.ps1" -JsonPath "<json>" -OutputDir "<ConfigDir>"
|
||||
```
|
||||
|
||||
| Параметр | Описание |
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
| `checkUnique` | `false` | CheckUnique |
|
||||
| `defaultPresentation` | `AsDescription` | DefaultPresentation |
|
||||
| `subordinationUse` | `ToItems` | SubordinationUse |
|
||||
| `quickChoice` | `true` | QuickChoice |
|
||||
| `quickChoice` | `false` | QuickChoice |
|
||||
| `choiceMode` | `BothWays` | ChoiceMode |
|
||||
| `owners` | `[]` | Owners |
|
||||
| `attributes` | `[]` | → Attribute в ChildObjects |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# meta-compile v1.10 — Compile 1C metadata object from JSON
|
||||
# meta-compile v1.11 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -1129,7 +1129,7 @@ function Emit-CatalogProperties {
|
||||
X "$i<Characteristics/>"
|
||||
X "$i<PredefinedDataUpdate>Auto</PredefinedDataUpdate>"
|
||||
X "$i<EditType>InDialog</EditType>"
|
||||
$quickChoice = if ($def.quickChoice -eq $false) { "false" } else { "true" }
|
||||
$quickChoice = if ($def.quickChoice -eq $true) { "true" } else { "false" }
|
||||
$choiceMode = Get-EnumProp "ChoiceMode" "choiceMode" "BothWays"
|
||||
X "$i<QuickChoice>$quickChoice</QuickChoice>"
|
||||
X "$i<ChoiceMode>$choiceMode</ChoiceMode>"
|
||||
@@ -1292,7 +1292,8 @@ function Emit-EnumProperties {
|
||||
Emit-StandardAttributes $i "Enum"
|
||||
X "$i<Characteristics/>"
|
||||
|
||||
X "$i<QuickChoice>true</QuickChoice>"
|
||||
$quickChoice = if ($def.quickChoice -eq $false) { "false" } else { "true" }
|
||||
X "$i<QuickChoice>$quickChoice</QuickChoice>"
|
||||
X "$i<ChoiceMode>BothWays</ChoiceMode>"
|
||||
X "$i<DefaultListForm/>"
|
||||
X "$i<DefaultChoiceForm/>"
|
||||
@@ -1663,7 +1664,8 @@ function Emit-ExchangePlanProperties {
|
||||
X "$i<IncludeConfigurationExtensions>$includeExt</IncludeConfigurationExtensions>"
|
||||
|
||||
X "$i<BasedOn/>"
|
||||
X "$i<QuickChoice>true</QuickChoice>"
|
||||
$quickChoice = if ($def.quickChoice -eq $true) { "true" } else { "false" }
|
||||
X "$i<QuickChoice>$quickChoice</QuickChoice>"
|
||||
X "$i<ChoiceMode>BothWays</ChoiceMode>"
|
||||
X "$i<InputByString>"
|
||||
X "$i`t<xr:Field>ExchangePlan.$objName.StandardAttribute.Description</xr:Field>"
|
||||
@@ -1764,7 +1766,8 @@ function Emit-ChartOfCharacteristicTypesProperties {
|
||||
X "$i<Characteristics/>"
|
||||
X "$i<PredefinedDataUpdate>Auto</PredefinedDataUpdate>"
|
||||
X "$i<EditType>InDialog</EditType>"
|
||||
X "$i<QuickChoice>true</QuickChoice>"
|
||||
$quickChoice = if ($def.quickChoice -eq $true) { "true" } else { "false" }
|
||||
X "$i<QuickChoice>$quickChoice</QuickChoice>"
|
||||
X "$i<ChoiceMode>BothWays</ChoiceMode>"
|
||||
X "$i<InputByString>"
|
||||
X "$i`t<xr:Field>ChartOfCharacteristicTypes.$objName.StandardAttribute.Description</xr:Field>"
|
||||
@@ -1905,7 +1908,8 @@ function Emit-ChartOfAccountsProperties {
|
||||
|
||||
X "$i<Characteristics/>"
|
||||
X "$i<PredefinedDataUpdate>Auto</PredefinedDataUpdate>"
|
||||
X "$i<QuickChoice>true</QuickChoice>"
|
||||
$quickChoice = if ($def.quickChoice -eq $true) { "true" } else { "false" }
|
||||
X "$i<QuickChoice>$quickChoice</QuickChoice>"
|
||||
X "$i<ChoiceMode>BothWays</ChoiceMode>"
|
||||
X "$i<InputByString>"
|
||||
X "$i`t<xr:Field>ChartOfAccounts.$objName.StandardAttribute.Description</xr:Field>"
|
||||
@@ -2021,7 +2025,8 @@ function Emit-ChartOfCalculationTypesProperties {
|
||||
X "$i<Characteristics/>"
|
||||
X "$i<PredefinedDataUpdate>Auto</PredefinedDataUpdate>"
|
||||
X "$i<EditType>InDialog</EditType>"
|
||||
X "$i<QuickChoice>true</QuickChoice>"
|
||||
$quickChoice = if ($def.quickChoice -eq $true) { "true" } else { "false" }
|
||||
X "$i<QuickChoice>$quickChoice</QuickChoice>"
|
||||
X "$i<ChoiceMode>BothWays</ChoiceMode>"
|
||||
X "$i<InputByString>"
|
||||
X "$i`t<xr:Field>ChartOfCalculationTypes.$objName.StandardAttribute.Description</xr:Field>"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# meta-compile v1.10 — Compile 1C metadata object from JSON
|
||||
# meta-compile v1.11 — Compile 1C metadata object from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
@@ -1024,7 +1024,7 @@ def emit_catalog_properties(indent):
|
||||
X(f'{i}<Characteristics/>')
|
||||
X(f'{i}<PredefinedDataUpdate>Auto</PredefinedDataUpdate>')
|
||||
X(f'{i}<EditType>InDialog</EditType>')
|
||||
quick_choice = 'false' if defn.get('quickChoice') is False else 'true'
|
||||
quick_choice = 'true' if defn.get('quickChoice') is True else 'false'
|
||||
choice_mode = get_enum_prop('ChoiceMode', 'choiceMode', 'BothWays')
|
||||
X(f'{i}<QuickChoice>{quick_choice}</QuickChoice>')
|
||||
X(f'{i}<ChoiceMode>{choice_mode}</ChoiceMode>')
|
||||
@@ -1157,7 +1157,8 @@ def emit_enum_properties(indent):
|
||||
X(f'{i}<UseStandardCommands>false</UseStandardCommands>')
|
||||
emit_standard_attributes(i, 'Enum')
|
||||
X(f'{i}<Characteristics/>')
|
||||
X(f'{i}<QuickChoice>true</QuickChoice>')
|
||||
quick_choice = 'false' if defn.get('quickChoice') is False else 'true'
|
||||
X(f'{i}<QuickChoice>{quick_choice}</QuickChoice>')
|
||||
X(f'{i}<ChoiceMode>BothWays</ChoiceMode>')
|
||||
X(f'{i}<DefaultListForm/>')
|
||||
X(f'{i}<DefaultChoiceForm/>')
|
||||
@@ -1471,7 +1472,8 @@ def emit_exchange_plan_properties(indent):
|
||||
X(f'{i}<DistributedInfoBase>{distributed}</DistributedInfoBase>')
|
||||
X(f'{i}<IncludeConfigurationExtensions>{include_ext}</IncludeConfigurationExtensions>')
|
||||
X(f'{i}<BasedOn/>')
|
||||
X(f'{i}<QuickChoice>true</QuickChoice>')
|
||||
quick_choice = 'true' if defn.get('quickChoice') is True else 'false'
|
||||
X(f'{i}<QuickChoice>{quick_choice}</QuickChoice>')
|
||||
X(f'{i}<ChoiceMode>BothWays</ChoiceMode>')
|
||||
X(f'{i}<InputByString>')
|
||||
X(f'{i}\t<xr:Field>ExchangePlan.{obj_name}.StandardAttribute.Description</xr:Field>')
|
||||
@@ -1557,7 +1559,8 @@ def emit_chart_of_characteristic_types_properties(indent):
|
||||
X(f'{i}<Characteristics/>')
|
||||
X(f'{i}<PredefinedDataUpdate>Auto</PredefinedDataUpdate>')
|
||||
X(f'{i}<EditType>InDialog</EditType>')
|
||||
X(f'{i}<QuickChoice>true</QuickChoice>')
|
||||
quick_choice = 'true' if defn.get('quickChoice') is True else 'false'
|
||||
X(f'{i}<QuickChoice>{quick_choice}</QuickChoice>')
|
||||
X(f'{i}<ChoiceMode>BothWays</ChoiceMode>')
|
||||
X(f'{i}<InputByString>')
|
||||
X(f'{i}\t<xr:Field>ChartOfCharacteristicTypes.{obj_name}.StandardAttribute.Description</xr:Field>')
|
||||
@@ -1673,7 +1676,8 @@ def emit_chart_of_accounts_properties(indent):
|
||||
X(f'{i}</StandardTabularSections>')
|
||||
X(f'{i}<Characteristics/>')
|
||||
X(f'{i}<PredefinedDataUpdate>Auto</PredefinedDataUpdate>')
|
||||
X(f'{i}<QuickChoice>true</QuickChoice>')
|
||||
quick_choice = 'true' if defn.get('quickChoice') is True else 'false'
|
||||
X(f'{i}<QuickChoice>{quick_choice}</QuickChoice>')
|
||||
X(f'{i}<ChoiceMode>BothWays</ChoiceMode>')
|
||||
X(f'{i}<InputByString>')
|
||||
X(f'{i}\t<xr:Field>ChartOfAccounts.{obj_name}.StandardAttribute.Description</xr:Field>')
|
||||
@@ -1764,7 +1768,8 @@ def emit_chart_of_calculation_types_properties(indent):
|
||||
X(f'{i}<Characteristics/>')
|
||||
X(f'{i}<PredefinedDataUpdate>Auto</PredefinedDataUpdate>')
|
||||
X(f'{i}<EditType>InDialog</EditType>')
|
||||
X(f'{i}<QuickChoice>true</QuickChoice>')
|
||||
quick_choice = 'true' if defn.get('quickChoice') is True else 'false'
|
||||
X(f'{i}<QuickChoice>{quick_choice}</QuickChoice>')
|
||||
X(f'{i}<ChoiceMode>BothWays</ChoiceMode>')
|
||||
X(f'{i}<InputByString>')
|
||||
X(f'{i}\t<xr:Field>ChartOfCalculationTypes.{obj_name}.StandardAttribute.Description</xr:Field>')
|
||||
|
||||
@@ -18,13 +18,13 @@ allowed-tools:
|
||||
### Inline mode (простые операции)
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/meta-edit/scripts/meta-edit.ps1 -ObjectPath "<path>" -Operation <op> -Value "<val>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-edit.ps1" -ObjectPath "<path>" -Operation <op> -Value "<val>"
|
||||
```
|
||||
|
||||
### JSON mode (сложные/комбинированные)
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/meta-edit/scripts/meta-edit.ps1 -DefinitionFile "<json>" -ObjectPath "<path>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-edit.ps1" -DefinitionFile "<json>" -ObjectPath "<path>"
|
||||
```
|
||||
|
||||
| Параметр | Описание |
|
||||
|
||||
@@ -23,7 +23,7 @@ allowed-tools:
|
||||
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/meta-info/scripts/meta-info.ps1 -ObjectPath "<путь>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-info.ps1" -ObjectPath "<путь>"
|
||||
```
|
||||
|
||||
## Три режима
|
||||
|
||||
@@ -32,7 +32,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/meta-remove/scripts/meta-remove.ps1 -ConfigDir "<путь>" -Object "Catalog.Товары"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-remove.ps1" -ConfigDir "<путь>" -Object "Catalog.Товары"
|
||||
```
|
||||
|
||||
## Поддерживаемые типы
|
||||
|
||||
@@ -24,6 +24,6 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/meta-validate/scripts/meta-validate.ps1 -ObjectPath "Catalogs/Номенклатура/Номенклатура.xml"
|
||||
powershell.exe -NoProfile -File .claude/skills/meta-validate/scripts/meta-validate.ps1 -ObjectPath "Catalogs/Банки|Documents/Заказ"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-validate.ps1" -ObjectPath "Catalogs/Номенклатура/Номенклатура.xml"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/meta-validate.ps1" -ObjectPath "Catalogs/Банки|Documents/Заказ"
|
||||
```
|
||||
|
||||
@@ -29,7 +29,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/mxl-compile/scripts/mxl-compile.ps1 -JsonPath "<путь>.json" -OutputPath "<путь>/Template.xml"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-compile.ps1" -JsonPath "<путь>.json" -OutputPath "<путь>/Template.xml"
|
||||
```
|
||||
|
||||
## Рабочий процесс
|
||||
|
||||
@@ -29,7 +29,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/mxl-decompile/scripts/mxl-decompile.ps1 -TemplatePath "<путь>/Template.xml" [-OutputPath "<путь>.json"]
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-decompile.ps1" -TemplatePath "<путь>/Template.xml" [-OutputPath "<путь>.json"]
|
||||
```
|
||||
|
||||
## Рабочий процесс
|
||||
|
||||
@@ -38,12 +38,12 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/mxl-info/scripts/mxl-info.ps1 -TemplatePath "<путь>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-info.ps1" -TemplatePath "<путь>"
|
||||
```
|
||||
|
||||
Или по имени обработки/макета:
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/mxl-info/scripts/mxl-info.ps1 -ProcessorName "<Имя>" -TemplateName "<Макет>" [-SrcDir "<каталог>"]
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-info.ps1" -ProcessorName "<Имя>" -TemplateName "<Макет>" [-SrcDir "<каталог>"]
|
||||
```
|
||||
|
||||
Дополнительные флаги:
|
||||
|
||||
@@ -23,7 +23,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/mxl-validate/scripts/mxl-validate.ps1 -TemplatePath "Catalogs/Номенклатура/Templates/Макет"
|
||||
powershell.exe -NoProfile -File .claude/skills/mxl-validate/scripts/mxl-validate.ps1 -TemplatePath "src/МояОбработка/Templates/ПечатнаяФорма"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-validate.ps1" -TemplatePath "Catalogs/Номенклатура/Templates/Макет"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/mxl-validate.ps1" -TemplatePath "src/МояОбработка/Templates/ПечатнаяФорма"
|
||||
```
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ allowed-tools:
|
||||
| `OutputDir` | Корень выгрузки конфигурации (где `Configuration.xml`, `Roles/` и т.д.) |
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/role-compile/scripts/role-compile.ps1 -JsonPath "<json>" -OutputDir "<ConfigDir>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-compile.ps1" -JsonPath "<json>" -OutputDir "<ConfigDir>"
|
||||
```
|
||||
|
||||
Создаёт `{OutputDir}/Roles/Имя.xml` и `{OutputDir}/Roles/Имя/Ext/Rights.xml`. Регистрирует `<Role>` в `Configuration.xml`.
|
||||
|
||||
@@ -22,7 +22,7 @@ allowed-tools:
|
||||
## Запуск скрипта
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/role-info/scripts/role-info.ps1 -RightsPath <path> -OutFile <output.txt>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-info.ps1" -RightsPath <path> -OutFile <output.txt>
|
||||
```
|
||||
|
||||
### Параметры
|
||||
|
||||
@@ -23,5 +23,5 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/role-validate/scripts/role-validate.ps1 -RightsPath "Roles/МояРоль"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/role-validate.ps1" -RightsPath "Roles/МояРоль"
|
||||
```
|
||||
|
||||
@@ -23,10 +23,10 @@ allowed-tools:
|
||||
|
||||
```powershell
|
||||
# Из файла
|
||||
powershell.exe -NoProfile -File .claude/skills/skd-compile/scripts/skd-compile.ps1 -DefinitionFile "<json>" -OutputPath "<Template.xml>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-compile.ps1" -DefinitionFile "<json>" -OutputPath "<Template.xml>"
|
||||
|
||||
# Из строки (без промежуточного файла)
|
||||
powershell.exe -NoProfile -File .claude/skills/skd-compile/scripts/skd-compile.ps1 -Value '<json-string>' -OutputPath "<Template.xml>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-compile.ps1" -Value '<json-string>' -OutputPath "<Template.xml>"
|
||||
```
|
||||
|
||||
## JSON DSL — краткий справочник
|
||||
|
||||
@@ -25,7 +25,7 @@ allowed-tools:
|
||||
| `NoSelection` | (опц.) Не добавлять поле в selection варианта |
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/skd-edit/scripts/skd-edit.ps1 -TemplatePath "<path>" -Operation <op> -Value "<value>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-edit.ps1" -TemplatePath "<path>" -Operation <op> -Value "<value>"
|
||||
```
|
||||
|
||||
## Пакетный режим (batch)
|
||||
|
||||
@@ -24,7 +24,7 @@ allowed-tools:
|
||||
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/skd-info/scripts/skd-info.ps1 -TemplatePath "<путь>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-info.ps1" -TemplatePath "<путь>"
|
||||
```
|
||||
|
||||
С указанием режима:
|
||||
|
||||
@@ -24,6 +24,6 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/skd-validate/scripts/skd-validate.ps1 -TemplatePath "src/МойОтчёт/Templates/ОсновнаяСхема"
|
||||
powershell.exe -NoProfile -File .claude/skills/skd-validate/scripts/skd-validate.ps1 -TemplatePath "Catalogs/Номенклатура/Templates/СКД/Ext/Template.xml"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-validate.ps1" -TemplatePath "src/МойОтчёт/Templates/ОсновнаяСхема"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/skd-validate.ps1" -TemplatePath "Catalogs/Номенклатура/Templates/СКД/Ext/Template.xml"
|
||||
```
|
||||
|
||||
@@ -24,7 +24,7 @@ allowed-tools:
|
||||
| `NoValidate` | Пропустить авто-валидацию |
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File '.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1' -Value '<json>' -OutputDir '<ConfigDir>'
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/subsystem-compile.ps1" -Value '<json>' -OutputDir '<ConfigDir>'
|
||||
```
|
||||
|
||||
## JSON-определение
|
||||
|
||||
@@ -24,7 +24,7 @@ allowed-tools:
|
||||
| `NoValidate` | Пропустить авто-валидацию |
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File '.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1' -SubsystemPath '<path>' -Operation add-content -Value 'Catalog.Товары'
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/subsystem-edit.ps1" -SubsystemPath '<path>' -Operation add-content -Value 'Catalog.Товары'
|
||||
```
|
||||
|
||||
## Операции
|
||||
|
||||
@@ -23,7 +23,7 @@ allowed-tools:
|
||||
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/subsystem-info/scripts/subsystem-info.ps1 -SubsystemPath "<путь>"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/subsystem-info.ps1" -SubsystemPath "<путь>"
|
||||
```
|
||||
|
||||
## Пять режимов
|
||||
|
||||
@@ -24,6 +24,6 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File ".claude/skills/subsystem-validate/scripts/subsystem-validate.ps1" -SubsystemPath "Subsystems/Продажи"
|
||||
powershell.exe -NoProfile -File ".claude/skills/subsystem-validate/scripts/subsystem-validate.ps1" -SubsystemPath "Subsystems/Продажи.xml"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/subsystem-validate.ps1" -SubsystemPath "Subsystems/Продажи"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/subsystem-validate.ps1" -SubsystemPath "Subsystems/Продажи.xml"
|
||||
```
|
||||
|
||||
@@ -33,7 +33,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/template-add/scripts/add-template.ps1 -ObjectName "<ObjectName>" -TemplateName "<TemplateName>" -TemplateType "<TemplateType>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-SetMainSKD]
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/add-template.ps1" -ObjectName "<ObjectName>" -TemplateName "<TemplateName>" -TemplateType "<TemplateType>" [-Synonym "<Synonym>"] [-SrcDir "<SrcDir>"] [-SetMainSKD]
|
||||
```
|
||||
|
||||
## Пример
|
||||
@@ -41,7 +41,7 @@ powershell.exe -NoProfile -File .claude/skills/template-add/scripts/add-template
|
||||
Добавить основную СКД к отчёту в расширении:
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/template-add/scripts/add-template.ps1 -ObjectName "ОтчётПродажи" -TemplateName "ОсновнаяСхемаКомпоновкиДанных" -TemplateType "DataCompositionSchema" -SrcDir "src/cfe/МоёРасширение/Reports"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/add-template.ps1" -ObjectName "ОтчётПродажи" -TemplateName "ОсновнаяСхемаКомпоновкиДанных" -TemplateType "DataCompositionSchema" -SrcDir "src/cfe/МоёРасширение/Reports"
|
||||
```
|
||||
|
||||
## Маппинг типов
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# template-add v1.4 — Add template to 1C object
|
||||
# template-add v1.5 — Add template to 1C object
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -20,6 +20,8 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
# --- Маппинг типов ---
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# add-template v1.4 — Add template to 1C object
|
||||
# add-template v1.5 — Add template to 1C object
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
|
||||
@@ -31,7 +31,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/template-remove/scripts/remove-template.ps1 -ObjectName "<ObjectName>" -TemplateName "<TemplateName>" [-SrcDir "<SrcDir>"]
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/remove-template.ps1" -ObjectName "<ObjectName>" -TemplateName "<TemplateName>" [-SrcDir "<SrcDir>"]
|
||||
```
|
||||
|
||||
## Что удаляется
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# template-remove v1.1 — Remove template from 1C object
|
||||
# template-remove v1.2 — Remove template from 1C object
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -12,6 +12,8 @@ param(
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
||||
|
||||
# --- Проверки ---
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# remove-template v1.0 — Remove template from 1C object
|
||||
# remove-template v1.1 — Remove template from 1C object
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
|
||||
import argparse
|
||||
|
||||
@@ -26,7 +26,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/web-info/scripts/web-info.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-info.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -55,8 +55,8 @@ Module: C:/Program Files/1cv8/8.3.24.1691/bin/wsap24.dll
|
||||
|
||||
```powershell
|
||||
# Статус по умолчанию
|
||||
powershell.exe -NoProfile -File .claude/skills/web-info/scripts/web-info.ps1
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-info.ps1"
|
||||
|
||||
# Указать путь к Apache
|
||||
powershell.exe -NoProfile -File .claude/skills/web-info/scripts/web-info.ps1 -ApachePath "C:\tools\apache24"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-info.ps1" -ApachePath "C:\tools\apache24"
|
||||
```
|
||||
|
||||
@@ -41,7 +41,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/web-publish/scripts/web-publish.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-publish.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -88,14 +88,14 @@ powershell.exe -NoProfile -File .claude/skills/web-publish/scripts/web-publish.p
|
||||
|
||||
```powershell
|
||||
# Файловая база
|
||||
powershell.exe -NoProfile -File .claude/skills/web-publish/scripts/web-publish.ps1 -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-publish.ps1" -InfoBasePath "C:\Bases\MyDB" -UserName "Admin"
|
||||
|
||||
# С явным именем публикации и портом
|
||||
powershell.exe -NoProfile -File .claude/skills/web-publish/scripts/web-publish.ps1 -InfoBasePath "C:\Bases\MyDB" -AppName "mydb" -Port 9090
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-publish.ps1" -InfoBasePath "C:\Bases\MyDB" -AppName "mydb" -Port 9090
|
||||
|
||||
# Серверная база
|
||||
powershell.exe -NoProfile -File .claude/skills/web-publish/scripts/web-publish.ps1 -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-publish.ps1" -InfoBaseServer "srv01" -InfoBaseRef "MyDB" -UserName "Admin" -Password "secret"
|
||||
|
||||
# Ручной режим (только инструкция)
|
||||
powershell.exe -NoProfile -File .claude/skills/web-publish/scripts/web-publish.ps1 -InfoBasePath "C:\Bases\MyDB" -Manual
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-publish.ps1" -InfoBasePath "C:\Bases\MyDB" -Manual
|
||||
```
|
||||
|
||||
@@ -26,7 +26,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/web-stop/scripts/web-stop.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-stop.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -45,8 +45,8 @@ powershell.exe -NoProfile -File .claude/skills/web-stop/scripts/web-stop.ps1 <п
|
||||
|
||||
```powershell
|
||||
# Остановить Apache
|
||||
powershell.exe -NoProfile -File .claude/skills/web-stop/scripts/web-stop.ps1
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-stop.ps1"
|
||||
|
||||
# С указанием пути
|
||||
powershell.exe -NoProfile -File .claude/skills/web-stop/scripts/web-stop.ps1 -ApachePath "C:\tools\apache24"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-stop.ps1" -ApachePath "C:\tools\apache24"
|
||||
```
|
||||
|
||||
@@ -17,7 +17,7 @@ Automates user interactions with 1C:Enterprise web client via Playwright — nav
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
RUN=".claude/skills/web-test/scripts/run.mjs"
|
||||
RUN="${CLAUDE_SKILL_DIR}/scripts/run.mjs"
|
||||
|
||||
# One-shot: opens browser → runs script → closes browser → exits
|
||||
node $RUN run http://localhost:8081/bpdemo test-scenario.js
|
||||
@@ -35,7 +35,7 @@ SCRIPT
|
||||
## Setup (first time)
|
||||
|
||||
```bash
|
||||
cd .claude/skills/web-test/scripts && npm install
|
||||
cd "${CLAUDE_SKILL_DIR}/scripts" && npm install
|
||||
```
|
||||
|
||||
Requires Node.js 18+. `npm install` downloads Playwright and Chromium.
|
||||
|
||||
@@ -35,7 +35,7 @@ allowed-tools:
|
||||
## Команда
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -File .claude/skills/web-unpublish/scripts/web-unpublish.ps1 <параметры>
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-unpublish.ps1" <параметры>
|
||||
```
|
||||
|
||||
### Параметры скрипта
|
||||
@@ -52,11 +52,11 @@ powershell.exe -NoProfile -File .claude/skills/web-unpublish/scripts/web-unpubli
|
||||
|
||||
```powershell
|
||||
# Удалить одну публикацию
|
||||
powershell.exe -NoProfile -File .claude/skills/web-unpublish/scripts/web-unpublish.ps1 -AppName "bpdemo"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-unpublish.ps1" -AppName "bpdemo"
|
||||
|
||||
# Удалить все публикации
|
||||
powershell.exe -NoProfile -File .claude/skills/web-unpublish/scripts/web-unpublish.ps1 -All
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-unpublish.ps1" -All
|
||||
|
||||
# С указанием пути
|
||||
powershell.exe -NoProfile -File .claude/skills/web-unpublish/scripts/web-unpublish.ps1 -AppName "mydb" -ApachePath "C:\tools\apache24"
|
||||
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/web-unpublish.ps1" -AppName "mydb" -ApachePath "C:\tools\apache24"
|
||||
```
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# 1C Skills for {{PLATFORM_LABEL}} ({{RUNTIME_LABEL}})
|
||||
|
||||
Автоматическая сборка из [main]({{MAIN_REPO_URL}}) — навыки 1С:Предприятие 8.3 для AI-агента **{{PLATFORM_LABEL}}** с рантаймом **{{RUNTIME_LABEL}}**.
|
||||
|
||||
> Эта ветка генерируется CI на каждый push в main. **Не редактируйте напрямую** — все правки идут в [main]({{MAIN_REPO_URL}}).
|
||||
|
||||
## Установка
|
||||
|
||||
1. Скачайте ZIP этой ветки: **Code → Download ZIP** (или `git archive`).
|
||||
2. Распакуйте в корень своего проекта — должна появиться папка `{{PLATFORM_DIR}}/`.
|
||||
3. Запустите {{PLATFORM_LABEL}} из этого проекта — навыки станут доступны.
|
||||
|
||||
## Требования
|
||||
|
||||
- **Windows** с PowerShell 5.1+ (входит в Windows) — для PowerShell-сборки.
|
||||
- **Python 3.10+** — для Python-сборки. Зависимости: `lxml>=4.9.0`, `psutil>=5.9.0` (для DOM- и web-навыков).
|
||||
- **1С:Предприятие 8.3** — для сборки/разборки EPF/ERF и работы с базами.
|
||||
- **Node.js 18+** — для `/web-test`.
|
||||
|
||||
## Документация
|
||||
|
||||
Полные гайды, спецификации и описание навыков — в [main]({{MAIN_REPO_URL}}).
|
||||
|
||||
---
|
||||
|
||||
Source: {{MAIN_REPO_URL}}
|
||||
Build commit: `{{COMMIT_SHA}}`
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
||||
"name": "{{PLUGIN_NAME}}",
|
||||
"description": "[Python] Навыки для разработки на 1С:Предприятие 8.3 — абстракции над XML-форматами и CLI конфигуратора, плюс глаза и руки для тестирования через веб-клиент. Linux/Mac или когда PowerShell недоступен.",
|
||||
"author": {
|
||||
"name": "Nikolay Shirokov"
|
||||
},
|
||||
"homepage": "https://github.com/Nikolay-Shirokov/cc-1c-skills",
|
||||
"repository": "https://github.com/Nikolay-Shirokov/cc-1c-skills",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"1c",
|
||||
"1c-dev",
|
||||
"cf",
|
||||
"cfe",
|
||||
"epf",
|
||||
"erf",
|
||||
"metadata",
|
||||
"configuration",
|
||||
"extension",
|
||||
"form",
|
||||
"report",
|
||||
"skd",
|
||||
"data-processor",
|
||||
"mxl",
|
||||
"web-client",
|
||||
"testing",
|
||||
"test-automation"
|
||||
],
|
||||
"skills": "./.claude/skills/"
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "{{PLUGIN_NAME}}",
|
||||
"version": "{{VERSION}}",
|
||||
"description": "[{{RUNTIME_LABEL}}] Навыки для разработки на 1С:Предприятие 8.3 — абстракции над XML-форматами и CLI конфигуратора, плюс глаза и руки для тестирования через веб-клиент.",
|
||||
"author": {
|
||||
"name": "Nikolay Shirokov"
|
||||
},
|
||||
"homepage": "https://github.com/Nikolay-Shirokov/cc-1c-skills",
|
||||
"repository": "https://github.com/Nikolay-Shirokov/cc-1c-skills",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"1c",
|
||||
"1c-dev",
|
||||
"cf",
|
||||
"cfe",
|
||||
"epf",
|
||||
"erf",
|
||||
"metadata",
|
||||
"configuration",
|
||||
"extension",
|
||||
"form",
|
||||
"report",
|
||||
"skd",
|
||||
"data-processor",
|
||||
"mxl",
|
||||
"web-client",
|
||||
"testing",
|
||||
"test-automation"
|
||||
],
|
||||
"skills": "./.codex/skills/",
|
||||
"interface": {
|
||||
"displayName": "1C Skills ({{RUNTIME_LABEL}})",
|
||||
"shortDescription": "{{SHORT_DESCRIPTION}}",
|
||||
"category": "Development"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
name: Build port branches
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- '.claude/skills/**'
|
||||
- 'scripts/switch.py'
|
||||
- '.github/templates/README.port.md.tmpl'
|
||||
- '.github/templates/codex-plugin.json.tmpl'
|
||||
- '.github/templates/claude-plugin.json.tmpl'
|
||||
- '.github/workflows/build-ports.yml'
|
||||
- 'LICENSE'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: claude-code
|
||||
runtime: python
|
||||
branch: port-claude-code-py
|
||||
label: Claude Code
|
||||
target_dir: .claude/skills
|
||||
- platform: cursor
|
||||
runtime: powershell
|
||||
branch: port-cursor
|
||||
label: Cursor
|
||||
target_dir: .cursor/skills
|
||||
- platform: cursor
|
||||
runtime: python
|
||||
branch: port-cursor-py
|
||||
label: Cursor
|
||||
target_dir: .cursor/skills
|
||||
- platform: codex
|
||||
runtime: powershell
|
||||
branch: port-codex
|
||||
label: Codex
|
||||
target_dir: .codex/skills
|
||||
- platform: codex
|
||||
runtime: python
|
||||
branch: port-codex-py
|
||||
label: Codex
|
||||
target_dir: .codex/skills
|
||||
- platform: copilot
|
||||
runtime: powershell
|
||||
branch: port-copilot
|
||||
label: GitHub Copilot
|
||||
target_dir: .github/skills
|
||||
- platform: copilot
|
||||
runtime: python
|
||||
branch: port-copilot-py
|
||||
label: GitHub Copilot
|
||||
target_dir: .github/skills
|
||||
- platform: augment
|
||||
runtime: powershell
|
||||
branch: port-augment
|
||||
label: Augment
|
||||
target_dir: .augment/skills
|
||||
- platform: augment
|
||||
runtime: python
|
||||
branch: port-augment-py
|
||||
label: Augment
|
||||
target_dir: .augment/skills
|
||||
- platform: cline
|
||||
runtime: powershell
|
||||
branch: port-cline
|
||||
label: Cline
|
||||
target_dir: .cline/skills
|
||||
- platform: cline
|
||||
runtime: python
|
||||
branch: port-cline-py
|
||||
label: Cline
|
||||
target_dir: .cline/skills
|
||||
- platform: kilo
|
||||
runtime: powershell
|
||||
branch: port-kilo
|
||||
label: Kilo Code
|
||||
target_dir: .kilocode/skills
|
||||
- platform: kilo
|
||||
runtime: python
|
||||
branch: port-kilo-py
|
||||
label: Kilo Code
|
||||
target_dir: .kilocode/skills
|
||||
- platform: kiro
|
||||
runtime: powershell
|
||||
branch: port-kiro
|
||||
label: Kiro
|
||||
target_dir: .kiro/skills
|
||||
- platform: kiro
|
||||
runtime: python
|
||||
branch: port-kiro-py
|
||||
label: Kiro
|
||||
target_dir: .kiro/skills
|
||||
- platform: gemini
|
||||
runtime: powershell
|
||||
branch: port-gemini
|
||||
label: Gemini CLI
|
||||
target_dir: .gemini/skills
|
||||
- platform: gemini
|
||||
runtime: python
|
||||
branch: port-gemini-py
|
||||
label: Gemini CLI
|
||||
target_dir: .gemini/skills
|
||||
- platform: opencode
|
||||
runtime: powershell
|
||||
branch: port-opencode
|
||||
label: OpenCode
|
||||
target_dir: .opencode/skills
|
||||
- platform: opencode
|
||||
runtime: python
|
||||
branch: port-opencode-py
|
||||
label: OpenCode
|
||||
target_dir: .opencode/skills
|
||||
- platform: roo
|
||||
runtime: powershell
|
||||
branch: port-roo
|
||||
label: Roo Code
|
||||
target_dir: .roo/skills
|
||||
- platform: roo
|
||||
runtime: python
|
||||
branch: port-roo-py
|
||||
label: Roo Code
|
||||
target_dir: .roo/skills
|
||||
- platform: windsurf
|
||||
runtime: powershell
|
||||
branch: port-windsurf
|
||||
label: Windsurf
|
||||
target_dir: .windsurf/skills
|
||||
- platform: windsurf
|
||||
runtime: python
|
||||
branch: port-windsurf-py
|
||||
label: Windsurf
|
||||
target_dir: .windsurf/skills
|
||||
- platform: agents
|
||||
runtime: powershell
|
||||
branch: port-agents
|
||||
label: Agent Skills
|
||||
target_dir: .agents/skills
|
||||
- platform: agents
|
||||
runtime: python
|
||||
branch: port-agents-py
|
||||
label: Agent Skills
|
||||
target_dir: .agents/skills
|
||||
|
||||
steps:
|
||||
- name: Checkout main
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Build skills tree for ${{ matrix.platform }} (${{ matrix.runtime }})
|
||||
run: |
|
||||
python scripts/switch.py "${{ matrix.platform }}" \
|
||||
--project-dir build \
|
||||
--runtime "${{ matrix.runtime }}"
|
||||
|
||||
- name: Render port README
|
||||
env:
|
||||
PLATFORM_LABEL: ${{ matrix.label }}
|
||||
PLATFORM_DIR: ${{ matrix.target_dir }}
|
||||
RUNTIME_LABEL: ${{ matrix.runtime == 'powershell' && 'PowerShell' || 'Python' }}
|
||||
COMMIT_SHA: ${{ github.sha }}
|
||||
MAIN_REPO_URL: https://github.com/${{ github.repository }}
|
||||
run: |
|
||||
sed \
|
||||
-e "s|{{PLATFORM_LABEL}}|${PLATFORM_LABEL}|g" \
|
||||
-e "s|{{PLATFORM_DIR}}|${PLATFORM_DIR}|g" \
|
||||
-e "s|{{RUNTIME_LABEL}}|${RUNTIME_LABEL}|g" \
|
||||
-e "s|{{COMMIT_SHA}}|${COMMIT_SHA}|g" \
|
||||
-e "s|{{MAIN_REPO_URL}}|${MAIN_REPO_URL}|g" \
|
||||
.github/templates/README.port.md.tmpl > build/README.md
|
||||
|
||||
- name: Render Codex plugin manifest
|
||||
if: matrix.platform == 'codex'
|
||||
env:
|
||||
PLUGIN_NAME: ${{ matrix.runtime == 'python' && '1c-skills-py' || '1c-skills' }}
|
||||
RUNTIME_LABEL: ${{ matrix.runtime == 'powershell' && 'PowerShell' || 'Python' }}
|
||||
SHORT_DESCRIPTION: ${{ matrix.runtime == 'python' && 'Python runtime (Linux/Mac/Windows)' || 'PowerShell runtime (Windows-first)' }}
|
||||
COMMIT_SHA: ${{ github.sha }}
|
||||
run: |
|
||||
VERSION="$(date -u +%Y.%-m.%-d)+${COMMIT_SHA::7}"
|
||||
mkdir -p build/.codex-plugin
|
||||
sed \
|
||||
-e "s|{{PLUGIN_NAME}}|${PLUGIN_NAME}|g" \
|
||||
-e "s|{{VERSION}}|${VERSION}|g" \
|
||||
-e "s|{{RUNTIME_LABEL}}|${RUNTIME_LABEL}|g" \
|
||||
-e "s|{{SHORT_DESCRIPTION}}|${SHORT_DESCRIPTION}|g" \
|
||||
.github/templates/codex-plugin.json.tmpl > build/.codex-plugin/plugin.json
|
||||
|
||||
- name: Render Claude plugin manifest (Py variant)
|
||||
if: matrix.platform == 'claude-code' && matrix.runtime == 'python'
|
||||
env:
|
||||
PLUGIN_NAME: 1c-skills-py
|
||||
run: |
|
||||
mkdir -p build/.claude-plugin
|
||||
sed -e "s|{{PLUGIN_NAME}}|${PLUGIN_NAME}|g" \
|
||||
.github/templates/claude-plugin.json.tmpl > build/.claude-plugin/plugin.json
|
||||
|
||||
- name: Copy LICENSE
|
||||
run: cp LICENSE build/LICENSE
|
||||
|
||||
- name: Force-push orphan snapshot to ${{ matrix.branch }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
cd build
|
||||
git init -q -b master
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git add -A
|
||||
git commit -q -m "Auto-build: ${{ matrix.platform }} (${{ matrix.runtime }}) from ${GITHUB_SHA::7}"
|
||||
git push --force \
|
||||
"https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git" \
|
||||
"master:${{ matrix.branch }}"
|
||||
+1
-1
@@ -37,7 +37,7 @@ __pycache__/
|
||||
*.mp4
|
||||
|
||||
# Навыки, скопированные для других AI-платформ (генерируются scripts/switch.py)
|
||||
.agents/
|
||||
.agents/skills/
|
||||
.augment/
|
||||
.cline/
|
||||
.codex/
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
# 1C Skills for Claude Code
|
||||
|
||||
> **Work in progress** — навыки находятся в стадии тестирования, отладки и оптимизации.
|
||||
> **Проект живой, активно развивается** — добавляются новые возможности, отлавливаются и исправляются баги, производится оптимизация. Следите за обновлениями.
|
||||
|
||||
Набор навыков для AI-агентов (в первую очередь для [Claude Code](https://docs.anthropic.com/en/docs/claude-code/skills)), помогающий охватить полный цикл разработки на платформе 1С:Предприятие 8.3 — от создания конфигураций, расширений, внешних обработок и отчётов до загрузки изменений в информационную базу, обновления, запуска, публикации на веб-сервере (портативная версия Apache), тестирования через веб-клиент и записи видеоинструкций.
|
||||
|
||||
Навыки дают модели готовые абстракции над XML-форматами и CLI конфигуратора — чтобы работать с сутью задачи, а не с деталями реализации. А веб-тестирование даёт ей глаза и руки для взаимодействия с интерфейсом 1С.
|
||||
|
||||
## Версии навыков для разных платформ
|
||||
|
||||
> **PS** — версия со скриптами на PowerShell (стандартная, для Windows). **Py** — версия со скриптами на Python (если PowerShell не подходит). Можно начать с **PS** — это основной вариант.
|
||||
|
||||
**Claude Code** [PS](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/main) · [Py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-claude-code-py) — **Cursor** [PS](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-cursor) · [Py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-cursor-py) — **Codex** [PS](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-codex) · [Py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-codex-py) — [Другие платформы →](#поддерживаемые-платформы)
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
Скопируйте каталог `.claude/skills/` из этого репозитория в корень вашего проекта. Навыки станут доступны при запуске Claude Code из этого каталога.
|
||||
@@ -16,6 +22,21 @@
|
||||
└── ...
|
||||
```
|
||||
|
||||
Или установите как плагин Claude Code:
|
||||
|
||||
```
|
||||
/plugin marketplace add https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
/plugin install 1c-skills@cc-1c-skills # PowerShell (Windows)
|
||||
/plugin install 1c-skills-py@cc-1c-skills # Python (Linux/Mac или если PS недоступен)
|
||||
```
|
||||
|
||||
Или установите как плагин OpenAI Codex:
|
||||
|
||||
```
|
||||
codex plugin marketplace add Nikolay-Shirokov/cc-1c-skills
|
||||
codex /plugins # выберите 1c-skills (PowerShell) или 1c-skills-py (Python) и нажмите Install
|
||||
```
|
||||
|
||||
Или используйте скрипт установки:
|
||||
|
||||
```bash
|
||||
@@ -61,9 +82,37 @@ python tools/cc-1c-skills/scripts/switch.py
|
||||
- **1С:Предприятие 8.3** — для сборки/разборки EPF/ERF (навыки генерации XML работают без платформы)
|
||||
- **Node.js 18+** — для `/web-test` (тестирование через браузер)
|
||||
|
||||
<a id="поддерживаемые-платформы"></a>
|
||||
### Другие AI-платформы
|
||||
|
||||
Навыки построены на открытом стандарте [Agent Skills](https://agentskills.io/specification) и совместимы с любой платформой, поддерживающей этот формат. Скрипт `switch.py` копирует навыки в нужный каталог с перезаписью путей:
|
||||
Навыки построены на открытом стандарте [Agent Skills](https://agentskills.io/specification) и совместимы с любой платформой, поддерживающей этот формат. Самый быстрый путь — скачать готовую сборку под нужную платформу из ветки ниже (**Code → Download ZIP**) и распаковать в корень своего проекта.
|
||||
|
||||
#### Поддерживаемые платформы
|
||||
|
||||
| Платформа | Целевой каталог | PowerShell | Python |
|
||||
|-----------|----------------|------------|--------|
|
||||
| Claude Code | `.claude/skills/` | [main](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/main) | [port-claude-code-py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-claude-code-py) |
|
||||
| Cursor | `.cursor/skills/` | [port-cursor](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-cursor) | [port-cursor-py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-cursor-py) |
|
||||
| OpenAI Codex | `.codex/skills/` | [port-codex](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-codex) | [port-codex-py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-codex-py) |
|
||||
| GitHub Copilot | `.github/skills/` | [port-copilot](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-copilot) | [port-copilot-py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-copilot-py) |
|
||||
| Augment | `.augment/skills/` | [port-augment](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-augment) | [port-augment-py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-augment-py) |
|
||||
| Cline | `.cline/skills/` | [port-cline](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-cline) | [port-cline-py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-cline-py) |
|
||||
| Kilo Code | `.kilocode/skills/` | [port-kilo](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-kilo) | [port-kilo-py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-kilo-py) |
|
||||
| Kiro | `.kiro/skills/` | [port-kiro](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-kiro) | [port-kiro-py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-kiro-py) |
|
||||
| Gemini CLI | `.gemini/skills/` | [port-gemini](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-gemini) | [port-gemini-py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-gemini-py) |
|
||||
| OpenCode | `.opencode/skills/` | [port-opencode](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-opencode) | [port-opencode-py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-opencode-py) |
|
||||
| Roo Code | `.roo/skills/` | [port-roo](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-roo) | [port-roo-py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-roo-py) |
|
||||
| Windsurf | `.windsurf/skills/` | [port-windsurf](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-windsurf) | [port-windsurf-py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-windsurf-py) |
|
||||
| Agent Skills | `.agents/skills/` | [port-agents](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-agents) | [port-agents-py](https://github.com/Nikolay-Shirokov/cc-1c-skills/tree/port-agents-py) |
|
||||
|
||||
Готовые ветки `port-*` пересобираются автоматически на каждое изменение в навыках. Если нужна свежая сборка прямо сейчас — соберите [локально через `switch.py`](#альтернативный-способ--собрать-локально-через-switchpy).
|
||||
|
||||
Некоторые платформы (Augment, Cline, VS Code/Copilot) также сканируют `.claude/skills/` как fallback — для них достаточно `main`.
|
||||
|
||||
<a id="альтернативный-способ--собрать-локально-через-switchpy"></a>
|
||||
#### Альтернативный способ — собрать локально через `switch.py`
|
||||
|
||||
Если нужна свежая сборка под свою платформу (или платформа ещё не в матрице port-веток):
|
||||
|
||||
```bash
|
||||
python scripts/switch.py # интерактивный режим
|
||||
@@ -80,26 +129,6 @@ python scripts/switch.py --undo cursor # удалить
|
||||
|
||||
> ⚠ **Известные ограничения `--link`:** Node.js резолвит `__dirname` через junction к реальному пути источника, а не к каталогу проекта. Это может приводить к тому, что навыки с Node.js-скриптами (например, `/web-test`) будут записывать файлы в каталог репозитория навыков вместо каталога проекта. При возникновении проблем переключитесь на копирование (без `--link`).
|
||||
|
||||
Поддерживаемые платформы:
|
||||
|
||||
| Платформа | Целевой каталог | `switch.py <platform>` |
|
||||
|-----------|----------------|------------------------|
|
||||
| Claude Code | `.claude/skills/` | `claude-code` |
|
||||
| Augment | `.augment/skills/` | `augment` |
|
||||
| Cline | `.cline/skills/` | `cline` |
|
||||
| Cursor | `.cursor/skills/` | `cursor` |
|
||||
| GitHub Copilot | `.github/skills/` | `copilot` |
|
||||
| Kilo Code | `.kilocode/skills/` | `kilo` |
|
||||
| Kiro | `.kiro/skills/` | `kiro` |
|
||||
| OpenAI Codex | `.codex/skills/` | `codex` |
|
||||
| Gemini CLI | `.gemini/skills/` | `gemini` |
|
||||
| OpenCode | `.opencode/skills/` | `opencode` |
|
||||
| Roo Code | `.roo/skills/` | `roo` |
|
||||
| Windsurf | `.windsurf/skills/` | `windsurf` |
|
||||
| Agent Skills | `.agents/skills/` | `agents` |
|
||||
|
||||
Некоторые платформы (Augment, Cline, VS Code/Copilot) также сканируют `.claude/skills/` как fallback — для них копирование необязательно, но `switch.py` даёт явный контроль над путями.
|
||||
|
||||
Автоактивация — основной режим: просто опишите задачу своими словами, ассистент сам подберёт нужный навык по `description` в SKILL.md. Слеш-команды (например `/epf-init`) — для точного контроля, когда нужно вызвать конкретный навык.
|
||||
|
||||
### Переключение рантайма (PowerShell ↔ Python)
|
||||
|
||||
@@ -1199,6 +1199,7 @@ ChildItems
|
||||
| Popup | ~40% |
|
||||
| PictureDecoration | ~40% |
|
||||
| PictureField | ~15% |
|
||||
| RadioButtonField | ~8.5% |
|
||||
| CalendarField | ~5% |
|
||||
|
||||
---
|
||||
@@ -1207,7 +1208,6 @@ ChildItems
|
||||
|
||||
Следующие элементы управления существуют в платформе, но не использованы в БП 3.0:
|
||||
|
||||
- `RadioButtonField`
|
||||
- `TrackBarField`
|
||||
- `ProgressBarField`
|
||||
- `TextDocumentField`
|
||||
|
||||
+58
-1
@@ -199,6 +199,35 @@
|
||||
| `path` | string | DataPath |
|
||||
| `titleLocation` | string | Расположение заголовка |
|
||||
|
||||
#### radio — RadioButtonField
|
||||
|
||||
```json
|
||||
{
|
||||
"radio": "СпособКурса",
|
||||
"path": "Объект.СпособУстановкиКурса",
|
||||
"radioButtonType": "Auto",
|
||||
"choiceList": [
|
||||
{ "value": "Enum.СпособыКурса.EnumValue.Авто", "presentation": "автоматически" },
|
||||
{ "value": "Enum.СпособыКурса.EnumValue.Ручной", "presentation": { "ru": "вручную", "en": "manual" } }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
| Свойство | Тип | Описание |
|
||||
|----------|-----|----------|
|
||||
| `path` | string | DataPath |
|
||||
| `radioButtonType` | string | `Auto` (по умолчанию), `RadioButtons`, `Tumbler` |
|
||||
| `columnsCount` | int | Число колонок раскладки |
|
||||
| `titleLocation` | string | Расположение заголовка (компилятор подставляет `None`, если не задан) |
|
||||
| `choiceList` | array | Варианты выбора: массив `{ value, presentation }` |
|
||||
|
||||
`choiceList[*]`:
|
||||
|
||||
| Свойство | Тип | Описание |
|
||||
|----------|-----|----------|
|
||||
| `value` | string/number/bool | Значение варианта. Для перечисления — `"Enum.ИмяТипа.EnumValue.ИмяЗначения"` (xsi:type автоматически: `xr:DesignTimeRef` / `xs:string` / `xs:decimal` / `xs:boolean`) |
|
||||
| `presentation` | string или object | Текст рядом с переключателем. Строка → ru; объект `{ru, en, ...}` → мультиязык. Если не задано — выводится из имени значения |
|
||||
|
||||
#### label — LabelDecoration
|
||||
|
||||
```json
|
||||
@@ -239,7 +268,7 @@
|
||||
| Свойство | Тип | Описание |
|
||||
|----------|-----|----------|
|
||||
| `path` | string | DataPath |
|
||||
| `columns` | array | Колонки (элементы input/check/labelField/picField) |
|
||||
| `columns` | array | Колонки (элементы input/check/labelField/picField, либо `columnGroup` для группировки) |
|
||||
| `representation` | string | `List`, `Tree`, `HierarchicalList` |
|
||||
| `changeRowSet` | bool | Разрешить добавление/удаление строк |
|
||||
| `changeRowOrder` | bool | Разрешить перемещение строк |
|
||||
@@ -249,6 +278,33 @@
|
||||
| `commandBarLocation` | string | `None`, `Top`, `Bottom`, `Auto` |
|
||||
| `searchStringLocation` | string | `None`, `Top`, `Bottom`, `CommandBar`, `Auto` |
|
||||
|
||||
#### columnGroup — ColumnGroup
|
||||
|
||||
Группа колонок таблицы. Используется только внутри `columns` таблицы. Допускается вложение `columnGroup` в `columnGroup`.
|
||||
|
||||
```json
|
||||
{ "table": "Список", "path": "Список", "columns": [
|
||||
{ "columnGroup": "horizontal", "name": "ГруппаДата", "title": "Срок", "children": [
|
||||
{ "input": "ДатаНачала", "path": "Список.ДатаНачала" },
|
||||
{ "input": "ДатаОкончания", "path": "Список.ДатаОкончания" }
|
||||
]},
|
||||
{ "columnGroup": "inCell", "name": "ГруппаИсполнитель", "showInHeader": true, "children": [
|
||||
{ "input": "Исполнитель", "path": "Список.Исполнитель" }
|
||||
]}
|
||||
]}
|
||||
```
|
||||
|
||||
| Свойство | Тип | Описание |
|
||||
|----------|-----|----------|
|
||||
| `columnGroup` | string | Ориентация: `horizontal`, `vertical`, `inCell` (склейка колонок в одной ячейке шапки) |
|
||||
| `name` | string | Имя элемента (рекомендуется задавать явно) |
|
||||
| `title` | string/object | Заголовок группы |
|
||||
| `showTitle` | bool | Показывать заголовок |
|
||||
| `showInHeader` | bool | Показывать в шапке таблицы |
|
||||
| `width` | int | Ширина |
|
||||
| `horizontalStretch` | bool | Растягивание |
|
||||
| `children` | array | Колонки внутри группы |
|
||||
|
||||
#### pages / page — Pages / Page
|
||||
|
||||
```json
|
||||
@@ -437,6 +493,7 @@ Pages поддерживает `pagesRepresentation`: `None`, `TabsOnTop`, `Tabs
|
||||
| UsualGroup | ExtendedTooltip |
|
||||
| InputField | ContextMenu, ExtendedTooltip |
|
||||
| CheckBoxField | ContextMenu, ExtendedTooltip |
|
||||
| RadioButtonField | ContextMenu, ExtendedTooltip |
|
||||
| LabelDecoration | ContextMenu, ExtendedTooltip |
|
||||
| LabelField | ContextMenu, ExtendedTooltip |
|
||||
| PictureDecoration | ContextMenu, ExtendedTooltip |
|
||||
|
||||
+98
-20
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# switch.py v1.3 — Переключение навыков 1С между AI-платформами и рантаймами
|
||||
# switch.py v1.6 — Переключение навыков 1С между AI-платформами и рантаймами
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
"""
|
||||
Копирует (или создаёт ссылки на) навыки из .claude/skills/ на другие AI-платформы
|
||||
@@ -43,6 +43,11 @@ PLATFORMS = {
|
||||
|
||||
SOURCE_PREFIX = '.claude/skills'
|
||||
|
||||
# ${CLAUDE_SKILL_DIR}/../<other>/<rest> — cross-skill reference (more specific, match first)
|
||||
RX_SKILL_DIR_CROSS = re.compile(r'\$\{CLAUDE_SKILL_DIR\}/\.\./([a-z][a-z0-9-]+)/')
|
||||
# ${CLAUDE_SKILL_DIR}/<rest> — same-skill reference
|
||||
SKILL_DIR_VAR = '${CLAUDE_SKILL_DIR}/'
|
||||
|
||||
# Рекомендуемые записи для .gitignore целевого проекта
|
||||
GITIGNORE_RECOMMENDATIONS = [
|
||||
'.v8-project.json',
|
||||
@@ -56,8 +61,36 @@ GITIGNORE_RECOMMENDATIONS = [
|
||||
# ---------------------------------------------------------------------------
|
||||
# Runtime regex patterns (from switch-to-python.py / switch-to-powershell.py)
|
||||
# ---------------------------------------------------------------------------
|
||||
RX_PS = re.compile(r'powershell\.exe\s+(?:-NoProfile\s+)?-File\s+(.+?)\.ps1')
|
||||
RX_PY = re.compile(r"python\s+('?[\w./_-]+?)\.py")
|
||||
# Capture optional surrounding quote (group 'q') and bare path (group 'path').
|
||||
# Path matches non-whitespace non-quote chars to support ${CLAUDE_SKILL_DIR}/...
|
||||
# Optional -ExecutionPolicy <value> between -NoProfile and -File (used for codex target).
|
||||
RX_PS = re.compile(
|
||||
r'powershell\.exe\s+'
|
||||
r'(?:-NoProfile\s+)?'
|
||||
r'(?:-ExecutionPolicy\s+\S+\s+)?'
|
||||
r'-File\s+(?P<q>["\']?)(?P<path>[^"\s]+?)\.ps1(?P=q)?'
|
||||
)
|
||||
RX_PY = re.compile(r"python\s+(?P<q>[\"']?)(?P<path>[^\"\s]+?)\.py(?P=q)?")
|
||||
|
||||
# Платформы, требующие -ExecutionPolicy Bypass (Codex запускает powershell как
|
||||
# login-shell, профиль грузится и упирается в Restricted policy).
|
||||
PS_BYPASS_PLATFORMS = {'codex'}
|
||||
|
||||
|
||||
def emit_ps_invocation(path, quote, platform):
|
||||
"""Build canonical powershell.exe invocation for a target platform."""
|
||||
ep = ' -ExecutionPolicy Bypass' if platform in PS_BYPASS_PLATFORMS else ''
|
||||
return f"powershell.exe -NoProfile{ep} -File {quote}{path}.ps1{quote}"
|
||||
|
||||
|
||||
def normalize_ps_invocation(content, platform):
|
||||
"""Re-emit existing powershell.exe ...ps1 invocations with platform flags.
|
||||
|
||||
Idempotent: matches both with and without -ExecutionPolicy in source.
|
||||
"""
|
||||
def repl(m):
|
||||
return emit_ps_invocation(m.group('path'), m.group('q'), platform)
|
||||
return RX_PS.sub(repl, content)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -148,23 +181,40 @@ def classify_skill_runtime(skill_dir):
|
||||
return 'ps' if has_ps else ('py' if has_py else 'none')
|
||||
|
||||
|
||||
def expand_skill_path(path, skill_name, source_prefix=SOURCE_PREFIX):
|
||||
"""Expand ${CLAUDE_SKILL_DIR} placeholder to a path relative to source_prefix.
|
||||
|
||||
${CLAUDE_SKILL_DIR}/<rest> -> <source_prefix>/<skill_name>/<rest>
|
||||
${CLAUDE_SKILL_DIR}/../<other>/<rest> -> <source_prefix>/<other>/<rest>
|
||||
Anything else returned as-is (legacy literal path).
|
||||
"""
|
||||
var = '${CLAUDE_SKILL_DIR}/'
|
||||
if not path.startswith(var):
|
||||
return path
|
||||
rest = path[len(var):]
|
||||
if rest.startswith('../'):
|
||||
return f'{source_prefix}/{rest[3:]}'
|
||||
return f'{source_prefix}/{skill_name}/{rest}'
|
||||
|
||||
|
||||
def check_missing_files(skill_dir, target_runtime, root):
|
||||
"""Check if target runtime script files exist for a skill.
|
||||
|
||||
Returns list of missing file paths (relative to root).
|
||||
"""
|
||||
missing = []
|
||||
skill_name = os.path.basename(os.path.normpath(skill_dir))
|
||||
for md_path in collect_md_files(skill_dir):
|
||||
with open(md_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
if target_runtime == 'python':
|
||||
for m in RX_PS.findall(content):
|
||||
py_path = m.lstrip("'") + '.py'
|
||||
for m in RX_PS.finditer(content):
|
||||
py_path = expand_skill_path(m.group('path'), skill_name) + '.py'
|
||||
if not os.path.isfile(os.path.join(root, py_path)):
|
||||
missing.append(py_path)
|
||||
elif target_runtime == 'powershell':
|
||||
for m in RX_PY.findall(content):
|
||||
ps1_path = m.lstrip("'") + '.ps1'
|
||||
for m in RX_PY.finditer(content):
|
||||
ps1_path = expand_skill_path(m.group('path'), skill_name) + '.ps1'
|
||||
if not os.path.isfile(os.path.join(root, ps1_path)):
|
||||
missing.append(ps1_path)
|
||||
return missing
|
||||
@@ -179,17 +229,39 @@ def is_different_dir(dir1, dir2):
|
||||
# ---------------------------------------------------------------------------
|
||||
# Transformations
|
||||
# ---------------------------------------------------------------------------
|
||||
def rewrite_paths(content, source_prefix, target_prefix):
|
||||
"""Replace .claude/skills/ path prefix with target platform prefix."""
|
||||
return content.replace(source_prefix + '/', target_prefix + '/')
|
||||
def rewrite_paths(content, platform, target_prefix, skill_name):
|
||||
"""Resolve ${CLAUDE_SKILL_DIR} placeholders to target platform prefix.
|
||||
|
||||
For claude-code target, leave ${CLAUDE_SKILL_DIR} untouched — Claude Code
|
||||
substitutes it natively at invocation time. For all other targets,
|
||||
expand to a literal path:
|
||||
${CLAUDE_SKILL_DIR}/<rest> → <target_prefix>/<skill_name>/<rest>
|
||||
${CLAUDE_SKILL_DIR}/../<other>/<rest> → <target_prefix>/<other>/<rest>
|
||||
"""
|
||||
if platform == 'claude-code':
|
||||
return content
|
||||
# Cross-skill first (more specific pattern)
|
||||
content = RX_SKILL_DIR_CROSS.sub(f'{target_prefix}/\\1/', content)
|
||||
# Then same-skill
|
||||
content = content.replace(SKILL_DIR_VAR, f'{target_prefix}/{skill_name}/')
|
||||
return content
|
||||
|
||||
|
||||
def switch_runtime_content(content, target_runtime):
|
||||
"""Switch runtime invocations in .md content. Returns (new_content, switched)."""
|
||||
def switch_runtime_content(content, target_runtime, platform='claude-code'):
|
||||
"""Switch runtime invocations in .md content. Returns (new_content, switched).
|
||||
|
||||
Platform controls flags on emitted powershell invocations
|
||||
(codex requires -ExecutionPolicy Bypass).
|
||||
"""
|
||||
if target_runtime == 'python':
|
||||
new = RX_PS.sub(r'python \1.py', content)
|
||||
def to_py(m):
|
||||
q = m.group('q')
|
||||
return f"python {q}{m.group('path')}.py{q}"
|
||||
new = RX_PS.sub(to_py, content)
|
||||
elif target_runtime == 'powershell':
|
||||
new = RX_PY.sub(r'powershell.exe -NoProfile -File \1.ps1', content)
|
||||
def to_ps(m):
|
||||
return emit_ps_invocation(m.group('path'), m.group('q'), platform)
|
||||
new = RX_PY.sub(to_ps, content)
|
||||
else:
|
||||
return content, False
|
||||
return new, new != content
|
||||
@@ -305,15 +377,19 @@ def cmd_install(platform, runtime, project_dir):
|
||||
with open(md_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
new_content = rewrite_paths(content, SOURCE_PREFIX, target_prefix)
|
||||
new_content = rewrite_paths(content, platform, target_prefix, skill_name)
|
||||
|
||||
# Apply runtime switch (skip for single-runtime skills
|
||||
# where target runtime is not available)
|
||||
if not skip_runtime:
|
||||
if runtime == 'python':
|
||||
new_content, _ = switch_runtime_content(new_content, 'python')
|
||||
new_content, _ = switch_runtime_content(new_content, 'python', platform)
|
||||
elif runtime == 'powershell':
|
||||
new_content, _ = switch_runtime_content(new_content, 'powershell')
|
||||
new_content, _ = switch_runtime_content(new_content, 'powershell', platform)
|
||||
|
||||
# Normalize any remaining powershell invocations with platform flags
|
||||
# (covers skip_runtime=True case where source PS commands stayed)
|
||||
new_content = normalize_ps_invocation(new_content, platform)
|
||||
|
||||
if new_content != content:
|
||||
with open(md_path, 'w', encoding='utf-8') as f:
|
||||
@@ -448,14 +524,14 @@ def cmd_switch_runtime(runtime, project_dir):
|
||||
# Skip runtime conversion for single-runtime skills where
|
||||
# target files don't exist (e.g. img-grid has only .py)
|
||||
cur_rt = classify_skill_runtime(skill_path)
|
||||
missing = check_missing_files(skill_path, runtime, repo_root())
|
||||
missing = check_missing_files(skill_path, runtime, project_dir)
|
||||
skip_runtime = bool(missing) and (
|
||||
(runtime == 'python' and cur_rt in ('ps', 'none'))
|
||||
or (runtime == 'powershell' and cur_rt in ('py', 'none'))
|
||||
)
|
||||
|
||||
info, warnings = collect_runtime_messages(
|
||||
skill_name, skill_path, runtime, repo_root())
|
||||
skill_name, skill_path, runtime, project_dir)
|
||||
all_info.extend(info)
|
||||
all_warnings.extend(warnings)
|
||||
|
||||
@@ -466,7 +542,9 @@ def cmd_switch_runtime(runtime, project_dir):
|
||||
with open(md_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
new_content, changed = switch_runtime_content(content, runtime)
|
||||
new_content, _ = switch_runtime_content(content, runtime, platform_name)
|
||||
new_content = normalize_ps_invocation(new_content, platform_name)
|
||||
changed = new_content != content
|
||||
|
||||
if changed:
|
||||
with open(md_path, 'w', encoding='utf-8') as f:
|
||||
|
||||
+15
-1
@@ -14,10 +14,23 @@ node tests/skills/runner.mjs --verbose # подробн
|
||||
node tests/skills/runner.mjs --update-snapshots # обновить эталоны
|
||||
node tests/skills/runner.mjs --runtime python # запуск на PY-версиях
|
||||
node tests/skills/runner.mjs --json report.json # JSON-отчёт
|
||||
node tests/skills/runner.mjs --concurrency 4 # ограничить параллельность
|
||||
node tests/skills/runner.mjs --with-validation # + платформенная валидация
|
||||
node tests/skills/runner.mjs --help # полный список опций
|
||||
```
|
||||
|
||||
Exit code: 0 = все прошли, 1 = есть падения.
|
||||
|
||||
### Платформенная верификация снапшотов
|
||||
|
||||
```bash
|
||||
node tests/skills/verify-snapshots.mjs --skill form-compile # один навык
|
||||
node tests/skills/verify-snapshots.mjs --case table # один кейс
|
||||
node tests/skills/verify-snapshots.mjs --help # полный список опций
|
||||
```
|
||||
|
||||
Перепрогоняет навык из DSL кейса и грузит результат в 1С — отлавливает случаи, когда снапшоты обновили, но платформа уже не принимает выход.
|
||||
|
||||
## Что делать при падении
|
||||
|
||||
1. Смотри **case id** в выводе — это путь к файлу кейса (можно перезапустить: `node runner.mjs <case-id>`)
|
||||
@@ -194,7 +207,8 @@ node tests/skills/runner.mjs cases/meta-compile/enum --update-snapshots # од
|
||||
|
||||
```
|
||||
tests/skills/
|
||||
runner.mjs # тест-раннер
|
||||
runner.mjs # тест-раннер (snapshot-сравнение)
|
||||
verify-snapshots.mjs # платформенная верификация снапшотов
|
||||
README.md # этот файл
|
||||
.cache/ # кэш фикстур (в .gitignore)
|
||||
cases/
|
||||
|
||||
@@ -1,16 +1,63 @@
|
||||
{
|
||||
"name": "Установить начальную страницу (template + left/right + visibility/roles)",
|
||||
"preRun": [
|
||||
{
|
||||
"script": "meta-compile/scripts/meta-compile",
|
||||
"input": { "type": "Catalog", "name": "Товары" },
|
||||
"args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" }
|
||||
},
|
||||
{
|
||||
"script": "form-add/scripts/form-add",
|
||||
"args": { "-ObjectPath": "{workDir}/Catalogs/Товары", "-FormName": "ФормаСписка", "-Purpose": "List" }
|
||||
},
|
||||
{
|
||||
"script": "form-add/scripts/form-add",
|
||||
"args": { "-ObjectPath": "{workDir}/Catalogs/Товары", "-FormName": "ФормаЭлемента", "-Purpose": "Object" }
|
||||
},
|
||||
{
|
||||
"script": "meta-compile/scripts/meta-compile",
|
||||
"input": { "type": "Catalog", "name": "Контрагенты" },
|
||||
"args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" }
|
||||
},
|
||||
{
|
||||
"script": "form-add/scripts/form-add",
|
||||
"args": { "-ObjectPath": "{workDir}/Catalogs/Контрагенты", "-FormName": "ФормаСписка", "-Purpose": "List" }
|
||||
},
|
||||
{
|
||||
"script": "form-add/scripts/form-add",
|
||||
"args": { "-ObjectPath": "{workDir}/Catalogs/Контрагенты", "-FormName": "ФормаОбъекта", "-Purpose": "Object" }
|
||||
},
|
||||
{
|
||||
"script": "meta-compile/scripts/meta-compile",
|
||||
"input": { "type": "DataProcessor", "name": "Поиск" },
|
||||
"args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" }
|
||||
},
|
||||
{
|
||||
"script": "form-add/scripts/form-add",
|
||||
"args": { "-ObjectPath": "{workDir}/DataProcessors/Поиск", "-FormName": "ФормаПоиска", "-Purpose": "Object" }
|
||||
},
|
||||
{
|
||||
"script": "role-compile/scripts/role-compile",
|
||||
"input": { "name": "Оператор", "objects": [] },
|
||||
"args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" }
|
||||
},
|
||||
{
|
||||
"script": "role-compile/scripts/role-compile",
|
||||
"input": { "name": "ПолныеПрава", "objects": [] },
|
||||
"args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" }
|
||||
}
|
||||
],
|
||||
"input": [
|
||||
{
|
||||
"operation": "set-home-page",
|
||||
"value": {
|
||||
"template": "TwoColumnsVariableWidth",
|
||||
"left": [
|
||||
"CommonForm.НачалоРаботы",
|
||||
{ "form": "CommonForm.СписокЗадач", "height": 100, "visibility": false },
|
||||
"Catalog.Товары.Form.ФормаСписка",
|
||||
{ "form": "Catalog.Товары.Form.ФормаЭлемента", "height": 100, "visibility": false },
|
||||
{ "form": "Справочник.Контрагенты.ФормаСписка", "height": 50 },
|
||||
{
|
||||
"form": "CommonForm.РабочийСтолОператора",
|
||||
"form": "Catalog.Контрагенты.Form.ФормаОбъекта",
|
||||
"visibility": false,
|
||||
"roles": { "Role.Оператор": true, "ПолныеПрава": false }
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@
|
||||
<Characteristics/>
|
||||
<PredefinedDataUpdate>Auto</PredefinedDataUpdate>
|
||||
<EditType>InDialog</EditType>
|
||||
<QuickChoice>true</QuickChoice>
|
||||
<QuickChoice>false</QuickChoice>
|
||||
<ChoiceMode>BothWays</ChoiceMode>
|
||||
<InputByString>
|
||||
<xr:Field>Catalog.Товары.StandardAttribute.Description</xr:Field>
|
||||
|
||||
@@ -287,7 +287,7 @@
|
||||
<Characteristics/>
|
||||
<PredefinedDataUpdate>Auto</PredefinedDataUpdate>
|
||||
<EditType>InDialog</EditType>
|
||||
<QuickChoice>true</QuickChoice>
|
||||
<QuickChoice>false</QuickChoice>
|
||||
<ChoiceMode>BothWays</ChoiceMode>
|
||||
<InputByString>
|
||||
<xr:Field>Catalog.Остающийся.StandardAttribute.Description</xr:Field>
|
||||
|
||||
@@ -287,7 +287,7 @@
|
||||
<Characteristics/>
|
||||
<PredefinedDataUpdate>Auto</PredefinedDataUpdate>
|
||||
<EditType>InDialog</EditType>
|
||||
<QuickChoice>true</QuickChoice>
|
||||
<QuickChoice>false</QuickChoice>
|
||||
<ChoiceMode>BothWays</ChoiceMode>
|
||||
<InputByString>
|
||||
<xr:Field>Catalog.Удаляемый.StandardAttribute.Description</xr:Field>
|
||||
|
||||
@@ -0,0 +1,330 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
|
||||
<Catalog uuid="UUID-001">
|
||||
<InternalInfo>
|
||||
<xr:GeneratedType name="CatalogObject.Контрагенты" category="Object">
|
||||
<xr:TypeId>UUID-002</xr:TypeId>
|
||||
<xr:ValueId>UUID-003</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="CatalogRef.Контрагенты" category="Ref">
|
||||
<xr:TypeId>UUID-004</xr:TypeId>
|
||||
<xr:ValueId>UUID-005</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="CatalogSelection.Контрагенты" category="Selection">
|
||||
<xr:TypeId>UUID-006</xr:TypeId>
|
||||
<xr:ValueId>UUID-007</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="CatalogList.Контрагенты" category="List">
|
||||
<xr:TypeId>UUID-008</xr:TypeId>
|
||||
<xr:ValueId>UUID-009</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
<xr:GeneratedType name="CatalogManager.Контрагенты" category="Manager">
|
||||
<xr:TypeId>UUID-010</xr:TypeId>
|
||||
<xr:ValueId>UUID-011</xr:ValueId>
|
||||
</xr:GeneratedType>
|
||||
</InternalInfo>
|
||||
<Properties>
|
||||
<Name>Контрагенты</Name>
|
||||
<Synonym>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Контрагенты</v8:content>
|
||||
</v8:item>
|
||||
</Synonym>
|
||||
<Comment />
|
||||
<Hierarchical>false</Hierarchical>
|
||||
<HierarchyType>HierarchyFoldersAndItems</HierarchyType>
|
||||
<LimitLevelCount>false</LimitLevelCount>
|
||||
<LevelCount>2</LevelCount>
|
||||
<FoldersOnTop>true</FoldersOnTop>
|
||||
<UseStandardCommands>true</UseStandardCommands>
|
||||
<Owners />
|
||||
<SubordinationUse>ToItems</SubordinationUse>
|
||||
<CodeLength>9</CodeLength>
|
||||
<DescriptionLength>25</DescriptionLength>
|
||||
<CodeType>String</CodeType>
|
||||
<CodeAllowedLength>Variable</CodeAllowedLength>
|
||||
<CodeSeries>WholeCatalog</CodeSeries>
|
||||
<CheckUnique>false</CheckUnique>
|
||||
<Autonumbering>true</Autonumbering>
|
||||
<DefaultPresentation>AsDescription</DefaultPresentation>
|
||||
<StandardAttributes>
|
||||
<xr:StandardAttribute name="PredefinedDataName">
|
||||
<xr:LinkByType />
|
||||
<xr:FillChecking>DontCheck</xr:FillChecking>
|
||||
<xr:MultiLine>false</xr:MultiLine>
|
||||
<xr:FillFromFillingValue>false</xr:FillFromFillingValue>
|
||||
<xr:CreateOnInput>Auto</xr:CreateOnInput>
|
||||
<xr:MaxValue xsi:nil="true" />
|
||||
<xr:ToolTip />
|
||||
<xr:ExtendedEdit>false</xr:ExtendedEdit>
|
||||
<xr:Format />
|
||||
<xr:ChoiceForm />
|
||||
<xr:QuickChoice>Auto</xr:QuickChoice>
|
||||
<xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput>
|
||||
<xr:EditFormat />
|
||||
<xr:PasswordMode>false</xr:PasswordMode>
|
||||
<xr:DataHistory>Use</xr:DataHistory>
|
||||
<xr:MarkNegatives>false</xr:MarkNegatives>
|
||||
<xr:MinValue xsi:nil="true" />
|
||||
<xr:Synonym />
|
||||
<xr:Comment />
|
||||
<xr:FullTextSearch>Use</xr:FullTextSearch>
|
||||
<xr:ChoiceParameterLinks />
|
||||
<xr:FillValue xsi:nil="true" />
|
||||
<xr:Mask />
|
||||
<xr:ChoiceParameters />
|
||||
</xr:StandardAttribute>
|
||||
<xr:StandardAttribute name="Predefined">
|
||||
<xr:LinkByType />
|
||||
<xr:FillChecking>DontCheck</xr:FillChecking>
|
||||
<xr:MultiLine>false</xr:MultiLine>
|
||||
<xr:FillFromFillingValue>false</xr:FillFromFillingValue>
|
||||
<xr:CreateOnInput>Auto</xr:CreateOnInput>
|
||||
<xr:MaxValue xsi:nil="true" />
|
||||
<xr:ToolTip />
|
||||
<xr:ExtendedEdit>false</xr:ExtendedEdit>
|
||||
<xr:Format />
|
||||
<xr:ChoiceForm />
|
||||
<xr:QuickChoice>Auto</xr:QuickChoice>
|
||||
<xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput>
|
||||
<xr:EditFormat />
|
||||
<xr:PasswordMode>false</xr:PasswordMode>
|
||||
<xr:DataHistory>Use</xr:DataHistory>
|
||||
<xr:MarkNegatives>false</xr:MarkNegatives>
|
||||
<xr:MinValue xsi:nil="true" />
|
||||
<xr:Synonym />
|
||||
<xr:Comment />
|
||||
<xr:FullTextSearch>Use</xr:FullTextSearch>
|
||||
<xr:ChoiceParameterLinks />
|
||||
<xr:FillValue xsi:nil="true" />
|
||||
<xr:Mask />
|
||||
<xr:ChoiceParameters />
|
||||
</xr:StandardAttribute>
|
||||
<xr:StandardAttribute name="Ref">
|
||||
<xr:LinkByType />
|
||||
<xr:FillChecking>DontCheck</xr:FillChecking>
|
||||
<xr:MultiLine>false</xr:MultiLine>
|
||||
<xr:FillFromFillingValue>false</xr:FillFromFillingValue>
|
||||
<xr:CreateOnInput>Auto</xr:CreateOnInput>
|
||||
<xr:MaxValue xsi:nil="true" />
|
||||
<xr:ToolTip />
|
||||
<xr:ExtendedEdit>false</xr:ExtendedEdit>
|
||||
<xr:Format />
|
||||
<xr:ChoiceForm />
|
||||
<xr:QuickChoice>Auto</xr:QuickChoice>
|
||||
<xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput>
|
||||
<xr:EditFormat />
|
||||
<xr:PasswordMode>false</xr:PasswordMode>
|
||||
<xr:DataHistory>Use</xr:DataHistory>
|
||||
<xr:MarkNegatives>false</xr:MarkNegatives>
|
||||
<xr:MinValue xsi:nil="true" />
|
||||
<xr:Synonym />
|
||||
<xr:Comment />
|
||||
<xr:FullTextSearch>Use</xr:FullTextSearch>
|
||||
<xr:ChoiceParameterLinks />
|
||||
<xr:FillValue xsi:nil="true" />
|
||||
<xr:Mask />
|
||||
<xr:ChoiceParameters />
|
||||
</xr:StandardAttribute>
|
||||
<xr:StandardAttribute name="DeletionMark">
|
||||
<xr:LinkByType />
|
||||
<xr:FillChecking>DontCheck</xr:FillChecking>
|
||||
<xr:MultiLine>false</xr:MultiLine>
|
||||
<xr:FillFromFillingValue>false</xr:FillFromFillingValue>
|
||||
<xr:CreateOnInput>Auto</xr:CreateOnInput>
|
||||
<xr:MaxValue xsi:nil="true" />
|
||||
<xr:ToolTip />
|
||||
<xr:ExtendedEdit>false</xr:ExtendedEdit>
|
||||
<xr:Format />
|
||||
<xr:ChoiceForm />
|
||||
<xr:QuickChoice>Auto</xr:QuickChoice>
|
||||
<xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput>
|
||||
<xr:EditFormat />
|
||||
<xr:PasswordMode>false</xr:PasswordMode>
|
||||
<xr:DataHistory>Use</xr:DataHistory>
|
||||
<xr:MarkNegatives>false</xr:MarkNegatives>
|
||||
<xr:MinValue xsi:nil="true" />
|
||||
<xr:Synonym />
|
||||
<xr:Comment />
|
||||
<xr:FullTextSearch>Use</xr:FullTextSearch>
|
||||
<xr:ChoiceParameterLinks />
|
||||
<xr:FillValue xsi:nil="true" />
|
||||
<xr:Mask />
|
||||
<xr:ChoiceParameters />
|
||||
</xr:StandardAttribute>
|
||||
<xr:StandardAttribute name="IsFolder">
|
||||
<xr:LinkByType />
|
||||
<xr:FillChecking>DontCheck</xr:FillChecking>
|
||||
<xr:MultiLine>false</xr:MultiLine>
|
||||
<xr:FillFromFillingValue>false</xr:FillFromFillingValue>
|
||||
<xr:CreateOnInput>Auto</xr:CreateOnInput>
|
||||
<xr:MaxValue xsi:nil="true" />
|
||||
<xr:ToolTip />
|
||||
<xr:ExtendedEdit>false</xr:ExtendedEdit>
|
||||
<xr:Format />
|
||||
<xr:ChoiceForm />
|
||||
<xr:QuickChoice>Auto</xr:QuickChoice>
|
||||
<xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput>
|
||||
<xr:EditFormat />
|
||||
<xr:PasswordMode>false</xr:PasswordMode>
|
||||
<xr:DataHistory>Use</xr:DataHistory>
|
||||
<xr:MarkNegatives>false</xr:MarkNegatives>
|
||||
<xr:MinValue xsi:nil="true" />
|
||||
<xr:Synonym />
|
||||
<xr:Comment />
|
||||
<xr:FullTextSearch>Use</xr:FullTextSearch>
|
||||
<xr:ChoiceParameterLinks />
|
||||
<xr:FillValue xsi:nil="true" />
|
||||
<xr:Mask />
|
||||
<xr:ChoiceParameters />
|
||||
</xr:StandardAttribute>
|
||||
<xr:StandardAttribute name="Owner">
|
||||
<xr:LinkByType />
|
||||
<xr:FillChecking>DontCheck</xr:FillChecking>
|
||||
<xr:MultiLine>false</xr:MultiLine>
|
||||
<xr:FillFromFillingValue>false</xr:FillFromFillingValue>
|
||||
<xr:CreateOnInput>Auto</xr:CreateOnInput>
|
||||
<xr:MaxValue xsi:nil="true" />
|
||||
<xr:ToolTip />
|
||||
<xr:ExtendedEdit>false</xr:ExtendedEdit>
|
||||
<xr:Format />
|
||||
<xr:ChoiceForm />
|
||||
<xr:QuickChoice>Auto</xr:QuickChoice>
|
||||
<xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput>
|
||||
<xr:EditFormat />
|
||||
<xr:PasswordMode>false</xr:PasswordMode>
|
||||
<xr:DataHistory>Use</xr:DataHistory>
|
||||
<xr:MarkNegatives>false</xr:MarkNegatives>
|
||||
<xr:MinValue xsi:nil="true" />
|
||||
<xr:Synonym />
|
||||
<xr:Comment />
|
||||
<xr:FullTextSearch>Use</xr:FullTextSearch>
|
||||
<xr:ChoiceParameterLinks />
|
||||
<xr:FillValue xsi:nil="true" />
|
||||
<xr:Mask />
|
||||
<xr:ChoiceParameters />
|
||||
</xr:StandardAttribute>
|
||||
<xr:StandardAttribute name="Parent">
|
||||
<xr:LinkByType />
|
||||
<xr:FillChecking>DontCheck</xr:FillChecking>
|
||||
<xr:MultiLine>false</xr:MultiLine>
|
||||
<xr:FillFromFillingValue>false</xr:FillFromFillingValue>
|
||||
<xr:CreateOnInput>Auto</xr:CreateOnInput>
|
||||
<xr:MaxValue xsi:nil="true" />
|
||||
<xr:ToolTip />
|
||||
<xr:ExtendedEdit>false</xr:ExtendedEdit>
|
||||
<xr:Format />
|
||||
<xr:ChoiceForm />
|
||||
<xr:QuickChoice>Auto</xr:QuickChoice>
|
||||
<xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput>
|
||||
<xr:EditFormat />
|
||||
<xr:PasswordMode>false</xr:PasswordMode>
|
||||
<xr:DataHistory>Use</xr:DataHistory>
|
||||
<xr:MarkNegatives>false</xr:MarkNegatives>
|
||||
<xr:MinValue xsi:nil="true" />
|
||||
<xr:Synonym />
|
||||
<xr:Comment />
|
||||
<xr:FullTextSearch>Use</xr:FullTextSearch>
|
||||
<xr:ChoiceParameterLinks />
|
||||
<xr:FillValue xsi:nil="true" />
|
||||
<xr:Mask />
|
||||
<xr:ChoiceParameters />
|
||||
</xr:StandardAttribute>
|
||||
<xr:StandardAttribute name="Description">
|
||||
<xr:LinkByType />
|
||||
<xr:FillChecking>DontCheck</xr:FillChecking>
|
||||
<xr:MultiLine>false</xr:MultiLine>
|
||||
<xr:FillFromFillingValue>false</xr:FillFromFillingValue>
|
||||
<xr:CreateOnInput>Auto</xr:CreateOnInput>
|
||||
<xr:MaxValue xsi:nil="true" />
|
||||
<xr:ToolTip />
|
||||
<xr:ExtendedEdit>false</xr:ExtendedEdit>
|
||||
<xr:Format />
|
||||
<xr:ChoiceForm />
|
||||
<xr:QuickChoice>Auto</xr:QuickChoice>
|
||||
<xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput>
|
||||
<xr:EditFormat />
|
||||
<xr:PasswordMode>false</xr:PasswordMode>
|
||||
<xr:DataHistory>Use</xr:DataHistory>
|
||||
<xr:MarkNegatives>false</xr:MarkNegatives>
|
||||
<xr:MinValue xsi:nil="true" />
|
||||
<xr:Synonym />
|
||||
<xr:Comment />
|
||||
<xr:FullTextSearch>Use</xr:FullTextSearch>
|
||||
<xr:ChoiceParameterLinks />
|
||||
<xr:FillValue xsi:nil="true" />
|
||||
<xr:Mask />
|
||||
<xr:ChoiceParameters />
|
||||
</xr:StandardAttribute>
|
||||
<xr:StandardAttribute name="Code">
|
||||
<xr:LinkByType />
|
||||
<xr:FillChecking>DontCheck</xr:FillChecking>
|
||||
<xr:MultiLine>false</xr:MultiLine>
|
||||
<xr:FillFromFillingValue>false</xr:FillFromFillingValue>
|
||||
<xr:CreateOnInput>Auto</xr:CreateOnInput>
|
||||
<xr:MaxValue xsi:nil="true" />
|
||||
<xr:ToolTip />
|
||||
<xr:ExtendedEdit>false</xr:ExtendedEdit>
|
||||
<xr:Format />
|
||||
<xr:ChoiceForm />
|
||||
<xr:QuickChoice>Auto</xr:QuickChoice>
|
||||
<xr:ChoiceHistoryOnInput>Auto</xr:ChoiceHistoryOnInput>
|
||||
<xr:EditFormat />
|
||||
<xr:PasswordMode>false</xr:PasswordMode>
|
||||
<xr:DataHistory>Use</xr:DataHistory>
|
||||
<xr:MarkNegatives>false</xr:MarkNegatives>
|
||||
<xr:MinValue xsi:nil="true" />
|
||||
<xr:Synonym />
|
||||
<xr:Comment />
|
||||
<xr:FullTextSearch>Use</xr:FullTextSearch>
|
||||
<xr:ChoiceParameterLinks />
|
||||
<xr:FillValue xsi:nil="true" />
|
||||
<xr:Mask />
|
||||
<xr:ChoiceParameters />
|
||||
</xr:StandardAttribute>
|
||||
</StandardAttributes>
|
||||
<Characteristics />
|
||||
<PredefinedDataUpdate>Auto</PredefinedDataUpdate>
|
||||
<EditType>InDialog</EditType>
|
||||
<QuickChoice>false</QuickChoice>
|
||||
<ChoiceMode>BothWays</ChoiceMode>
|
||||
<InputByString>
|
||||
<xr:Field>Catalog.Контрагенты.StandardAttribute.Description</xr:Field>
|
||||
<xr:Field>Catalog.Контрагенты.StandardAttribute.Code</xr:Field>
|
||||
</InputByString>
|
||||
<SearchStringModeOnInputByString>Begin</SearchStringModeOnInputByString>
|
||||
<FullTextSearchOnInputByString>DontUse</FullTextSearchOnInputByString>
|
||||
<ChoiceDataGetModeOnInputByString>Directly</ChoiceDataGetModeOnInputByString>
|
||||
<DefaultObjectForm>Catalog.Контрагенты.Form.ФормаОбъекта</DefaultObjectForm>
|
||||
<DefaultFolderForm />
|
||||
<DefaultListForm>Catalog.Контрагенты.Form.ФормаСписка</DefaultListForm>
|
||||
<DefaultChoiceForm />
|
||||
<DefaultFolderChoiceForm />
|
||||
<AuxiliaryObjectForm />
|
||||
<AuxiliaryFolderForm />
|
||||
<AuxiliaryListForm />
|
||||
<AuxiliaryChoiceForm />
|
||||
<AuxiliaryFolderChoiceForm />
|
||||
<IncludeHelpInContents>false</IncludeHelpInContents>
|
||||
<BasedOn />
|
||||
<DataLockFields />
|
||||
<DataLockControlMode>Automatic</DataLockControlMode>
|
||||
<FullTextSearch>Use</FullTextSearch>
|
||||
<ObjectPresentation />
|
||||
<ExtendedObjectPresentation />
|
||||
<ListPresentation />
|
||||
<ExtendedListPresentation />
|
||||
<Explanation />
|
||||
<CreateOnInput>DontUse</CreateOnInput>
|
||||
<ChoiceHistoryOnInput>Auto</ChoiceHistoryOnInput>
|
||||
<DataHistory>DontUse</DataHistory>
|
||||
<UpdateDataHistoryImmediatelyAfterWrite>false</UpdateDataHistoryImmediatelyAfterWrite>
|
||||
<ExecuteAfterWriteDataHistoryVersionProcessing>false</ExecuteAfterWriteDataHistoryVersionProcessing>
|
||||
</Properties>
|
||||
<ChildObjects>
|
||||
<Form>ФормаСписка</Form>
|
||||
<Form>ФормаОбъекта</Form>
|
||||
</ChildObjects>
|
||||
</Catalog>
|
||||
</MetaDataObject>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user