From d05c91be03d3a3f7368d3d4d45435482feef1e27 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Wed, 5 Aug 2026 18:53:50 +0300 Subject: [PATCH] =?UTF-8?q?fix(epf-init,erf-init,form-add):=20CRLF=20?= =?UTF-8?q?=D0=B2=20=D1=80=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B8=D1=82=D0=B5?= =?UTF-8?q?=D0=BB=D1=8F=D1=85=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=20=D0=BC?= =?UTF-8?q?=D0=BE=D0=B4=D1=83=D0=BB=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Скелетные генераторы писали Module.bsl с LF, а платформа пишет модули с CRLF: в выгрузке БП 2643 CRLF и чисто-LF 0 из 3001 модуля (358 «смешанных» — LF внутри строковых литералов кода), BOM 2001/2001. По тому же доводу сходимости, что и для XML: платформа перепишет модуль в CRLF при первой выгрузке, значит наш LF — дифф, созданный нами. В репозитории уже была встречная конвенция: meta-compile (модуль команды) и cfe-patch-method (base/local/remote.bsl) пишут .bsl явным CRLF в обоих портах. Выбивались только эти три скелета. Хвостовой перевод строки НЕ трогаем: у платформы он неканоничен — 1235 модулей с ним, 766 без; это след автора кода, а не правило. Меняем только разделители. Правка в точке записи, а не в шаблоне: так одна строка на скрипт и не трогаются \u-экранированные кириллические литералы в py (Edit по ним переэкранирует). Снэпшоты нормализуют EOL и увидеть это не могут — добавлен preserves на модуль в epf-init/basic, erf-init/basic, form-add/basic. Windows 641/641 обоими портами, мак 590/0/51, дрейфа снэпшотов нет. Co-Authored-By: Claude Opus 5 --- .claude/skills/epf-init/scripts/init.ps1 | 7 ++++- .claude/skills/epf-init/scripts/init.py | 7 +++-- .claude/skills/erf-init/scripts/init.ps1 | 7 ++++- .claude/skills/erf-init/scripts/init.py | 7 +++-- .claude/skills/form-add/scripts/form-add.ps1 | 7 ++++- .claude/skills/form-add/scripts/form-add.py | 7 +++-- tests/skills/cases/epf-init/basic.json | 27 ++++++++++++-------- tests/skills/cases/erf-init/basic.json | 27 ++++++++++++-------- tests/skills/cases/form-add/basic.json | 27 ++++++++++++-------- 9 files changed, 84 insertions(+), 39 deletions(-) diff --git a/.claude/skills/epf-init/scripts/init.ps1 b/.claude/skills/epf-init/scripts/init.ps1 index d7c5f926..7ad5480d 100644 --- a/.claude/skills/epf-init/scripts/init.ps1 +++ b/.claude/skills/epf-init/scripts/init.ps1 @@ -1,4 +1,4 @@ -# epf-init v1.2 — Init 1C external data processor scaffold +# epf-init v1.3 — Init 1C external data processor scaffold # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -92,6 +92,11 @@ $moduleBsl = @" "@ $modulePath = Join-Path $extDir "ObjectModule.bsl" +# Модуль пишем в каноне платформы: CRLF в разделителях строк (корпус: 2643 CRLF, +# чисто-LF 0 из 3001). Хвостовой перевод НЕ навязываем — у платформы он +# неканоничен (1235 модулей с ним, 766 без). Шаблон берёт переводы строк из +# самого скрипта, а он в репозитории хранится с LF. +$moduleBsl = ($moduleBsl -replace "`r`n", "`n") -replace "`n", "`r`n" [System.IO.File]::WriteAllText($modulePath, $moduleBsl, $enc) Write-Host "[OK] Создана обработка: $rootFile" diff --git a/.claude/skills/epf-init/scripts/init.py b/.claude/skills/epf-init/scripts/init.py index 5f6ba8c7..971a4514 100644 --- a/.claude/skills/epf-init/scripts/init.py +++ b/.claude/skills/epf-init/scripts/init.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# epf-init v1.2 — Init 1C external data processor scaffold +# epf-init v1.3 — 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 @@ -96,7 +96,10 @@ def main(): #КонецОбласти""" module_path = os.path.join(ext_dir, "ObjectModule.bsl") - write_utf8_bom(module_path, module_bsl) + # Модуль пишем в каноне платформы: CRLF в разделителях строк (корпус: 2643 CRLF, + # чисто-LF 0 из 3001). Хвостовой перевод НЕ навязываем — у платформы он + # неканоничен (1235 модулей с ним, 766 без). + write_utf8_bom(module_path, module_bsl.replace('\r\n', '\n').replace('\n', '\r\n')) print(f"[OK] Создана обработка: {root_file}") print(f" Каталог: {processor_dir}") diff --git a/.claude/skills/erf-init/scripts/init.ps1 b/.claude/skills/erf-init/scripts/init.ps1 index ed03e930..eb40eff4 100644 --- a/.claude/skills/erf-init/scripts/init.ps1 +++ b/.claude/skills/erf-init/scripts/init.ps1 @@ -1,4 +1,4 @@ -# erf-init v1.2 — Init 1C external report scaffold +# erf-init v1.3 — Init 1C external report scaffold # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -126,6 +126,11 @@ $moduleBsl = @" "@ $modulePath = Join-Path $extDir "ObjectModule.bsl" +# Модуль пишем в каноне платформы: CRLF в разделителях строк (корпус: 2643 CRLF, +# чисто-LF 0 из 3001). Хвостовой перевод НЕ навязываем — у платформы он +# неканоничен (1235 модулей с ним, 766 без). Шаблон берёт переводы строк из +# самого скрипта, а он в репозитории хранится с LF. +$moduleBsl = ($moduleBsl -replace "`r`n", "`n") -replace "`n", "`r`n" [System.IO.File]::WriteAllText($modulePath, $moduleBsl, $enc) Write-Host "[OK] Создан отчёт: $rootFile" diff --git a/.claude/skills/erf-init/scripts/init.py b/.claude/skills/erf-init/scripts/init.py index 315b8b44..81c3616c 100644 --- a/.claude/skills/erf-init/scripts/init.py +++ b/.claude/skills/erf-init/scripts/init.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# erf-init v1.2 — Init 1C external report scaffold +# erf-init v1.3 — 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 @@ -114,7 +114,10 @@ def main(): #КонецОбласти""" module_path = os.path.join(ext_dir, "ObjectModule.bsl") - write_utf8_bom(module_path, module_bsl) + # Модуль пишем в каноне платформы: CRLF в разделителях строк (корпус: 2643 CRLF, + # чисто-LF 0 из 3001). Хвостовой перевод НЕ навязываем — у платформы он + # неканоничен (1235 модулей с ним, 766 без). + write_utf8_bom(module_path, module_bsl.replace('\r\n', '\n').replace('\n', '\r\n')) print(f"[OK] Создан отчёт: {root_file}") print(f" Каталог: {report_dir}") diff --git a/.claude/skills/form-add/scripts/form-add.ps1 b/.claude/skills/form-add/scripts/form-add.ps1 index e78d460c..b0a5e9a2 100644 --- a/.claude/skills/form-add/scripts/form-add.ps1 +++ b/.claude/skills/form-add/scripts/form-add.ps1 @@ -1,4 +1,4 @@ -# form-add v1.16 — Add managed form to 1C config object +# form-add v1.17 — Add managed form to 1C config object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -485,6 +485,11 @@ $moduleBsl = @" if (Test-Path $modulePath) { Write-Host "[SKIP] Module.bsl already exists: $modulePath — not overwriting" } else { + # Модуль пишем в каноне платформы: CRLF в разделителях строк (корпус: 2643 CRLF, + # чисто-LF 0 из 3001). Хвостовой перевод НЕ навязываем — у платформы он + # неканоничен (1235 модулей с ним, 766 без). Шаблон берёт переводы строк из + # самого скрипта, а он в репозитории хранится с LF. + $moduleBsl = ($moduleBsl -replace "`r`n", "`n") -replace "`n", "`r`n" [System.IO.File]::WriteAllText($modulePath, $moduleBsl, $encBom) } diff --git a/.claude/skills/form-add/scripts/form-add.py b/.claude/skills/form-add/scripts/form-add.py index 2656d275..a0d38e1b 100644 --- a/.claude/skills/form-add/scripts/form-add.py +++ b/.claude/skills/form-add/scripts/form-add.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-add v1.16 — Add managed form to 1C config object +# form-add v1.17 — Add managed form to 1C config object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -594,7 +594,10 @@ def main(): if os.path.exists(module_path): print(f"[SKIP] Module.bsl already exists: {module_path} — not overwriting") else: - write_text_with_bom(module_path, module_bsl) + # Модуль пишем в каноне платформы: CRLF в разделителях строк (корпус: 2643 CRLF, + # чисто-LF 0 из 3001). Хвостовой перевод НЕ навязываем — у платформы он + # неканоничен (1235 модулей с ним, 766 без). + write_text_with_bom(module_path, module_bsl.replace('\r\n', '\n').replace('\n', '\r\n')) # --- Phase 4: Register in parent object --- diff --git a/tests/skills/cases/epf-init/basic.json b/tests/skills/cases/epf-init/basic.json index 2cbf64aa..6feb6239 100644 --- a/tests/skills/cases/epf-init/basic.json +++ b/tests/skills/cases/epf-init/basic.json @@ -8,15 +8,22 @@ "files": [ "ТестоваяОбработка.xml" ], - "preserves": { - "file": "ТестоваяОбработка.xml", - "bom": true, - "eol": "crlf", - "encoding": "UTF-8", - "finalNewline": false, - "noCR13": true, - "selfClose": "tight", - "noEmptyPairs": true - } + "preserves": [ + { + "file": "ТестоваяОбработка.xml", + "bom": true, + "eol": "crlf", + "encoding": "UTF-8", + "finalNewline": false, + "noCR13": true, + "selfClose": "tight", + "noEmptyPairs": true + }, + { + "file": "ТестоваяОбработка/Ext/ObjectModule.bsl", + "bom": true, + "eol": "crlf" + } + ] } } diff --git a/tests/skills/cases/erf-init/basic.json b/tests/skills/cases/erf-init/basic.json index 41fc86a4..7e65d426 100644 --- a/tests/skills/cases/erf-init/basic.json +++ b/tests/skills/cases/erf-init/basic.json @@ -8,15 +8,22 @@ "files": [ "ТестовыйОтчёт.xml" ], - "preserves": { - "file": "ТестовыйОтчёт.xml", - "bom": true, - "eol": "crlf", - "encoding": "UTF-8", - "finalNewline": false, - "noCR13": true, - "selfClose": "tight", - "noEmptyPairs": true - } + "preserves": [ + { + "file": "ТестовыйОтчёт.xml", + "bom": true, + "eol": "crlf", + "encoding": "UTF-8", + "finalNewline": false, + "noCR13": true, + "selfClose": "tight", + "noEmptyPairs": true + }, + { + "file": "ТестовыйОтчёт/Ext/ObjectModule.bsl", + "bom": true, + "eol": "crlf" + } + ] } } diff --git a/tests/skills/cases/form-add/basic.json b/tests/skills/cases/form-add/basic.json index ca4d9bda..d9f4f18d 100644 --- a/tests/skills/cases/form-add/basic.json +++ b/tests/skills/cases/form-add/basic.json @@ -19,15 +19,22 @@ }, "validatePath": "Catalogs/Товары/Forms/ФормаЭлемента", "expect": { - "preserves": { - "file": "Catalogs/Товары/Forms/ФормаЭлемента/Ext/Form.xml", - "bom": true, - "eol": "crlf", - "encoding": "UTF-8", - "finalNewline": false, - "noCR13": true, - "selfClose": "tight", - "noEmptyPairs": true - } + "preserves": [ + { + "file": "Catalogs/Товары/Forms/ФормаЭлемента/Ext/Form.xml", + "bom": true, + "eol": "crlf", + "encoding": "UTF-8", + "finalNewline": false, + "noCR13": true, + "selfClose": "tight", + "noEmptyPairs": true + }, + { + "file": "Catalogs/Товары/Forms/ФормаЭлемента/Ext/Form/Module.bsl", + "bom": true, + "eol": "crlf" + } + ] } }