From 1e94b9236fad65fade113d1b983e1b1859dd772e Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Tue, 22 Sep 2026 16:45:50 +0300 Subject: [PATCH] =?UTF-8?q?fix(template-add):=20HTML-=D0=BC=D0=B0=D0=BA?= =?UTF-8?q?=D0=B5=D1=82=20=D0=B2=20=D0=BF=D0=BB=D0=B0=D1=82=D1=84=D0=BE?= =?UTF-8?q?=D1=80=D0=BC=D0=B5=D0=BD=D0=BD=D0=BE=D0=B9=20=D1=80=D0=B0=D1=81?= =?UTF-8?q?=D0=BA=D0=BB=D0=B0=D0=B4=D0=BA=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Навык создавал Templates/<Макет>/Ext/Template.html. Платформа такой файл молча игнорирует: загрузка проходит без ошибок и предупреждений, а макет в базе пустой. HTML-макет платформа хранит парой, как справку: дескриптор Ext/Template.xml со списком страниц и сама страница Ext/Template/<язык>.html (картинки — в _files/). Раскладка снята с выгрузки acc_8.3.27: 136 HTML-макетов из 136, дескриптор во всех байт в байт одинаков. Шапка страницы — в виде редактора платформы (одной строкой, парный ), чтобы первое сохранение в Конфигураторе не давало диффа. Язык страницы задаётся параметром -Lang (дефолт ru) — как в help-add. Вывод навыка теперь различает содержимое и дескриптор: «Содержимое» указывает на страницу, иначе правка ушла бы в дескриптор. Проверено на 8.3.27.1859: LoadConfigFromFiles + UpdateDBCfg + обратная выгрузка — текст макета доходит до базы и возвращается байт в байт, дескриптор тоже. Контроль — тот же макет в старой раскладке: в выгрузке из базы тела нет вовсе. EPF: epf-build → epf-dump — раскладка возвращается с содержимым. Диагноз и раскладка — из PR #98. Co-Authored-By: Roman Syuzyov Co-Authored-By: Claude Opus 5 (1M context) --- .claude/skills/template-add/SKILL.md | 8 ++- .../template-add/scripts/add-template.ps1 | 51 ++++++++++++----- .../template-add/scripts/add-template.py | 55 ++++++++++++++----- .../cases/template-add/html-template.json | 22 +++++++- .../Templates/МакетHTML/Ext/Template.html | 9 --- .../Templates/МакетHTML/Ext/Template.xml | 4 ++ .../Templates/МакетHTML/Ext/Template/ru.html | 2 + 7 files changed, 108 insertions(+), 43 deletions(-) delete mode 100644 tests/skills/cases/template-add/snapshots/html-template/МояОбработка/Templates/МакетHTML/Ext/Template.html create mode 100644 tests/skills/cases/template-add/snapshots/html-template/МояОбработка/Templates/МакетHTML/Ext/Template.xml create mode 100644 tests/skills/cases/template-add/snapshots/html-template/МояОбработка/Templates/МакетHTML/Ext/Template/ru.html diff --git a/.claude/skills/template-add/SKILL.md b/.claude/skills/template-add/SKILL.md index a45179d62..7e057517a 100644 --- a/.claude/skills/template-add/SKILL.md +++ b/.claude/skills/template-add/SKILL.md @@ -27,13 +27,14 @@ allowed-tools: | TemplateName | да | — | Имя макета | | TemplateType | да | — | Тип: HTML, Text, SpreadsheetDocument, BinaryData, DataCompositionSchema | | Synonym | нет | = TemplateName | Синоним макета | +| Lang | нет | `ru` | Код языка страницы — только для типа HTML | | SrcDir | нет | `src` | Путь к папке типа объектов (`Reports`, `DataProcessors`, `Catalogs`, `Documents`...), внутри которой лежит `.xml`. Дефолт `src` подходит для каталогов с внешними обработками/отчётами, лежащими рядом | | -SetMainSKD | нет | — | Принудительно установить MainDataCompositionSchema | ## Команда ```powershell -powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/add-template.ps1" -ObjectName "" -TemplateName "" -TemplateType "" [-Synonym ""] [-SrcDir ""] [-SetMainSKD] +powershell.exe -NoProfile -File "${CLAUDE_SKILL_DIR}/scripts/add-template.ps1" -ObjectName "" -TemplateName "" -TemplateType "" [-Synonym ""] [-Lang ""] [-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/.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" - ├── .xml # Метаданные макета (1 UUID) └── / └── Ext/ - └── Template. # Содержимое макета + ├── Template. # Содержимое макета + └── Template/.html # HTML: содержимое (Template.xml — дескриптор) ``` ## Что модифицируется diff --git a/.claude/skills/template-add/scripts/add-template.ps1 b/.claude/skills/template-add/scripts/add-template.ps1 index 6cb1e3305..5a9f3de6b 100644 --- a/.claude/skills/template-add/scripts/add-template.ps1 +++ b/.claude/skills/template-add/scripts/add-template.ps1 @@ -1,4 +1,4 @@ -# template-add v1.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//Ext/Template.) --- $templateFilePath = Join-Path $templateExtDir "Template$($tmpl.Ext)" +# Куда класть текст макета. Совпадает с $templateFilePath у всех типов, кроме HTML: +# там содержимое живёт в отдельной странице, а Template.xml — только дескриптор. +$templateBodyPath = $templateFilePath switch ($TemplateType) { "HTML" { - $content = @" - - - - - - - - - + # HTML-макет платформа хранит парой, как справку: дескриптор Ext/Template.xml + # со списком страниц и сама страница Ext/Template/<язык>.html (картинки — + # рядом в _files/). Одиночный Ext/Template.html платформа молча игнорирует: + # загрузка проходит без ошибок, а макет в базе пустой. + $pageXml = @" + + + $Lang + "@ - [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" + + # Шапка — в том же виде, в каком её пишет редактор платформы (одной строкой, + # парный ): первое сохранение в Конфигураторе даст минимальный дифф. + $content = @" + + +"@ + # Страница — с 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: 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)" } diff --git a/.claude/skills/template-add/scripts/add-template.py b/.claude/skills/template-add/scripts/add-template.py index e88422afb..bcc3c56b6 100644 --- a/.claude/skills/template-add/scripts/add-template.py +++ b/.claude/skills/template-add/scripts/add-template.py @@ -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//Ext/Template.) --- 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 = ( - '\n' - '\n' - '\n' - '\t\n' - '\t\n' - '\n' - '\n' - '\n' - '' + # HTML-макет платформа хранит парой, как справку: дескриптор Ext/Template.xml + # со списком страниц и сама страница Ext/Template/<язык>.html (картинки — + # рядом в _files/). Одиночный Ext/Template.html платформа молча игнорирует: + # загрузка проходит без ошибок, а макет в базе пустой. + page_xml = ( + '\n' + '\n' + f'\t{lang}\n' + '' ) - 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") + + # Шапка — в том же виде, в каком её пишет редактор платформы (одной строкой, + # парный ): первое сохранение в Конфигураторе даст минимальный дифф. + # Страница — с LF: платформа хранит HTML именно так. + content = ( + '' + '' + '' + '\n' + '' + ) + 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: 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}") diff --git a/tests/skills/cases/template-add/html-template.json b/tests/skills/cases/template-add/html-template.json index d5feed64e..7a5e7a736 100644 --- a/tests/skills/cases/template-add/html-template.json +++ b/tests/skills/cases/template-add/html-template.json @@ -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 + } + ] + } } diff --git a/tests/skills/cases/template-add/snapshots/html-template/МояОбработка/Templates/МакетHTML/Ext/Template.html b/tests/skills/cases/template-add/snapshots/html-template/МояОбработка/Templates/МакетHTML/Ext/Template.html deleted file mode 100644 index cb08d6161..000000000 --- a/tests/skills/cases/template-add/snapshots/html-template/МояОбработка/Templates/МакетHTML/Ext/Template.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/tests/skills/cases/template-add/snapshots/html-template/МояОбработка/Templates/МакетHTML/Ext/Template.xml b/tests/skills/cases/template-add/snapshots/html-template/МояОбработка/Templates/МакетHTML/Ext/Template.xml new file mode 100644 index 000000000..b9fbd0bc7 --- /dev/null +++ b/tests/skills/cases/template-add/snapshots/html-template/МояОбработка/Templates/МакетHTML/Ext/Template.xml @@ -0,0 +1,4 @@ + + + ru + \ No newline at end of file diff --git a/tests/skills/cases/template-add/snapshots/html-template/МояОбработка/Templates/МакетHTML/Ext/Template/ru.html b/tests/skills/cases/template-add/snapshots/html-template/МояОбработка/Templates/МакетHTML/Ext/Template/ru.html new file mode 100644 index 000000000..9433caa59 --- /dev/null +++ b/tests/skills/cases/template-add/snapshots/html-template/МояОбработка/Templates/МакетHTML/Ext/Template/ru.html @@ -0,0 +1,2 @@ + + \ No newline at end of file