fix(template-add): HTML-макет в платформенной раскладке

Навык создавал Templates/<Макет>/Ext/Template.html. Платформа такой файл молча
игнорирует: загрузка проходит без ошибок и предупреждений, а макет в базе пустой.

HTML-макет платформа хранит парой, как справку: дескриптор Ext/Template.xml со
списком страниц и сама страница Ext/Template/<язык>.html (картинки — в _files/).
Раскладка снята с выгрузки acc_8.3.27: 136 HTML-макетов из 136, дескриптор во всех
байт в байт одинаков. Шапка страницы — в виде редактора платформы (одной строкой,
парный </meta>), чтобы первое сохранение в Конфигураторе не давало диффа.

Язык страницы задаётся параметром -Lang (дефолт ru) — как в help-add.
Вывод навыка теперь различает содержимое и дескриптор: «Содержимое» указывает на
страницу, иначе правка ушла бы в дескриптор.

Проверено на 8.3.27.1859: LoadConfigFromFiles + UpdateDBCfg + обратная выгрузка —
текст макета доходит до базы и возвращается байт в байт, дескриптор тоже.
Контроль — тот же макет в старой раскладке: в выгрузке из базы тела нет вовсе.
EPF: epf-build → epf-dump — раскладка возвращается с содержимым.

Диагноз и раскладка — из PR #98.

Co-Authored-By: Roman Syuzyov <rsyuzyov@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-09-22 16:45:50 +03:00
co-authored by Roman Syuzyov Claude Opus 5
parent 6eaf3211cc
commit 1e94b9236f
7 changed files with 108 additions and 43 deletions
+5 -3
View File
@@ -27,13 +27,14 @@ allowed-tools:
| TemplateName | да | — | Имя макета |
| TemplateType | да | — | Тип: HTML, Text, SpreadsheetDocument, BinaryData, DataCompositionSchema |
| Synonym | нет | = TemplateName | Синоним макета |
| Lang | нет | `ru` | Код языка страницы — только для типа HTML |
| SrcDir | нет | `src` | Путь к папке типа объектов (`Reports`, `DataProcessors`, `Catalogs`, `Documents`...), внутри которой лежит `<ObjectName>.xml`. Дефолт `src` подходит для каталогов с внешними обработками/отчётами, лежащими рядом |
| -SetMainSKD | нет | — | Принудительно установить MainDataCompositionSchema |
## Команда
```powershell
powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/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>"] [-Lang "<Lang>"] [-SrcDir "<SrcDir>"] [-SetMainSKD]
```
## Пример
@@ -50,7 +51,7 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/add-template.ps1" -
| Пользователь пишет | TemplateType | Расширение | Содержимое |
|---------------------------------------------|---------------------|------------|-------------------------|
| HTML | HTMLDocument | `.html` | Пустой HTML-документ |
| HTML | HTMLDocument | `Template/<lang>.html` | Пустой HTML-документ |
| Text, текстовый документ, текст | TextDocument | `.txt` | Пустой файл |
| SpreadsheetDocument, табличный документ, MXL | SpreadsheetDocument | `.xml` | Минимальный spreadsheet |
| BinaryData, двоичные данные | BinaryData | `.bin` | Пустой файл |
@@ -80,7 +81,8 @@ powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/add-template.ps1" -
├── <TemplateName>.xml # Метаданные макета (1 UUID)
└── <TemplateName>/
└── Ext/
── Template.<ext> # Содержимое макета
── Template.<ext> # Содержимое макета
└── Template/<lang>.html # HTML: содержимое (Template.xml — дескриптор)
```
## Что модифицируется
@@ -1,4 +1,4 @@
# template-add v1.23 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи)
# template-add v1.24 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -14,6 +14,8 @@ param(
[string]$Synonym = $TemplateName,
[string]$Lang = "ru",
[string]$SrcDir = "src",
[switch]$SetMainSKD
@@ -157,7 +159,7 @@ function Assert-EditAllowed([string]$targetPath, [string]$require) {
# --- Маппинг типов ---
$typeMap = @{
"HTML" = @{ TemplateType = "HTMLDocument"; Ext = ".html" }
"HTML" = @{ TemplateType = "HTMLDocument"; Ext = ".xml" }
"Text" = @{ TemplateType = "TextDocument"; Ext = ".txt" }
"SpreadsheetDocument" = @{ TemplateType = "SpreadsheetDocument"; Ext = ".xml" }
"BinaryData" = @{ TemplateType = "BinaryData"; Ext = ".bin" }
@@ -297,7 +299,7 @@ $templateMetaXml = @"
# Копия этой функции есть в каждом навыке-эмиттере (навыки автономны). Держать
# копии одинаковыми — сознательно: разошедшиеся копии сводят на нет весь смысл.
#
# HTML-макет сюда НЕ идёт — платформа хранит его с LF.
# HTML-страница макета сюда НЕ идёт — платформа хранит её с LF.
function Write-XmlFile([string]$path, [string]$text, $encoding) {
$t = ($text -replace "`r`n", "`n") -replace "`n", "`r`n"
[System.IO.File]::WriteAllText($path, $t.TrimEnd("`r", "`n"), $encoding)
@@ -308,21 +310,37 @@ Write-XmlFile $templateMetaPath $templateMetaXml $encBom
# --- 2. Содержимое макета (Templates/<TemplateName>/Ext/Template.<ext>) ---
$templateFilePath = Join-Path $templateExtDir "Template$($tmpl.Ext)"
# Куда класть текст макета. Совпадает с $templateFilePath у всех типов, кроме HTML:
# там содержимое живёт в отдельной странице, а Template.xml — только дескриптор.
$templateBodyPath = $templateFilePath
switch ($TemplateType) {
"HTML" {
$content = @"
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
</body>
</html>
# HTML-макет платформа хранит парой, как справку: дескриптор Ext/Template.xml
# со списком страниц и сама страница Ext/Template/<язык>.html (картинки —
# рядом в _files/). Одиночный Ext/Template.html платформа молча игнорирует:
# загрузка проходит без ошибок, а макет в базе пустой.
$pageXml = @"
<?xml version="1.0" encoding="UTF-8"?>
<Help xmlns="http://v8.1c.ru/8.3/xcf/extrnprops" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="$formatVersion">
<Page>$Lang</Page>
</Help>
"@
[System.IO.File]::WriteAllText($templateFilePath, $content, $encBom)
Write-XmlFile $templateFilePath $pageXml $encBom
$pageDir = Join-Path $templateExtDir "Template"
New-Item -ItemType Directory -Path $pageDir -Force | Out-Null
$templateBodyPath = Join-Path $pageDir "$Lang.html"
# Шапка — в том же виде, в каком её пишет редактор платформы (одной строкой,
# парный </meta>): первое сохранение в Конфигураторе даст минимальный дифф.
$content = @"
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta></head><body>
</body></html>
"@
# Страница — с LF: платформа хранит HTML именно так.
$content = ($content -replace "`r`n", "`n")
[System.IO.File]::WriteAllText($templateBodyPath, $content, $encBom)
}
"Text" {
[System.IO.File]::WriteAllText($templateFilePath, "", $encBom)
@@ -463,7 +481,10 @@ if ($alreadyRegistered) {
Write-Host " Already registered: <Template>$TemplateName</Template> in ChildObjects (skipped duplicate)"
}
Write-Host " Метаданные: $templateMetaPath"
Write-Host " Содержимое: $templateFilePath"
Write-Host " Содержимое: $templateBodyPath"
if ($TemplateType -eq "HTML") {
Write-Host " Дескриптор: $templateFilePath"
}
if ($mainDCSUpdated) {
Write-Host " MainDataCompositionSchema: $($mainDCS.InnerText)"
}
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# template-add v1.23 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи)
# template-add v1.24 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -212,7 +212,7 @@ def assert_edit_allowed(target_path, require):
return
TYPE_MAP = {
"HTML": {"TemplateType": "HTMLDocument", "Ext": ".html"},
"HTML": {"TemplateType": "HTMLDocument", "Ext": ".xml"},
"Text": {"TemplateType": "TextDocument", "Ext": ".txt"},
"SpreadsheetDocument": {"TemplateType": "SpreadsheetDocument", "Ext": ".xml"},
"BinaryData": {"TemplateType": "BinaryData", "Ext": ".bin"},
@@ -282,7 +282,7 @@ def write_xml_file(path, content):
Копия этой функции есть в каждом навыке-эмиттере (навыки автономны). Держать
копии одинаковыми — сознательно: разошедшиеся копии сводят на нет весь смысл.
HTML-макет сюда НЕ идёт — платформа хранит его с LF.
HTML-страница макета сюда НЕ идёт — платформа хранит её с LF.
"""
text = content.replace('\r\n', '\n').replace('\n', '\r\n').rstrip('\r\n')
write_utf8_bom(path, text)
@@ -329,6 +329,7 @@ def main():
parser.add_argument("-TemplateType", required=True,
choices=["HTML", "Text", "SpreadsheetDocument", "BinaryData", "DataCompositionSchema"])
parser.add_argument("-Synonym", default=None)
parser.add_argument("-Lang", default="ru")
parser.add_argument("-SrcDir", default="src")
parser.add_argument("-SetMainSKD", action="store_true")
args = ci_parse_args(parser)
@@ -337,6 +338,7 @@ def main():
template_name = args.TemplateName
template_type = args.TemplateType
synonym = args.Synonym if args.Synonym is not None else template_name
lang = args.Lang
src_dir = args.SrcDir
set_main_skd = args.SetMainSKD
@@ -457,20 +459,41 @@ def main():
# --- 2. Template content (Templates/<TemplateName>/Ext/Template.<ext>) ---
template_file_path = os.path.join(template_ext_dir, f"Template{tmpl['Ext']}")
# Куда класть текст макета. Совпадает с template_file_path у всех типов, кроме HTML:
# там содержимое живёт в отдельной странице, а Template.xml — только дескриптор.
template_body_path = template_file_path
if template_type == "HTML":
content = (
'<!DOCTYPE html>\n'
'<html>\n'
'<head>\n'
'\t<meta charset="UTF-8">\n'
'\t<title></title>\n'
'</head>\n'
'<body>\n'
'</body>\n'
'</html>'
# HTML-макет платформа хранит парой, как справку: дескриптор Ext/Template.xml
# со списком страниц и сама страница Ext/Template/<язык>.html (картинки —
# рядом в _files/). Одиночный Ext/Template.html платформа молча игнорирует:
# загрузка проходит без ошибок, а макет в базе пустой.
page_xml = (
'<?xml version="1.0" encoding="UTF-8"?>\n'
'<Help xmlns="http://v8.1c.ru/8.3/xcf/extrnprops"'
' xmlns:xs="http://www.w3.org/2001/XMLSchema"'
' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
f' version="{format_version}">\n'
f'\t<Page>{lang}</Page>\n'
'</Help>'
)
write_utf8_bom(template_file_path, content)
write_xml_file(template_file_path, page_xml)
page_dir = os.path.join(template_ext_dir, "Template")
os.makedirs(page_dir, exist_ok=True)
template_body_path = os.path.join(page_dir, f"{lang}.html")
# Шапка — в том же виде, в каком её пишет редактор платформы (одной строкой,
# парный </meta>): первое сохранение в Конфигураторе даст минимальный дифф.
# Страница — с LF: платформа хранит HTML именно так.
content = (
'<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">'
'<html><head>'
'<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>'
'</head><body>\n'
'</body></html>'
)
write_utf8_bom(template_body_path, content)
elif template_type == "Text":
write_utf8_bom(template_file_path, "")
@@ -584,7 +607,9 @@ def main():
if already_registered:
print(f" Already registered: <Template>{template_name}</Template> in ChildObjects (skipped duplicate)")
print(f" Метаданные: {template_meta_path}")
print(f" Содержимое: {template_file_path}")
print(f" Содержимое: {template_body_path}")
if template_type == "HTML":
print(f" Дескриптор: {template_file_path}")
if main_dcs_updated:
print(f" MainDataCompositionSchema: {main_dcs.text}")
@@ -6,5 +6,25 @@
"args": { "-Name": "МояОбработка", "-SrcDir": "{workDir}" }
}
],
"params": { "objectName": "МояОбработка", "templateName": "МакетHTML", "templateType": "HTML" }
"params": { "objectName": "МояОбработка", "templateName": "МакетHTML", "templateType": "HTML" },
"expect": {
"stdoutContains": ["Содержимое:", "ru.html", "Дескриптор:"],
"preserves": [
{
"file": "МояОбработка/Templates/МакетHTML/Ext/Template.xml",
"bom": true,
"eol": "crlf",
"encoding": "UTF-8",
"finalNewline": false,
"noCR13": true,
"selfClose": "tight"
},
{
"file": "МояОбработка/Templates/МакетHTML/Ext/Template/ru.html",
"bom": true,
"eol": "lf",
"finalNewline": false
}
]
}
}
@@ -1,9 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
</body>
</html>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<Help xmlns="http://v8.1c.ru/8.3/xcf/extrnprops" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
<Page>ru</Page>
</Help>
@@ -0,0 +1,2 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta></head><body>
</body></html>