diff --git a/.claude/skills/cf-init/scripts/cf-init.ps1 b/.claude/skills/cf-init/scripts/cf-init.ps1 index 8fd50976..e09e0790 100644 --- a/.claude/skills/cf-init/scripts/cf-init.ps1 +++ b/.claude/skills/cf-init/scripts/cf-init.ps1 @@ -1,4 +1,4 @@ -# cf-init v1.9 — Create empty 1C configuration scaffold (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# cf-init v1.10 — Create empty 1C configuration scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/cf-init/scripts/cf-init.py b/.claude/skills/cf-init/scripts/cf-init.py index 616fec34..fae61faf 100644 --- a/.claude/skills/cf-init/scripts/cf-init.py +++ b/.claude/skills/cf-init/scripts/cf-init.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# cf-init v1.9 — Create empty 1C configuration scaffold (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# cf-init v1.10 — Create empty 1C configuration scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Generates minimal XML source files for a 1C configuration.""" import sys, os, argparse, re, uuid @@ -12,9 +12,12 @@ def new_uuid(): return str(uuid.uuid4()) def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. with open(path, 'w', encoding='utf-8-sig', newline='') as f: f.write(content) + def write_xml_file(path, content): """XML в каноне выгрузки Конфигуратора: CRLF в разделителях, без перевода в конце. diff --git a/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 b/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 index dfc530be..387581a8 100644 --- a/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 +++ b/.claude/skills/cfe-borrow/scripts/cfe-borrow.ps1 @@ -1,4 +1,4 @@ -# cfe-borrow v1.17 — Borrow objects from configuration into extension (CFE) (+detect_format_version: ветка автономной EPF/ERF) +# cfe-borrow v1.18 — Borrow objects from configuration into extension (CFE) (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][string]$ExtensionPath, diff --git a/.claude/skills/cfe-borrow/scripts/cfe-borrow.py b/.claude/skills/cfe-borrow/scripts/cfe-borrow.py index 346487f1..5bfc3312 100644 --- a/.claude/skills/cfe-borrow/scripts/cfe-borrow.py +++ b/.claude/skills/cfe-borrow/scripts/cfe-borrow.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# cfe-borrow v1.17 — Borrow objects from configuration into extension (CFE) (+detect_format_version: ветка автономной EPF/ERF) +# cfe-borrow v1.18 — Borrow objects from configuration into extension (CFE) (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -446,16 +446,12 @@ def save_xml_bom(tree, path): f.write(xml_bytes) -def save_text_bom(path, text): - """Записать текст как есть, ничего не нормализуя. +def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. + with open(path, 'w', encoding='utf-8-sig', newline='') as f: + f.write(content) - Для файлов, которые мы ПРАВИМ: переводы строк уже пришли из самого файла, и - менять их нельзя (контракт #44/#46/#47). newline="" обязателен — без него - текстовый режим Python дал бы CRLF на Windows и LF на macOS, то есть вывод - навыка зависел бы от ОС. - """ - with open(path, "w", encoding="utf-8-sig", newline="") as fh: - fh.write(text) def write_xml_file(path, content): @@ -467,7 +463,7 @@ def write_xml_file(path, content): Только для файлов, которые СОЗДАЁМ: правка существующего наследует его стиль. """ text = content.replace('\r\n', '\n').replace('\n', '\r\n').rstrip('\r\n') - save_text_bom(path, text) + write_utf8_bom(path, text) def new_guid(): @@ -1069,7 +1065,7 @@ def main(): obj_content = re.sub(r'', f"{all_attr_xml}\r\n\t\t", obj_content) else: obj_content = obj_content.replace("", f"{all_attr_xml}\r\n\t\t") - save_text_bom(obj_file, obj_content) + write_utf8_bom(obj_file, obj_content) info(f" Merged {added} attribute(s) into: {obj_file}") # --- 11h. Borrow main attribute orchestrator --- @@ -1156,7 +1152,7 @@ def main(): f"{existing_inner}\r\n{adopted_content}\r\n\t\t" ) - save_text_bom(obj_file, obj_content) + write_utf8_bom(obj_file, obj_content) info(f" Enriched object: {obj_file}") # Step 4: Collect all reference types and borrow as shells @@ -1646,7 +1642,7 @@ def main(): if os.path.isfile(module_bsl_file): info(" Preserved existing Module.bsl") else: - save_text_bom(module_bsl_file, "") + write_utf8_bom(module_bsl_file, "") info(f" Created: {module_bsl_file}") # 7. Register form in parent object ChildObjects diff --git a/.claude/skills/cfe-init/scripts/cfe-init.ps1 b/.claude/skills/cfe-init/scripts/cfe-init.ps1 index edb186c5..bee16f04 100644 --- a/.claude/skills/cfe-init/scripts/cfe-init.ps1 +++ b/.claude/skills/cfe-init/scripts/cfe-init.ps1 @@ -1,4 +1,4 @@ -# cfe-init v1.8 — Create 1C configuration extension scaffold (CFE) (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# cfe-init v1.9 — Create 1C configuration extension scaffold (CFE) (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/cfe-init/scripts/cfe-init.py b/.claude/skills/cfe-init/scripts/cfe-init.py index b7e496e9..735a327e 100644 --- a/.claude/skills/cfe-init/scripts/cfe-init.py +++ b/.claude/skills/cfe-init/scripts/cfe-init.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# cfe-init v1.8 — Create 1C configuration extension scaffold (CFE) (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# cfe-init v1.9 — Create 1C configuration extension scaffold (CFE) (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Generates minimal XML source files for a 1C configuration extension.""" import sys, os, re, argparse, uuid @@ -13,9 +13,12 @@ def new_uuid(): return str(uuid.uuid4()) def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. with open(path, 'w', encoding='utf-8-sig', newline='') as f: f.write(content) + def write_xml_file(path, content): """XML в каноне выгрузки Конфигуратора: CRLF в разделителях, без перевода в конце. diff --git a/.claude/skills/epf-init/scripts/init.ps1 b/.claude/skills/epf-init/scripts/init.ps1 index f8c96e84..86c914c8 100644 --- a/.claude/skills/epf-init/scripts/init.ps1 +++ b/.claude/skills/epf-init/scripts/init.ps1 @@ -1,4 +1,4 @@ -# epf-init v1.5 — Init 1C external data processor scaffold (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# epf-init v1.6 — Init 1C external data processor scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/epf-init/scripts/init.py b/.claude/skills/epf-init/scripts/init.py index 05c48004..319ff7c2 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.5 — Init 1C external data processor scaffold (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# epf-init v1.6 — Init 1C external data processor scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Generates minimal XML source files for a 1C external data processor.""" import sys, os, re, argparse, uuid @@ -12,9 +12,12 @@ def new_uuid(): return str(uuid.uuid4()) def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. with open(path, 'w', encoding='utf-8-sig', newline='') as f: f.write(content) + def write_xml_file(path, content): """XML в каноне выгрузки Конфигуратора: CRLF в разделителях, без перевода в конце. diff --git a/.claude/skills/erf-init/scripts/init.ps1 b/.claude/skills/erf-init/scripts/init.ps1 index bcd5ed65..7906a1a3 100644 --- a/.claude/skills/erf-init/scripts/init.ps1 +++ b/.claude/skills/erf-init/scripts/init.ps1 @@ -1,4 +1,4 @@ -# erf-init v1.5 — Init 1C external report scaffold (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# erf-init v1.6 — Init 1C external report scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/erf-init/scripts/init.py b/.claude/skills/erf-init/scripts/init.py index 7a6ac948..74587649 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.5 — Init 1C external report scaffold (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# erf-init v1.6 — Init 1C external report scaffold (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """Generates minimal XML source files for a 1C external report.""" import sys, os, re, argparse, uuid @@ -12,9 +12,12 @@ def new_uuid(): return str(uuid.uuid4()) def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. with open(path, 'w', encoding='utf-8-sig', newline='') as f: f.write(content) + def write_xml_file(path, content): """XML в каноне выгрузки Конфигуратора: CRLF в разделителях, без перевода в конце. diff --git a/.claude/skills/form-add/scripts/form-add.ps1 b/.claude/skills/form-add/scripts/form-add.ps1 index df95180a..730d0293 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.23 — Add managed form to 1C config object +# form-add v1.24 — Add managed form to 1C config object (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/form-add/scripts/form-add.py b/.claude/skills/form-add/scripts/form-add.py index 4e198602..35f2d89e 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.23 — Add managed form to 1C config object +# form-add v1.24 — Add managed form to 1C config object (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -274,12 +274,12 @@ def save_xml_with_bom(tree, path): f.write(xml_bytes) -def write_text_with_bom(path, text): - """Write text to file with UTF-8 BOM.""" - # newline="" => без трансляции: в текстовом режиме Python на Windows превратил - # бы \n в \r\n, а на macOS оставил \n — вывод зависел бы от ОС. - with open(path, "w", encoding="utf-8-sig", newline="") as f: - f.write(text) +def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. + with open(path, 'w', encoding='utf-8-sig', newline='') as f: + f.write(content) + def write_xml_file(path, content): @@ -291,7 +291,7 @@ def write_xml_file(path, content): Модуль .bsl сюда НЕ идёт — он пишется отдельно. """ text = content.replace('\r\n', '\n').replace('\n', '\r\n').rstrip('\r\n') - write_text_with_bom(path, text) + write_utf8_bom(path, text) def main(): @@ -641,7 +641,7 @@ def main(): # Модуль пишем в каноне платформы: CRLF в разделителях строк (корпус: 2643 CRLF, # чисто-LF 0 из 3001). Хвостовой перевод НЕ навязываем — у платформы он # неканоничен (1235 модулей с ним, 766 без). - write_text_with_bom(module_path, module_bsl.replace('\r\n', '\n').replace('\n', '\r\n')) + write_utf8_bom(module_path, module_bsl.replace('\r\n', '\n').replace('\n', '\r\n')) # --- Phase 4: Register in parent object --- diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index 5493bd61..1500053c 100644 --- a/.claude/skills/form-compile/scripts/form-compile.ps1 +++ b/.claude/skills/form-compile/scripts/form-compile.ps1 @@ -1,4 +1,4 @@ -# form-compile v1.188 — Compile 1C managed form from JSON or object metadata (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# form-compile v1.189 — Compile 1C managed form from JSON or object metadata (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 066f1531..057d42c0 100644 --- a/.claude/skills/form-compile/scripts/form-compile.py +++ b/.claude/skills/form-compile/scripts/form-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-compile v1.188 — Compile 1C managed form from JSON or object metadata (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# form-compile v1.189 — Compile 1C managed form from JSON or object metadata (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -2123,10 +2123,13 @@ def emit_conditional_appearance(lines, items, indent, block_view_mode=None, bloc def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. with open(path, 'w', encoding='utf-8-sig', newline='') as f: f.write(content) + # --- ID allocator --- _next_id = 0 diff --git a/.claude/skills/help-add/scripts/add-help.ps1 b/.claude/skills/help-add/scripts/add-help.ps1 index 77813ac7..673e241b 100644 --- a/.claude/skills/help-add/scripts/add-help.ps1 +++ b/.claude/skills/help-add/scripts/add-help.ps1 @@ -1,4 +1,4 @@ -# help-add v1.17 — Add built-in help to 1C object (+detect_format_version: ветка автономной EPF/ERF) +# help-add v1.18 — Add built-in help to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/help-add/scripts/add-help.py b/.claude/skills/help-add/scripts/add-help.py index 6aaf9f4a..29230f26 100644 --- a/.claude/skills/help-add/scripts/add-help.py +++ b/.claude/skills/help-add/scripts/add-help.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# help-add v1.17 — Add built-in help to 1C object (+detect_format_version: ветка автономной EPF/ERF) +# help-add v1.18 — Add built-in help to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -263,15 +263,12 @@ def save_xml_with_bom(tree, path): f.write(xml_bytes) -def write_text_with_bom(path, text): - """Write text to file with UTF-8 BOM. +def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. + with open(path, 'w', encoding='utf-8-sig', newline='') as f: + f.write(content) - newline="" обязателен: в текстовом режиме Python на Windows превратил бы \\n в - \\r\\n, а на macOS оставил \\n — вывод навыка зависел бы от ОС. Через эту функцию - идёт HTML-страница справки, а её платформа хранит именно с LF (корпус: 399 LF из 400). - """ - with open(path, "w", encoding="utf-8-sig", newline="") as f: - f.write(text) def write_xml_file(path, content): @@ -283,7 +280,7 @@ def write_xml_file(path, content): HTML-страница сюда НЕ идёт — платформа хранит её с LF. """ text = content.replace('\r\n', '\n').replace('\n', '\r\n').rstrip('\r\n') - write_text_with_bom(path, text) + write_utf8_bom(path, text) def main(): @@ -352,7 +349,7 @@ def main(): '' ) - write_text_with_bom(help_html_path, help_html) + write_utf8_bom(help_html_path, help_html) # --- 3. Check IncludeHelpInContents in form metadata --- diff --git a/.claude/skills/meta-compile/scripts/meta-compile.ps1 b/.claude/skills/meta-compile/scripts/meta-compile.ps1 index 5de67d44..582fe5b2 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.ps1 +++ b/.claude/skills/meta-compile/scripts/meta-compile.ps1 @@ -1,4 +1,4 @@ -# meta-compile v1.91 — Compile 1C metadata object from JSON (+resolve_type_str: срезание префикса cfg:/d5p1:) +# meta-compile v1.92 — Compile 1C metadata object from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/meta-compile/scripts/meta-compile.py b/.claude/skills/meta-compile/scripts/meta-compile.py index 8dd9035b..e9da38a1 100644 --- a/.claude/skills/meta-compile/scripts/meta-compile.py +++ b/.claude/skills/meta-compile/scripts/meta-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# meta-compile v1.91 — Compile 1C metadata object from JSON (+resolve_type_str: срезание префикса cfg:/d5p1:) +# meta-compile v1.92 — Compile 1C metadata object from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -206,9 +206,12 @@ def new_uuid(): return str(uuid.uuid4()) def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. with open(path, 'w', encoding='utf-8-sig', newline='') as f: f.write(content) + def write_xml_file_keep_eol(path, content): # Единая точка записи XML. Конфигуратор не пишет перевод строки в конце файла — # последний байт `>`. diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 b/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 index 696cde37..6f16ffab 100644 --- a/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 +++ b/.claude/skills/mxl-compile/scripts/mxl-compile.ps1 @@ -1,4 +1,4 @@ -# mxl-compile v1.11 — Compile 1C spreadsheet from JSON (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# mxl-compile v1.12 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/mxl-compile/scripts/mxl-compile.py b/.claude/skills/mxl-compile/scripts/mxl-compile.py index 18945141..e8bdfe4e 100644 --- a/.claude/skills/mxl-compile/scripts/mxl-compile.py +++ b/.claude/skills/mxl-compile/scripts/mxl-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# mxl-compile v1.11 — Compile 1C spreadsheet from JSON (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# mxl-compile v1.12 — Compile 1C spreadsheet from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -199,10 +199,13 @@ def esc_xml_text(s): def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. with open(path, 'w', encoding='utf-8-sig', newline='') as f: f.write(content) + def detect_format_version(d): while d: # Автономная внешняя обработка/отчёт: своего Configuration.xml у неё нет, версию несёт diff --git a/.claude/skills/role-compile/scripts/role-compile.ps1 b/.claude/skills/role-compile/scripts/role-compile.ps1 index 2e426ea5..44816434 100644 --- a/.claude/skills/role-compile/scripts/role-compile.ps1 +++ b/.claude/skills/role-compile/scripts/role-compile.ps1 @@ -1,4 +1,4 @@ -# role-compile v1.20 — Compile 1C role from JSON (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# role-compile v1.21 — Compile 1C role from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/role-compile/scripts/role-compile.py b/.claude/skills/role-compile/scripts/role-compile.py index 8333c92f..3649b26d 100644 --- a/.claude/skills/role-compile/scripts/role-compile.py +++ b/.claude/skills/role-compile/scripts/role-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# role-compile v1.20 — Compile 1C role from JSON (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# role-compile v1.21 — Compile 1C role from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -255,10 +255,13 @@ def new_uuid(): def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. with open(path, 'w', encoding='utf-8-sig', newline='') as f: f.write(content) + # --- Russian synonyms -> canonical English names --- TYPE_ALIASES = { diff --git a/.claude/skills/skd-compile/scripts/skd-compile.ps1 b/.claude/skills/skd-compile/scripts/skd-compile.ps1 index 409a114e..5fd3ca24 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.ps1 +++ b/.claude/skills/skd-compile/scripts/skd-compile.ps1 @@ -1,4 +1,4 @@ -# skd-compile v1.114 — Compile 1C DCS from JSON (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# skd-compile v1.115 — Compile 1C DCS from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, diff --git a/.claude/skills/skd-compile/scripts/skd-compile.py b/.claude/skills/skd-compile/scripts/skd-compile.py index f737fa62..f4713253 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.py +++ b/.claude/skills/skd-compile/scripts/skd-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# skd-compile v1.114 — Compile 1C DCS from JSON (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# skd-compile v1.115 — Compile 1C DCS from JSON (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -254,10 +254,13 @@ def new_uuid(): def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. with open(path, 'w', encoding='utf-8-sig', newline='') as f: f.write(content) + # --- Type system --- TYPE_SYNONYMS = { diff --git a/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 b/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 index 5b6b1616..053210c1 100644 --- a/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 +++ b/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 @@ -1,4 +1,4 @@ -# subsystem-compile v1.21 — Create 1C subsystem from JSON definition (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# subsystem-compile v1.22 — Create 1C subsystem from JSON definition (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, diff --git a/.claude/skills/subsystem-compile/scripts/subsystem-compile.py b/.claude/skills/subsystem-compile/scripts/subsystem-compile.py index 5c8cc80f..36c3e0e1 100644 --- a/.claude/skills/subsystem-compile/scripts/subsystem-compile.py +++ b/.claude/skills/subsystem-compile/scripts/subsystem-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# subsystem-compile v1.21 — Create 1C subsystem from JSON definition (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# subsystem-compile v1.22 — Create 1C subsystem from JSON definition (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json @@ -256,10 +256,13 @@ def new_uuid(): def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. with open(path, 'w', encoding='utf-8-sig', newline='') as f: f.write(content) + def split_camel_case(name): if not name: return name diff --git a/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 b/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 index 5f52b3c1..345dac9e 100644 --- a/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 +++ b/.claude/skills/subsystem-edit/scripts/subsystem-edit.ps1 @@ -1,4 +1,4 @@ -# subsystem-edit v1.16 — Edit existing 1C subsystem XML (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# subsystem-edit v1.17 — Edit existing 1C subsystem XML (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)][Alias('Path')][string]$SubsystemPath, diff --git a/.claude/skills/subsystem-edit/scripts/subsystem-edit.py b/.claude/skills/subsystem-edit/scripts/subsystem-edit.py index 68389aca..bcfc42f6 100644 --- a/.claude/skills/subsystem-edit/scripts/subsystem-edit.py +++ b/.claude/skills/subsystem-edit/scripts/subsystem-edit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# subsystem-edit v1.16 — Edit existing 1C subsystem XML (+esc_xml/esc_xml_text: разное экранирование атрибута и текста) +# subsystem-edit v1.17 — Edit existing 1C subsystem XML (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -204,10 +204,13 @@ def esc_xml_text(s): def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. with open(path, 'w', encoding='utf-8-sig', newline='') as f: f.write(content) + # Объявления пространств имён — одной переменной: место эмиссии её только подставляет. # Правки шапки (как xmlns:pal в формате 2.21) делаются в одном месте, в main. XMLNS_DECL = ( diff --git a/.claude/skills/template-add/scripts/add-template.ps1 b/.claude/skills/template-add/scripts/add-template.ps1 index 3155e528..56b46bd7 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.21 — Add template to 1C object +# template-add v1.22 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] diff --git a/.claude/skills/template-add/scripts/add-template.py b/.claude/skills/template-add/scripts/add-template.py index 8c4b3959..97b0524d 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.21 — Add template to 1C object +# template-add v1.22 — Add template to 1C object (+write_xml_file/write_utf8_bom: общий эталон записи) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -246,15 +246,12 @@ def save_xml_with_bom(tree, path): f.write(xml_bytes) -def write_text_with_bom(path, text): - """Write text to file with UTF-8 BOM. +def write_utf8_bom(path, content): + # newline='' — без трансляции: иначе текстовый режим Python дал бы CRLF на Windows + # и LF на macOS, то есть вывод навыка зависел бы от ОС. + with open(path, 'w', encoding='utf-8-sig', newline='') as f: + f.write(content) - newline="" обязателен: в текстовом режиме Python на Windows превратил бы \\n в - \\r\\n, а на macOS оставил \\n — вывод навыка зависел бы от ОС. Через эту функцию - идёт HTML-макет, а его платформа хранит именно с LF (корпус: 399 LF из 400). - """ - with open(path, "w", encoding="utf-8-sig", newline="") as f: - f.write(text) def write_xml_file(path, content): @@ -266,7 +263,7 @@ def write_xml_file(path, content): HTML-макет сюда НЕ идёт — платформа хранит его с LF. """ text = content.replace('\r\n', '\n').replace('\n', '\r\n').rstrip('\r\n') - write_text_with_bom(path, text) + write_utf8_bom(path, text) def detect_format_version(d): @@ -451,10 +448,10 @@ def main(): '\n' '' ) - write_text_with_bom(template_file_path, content) + write_utf8_bom(template_file_path, content) elif template_type == "Text": - write_text_with_bom(template_file_path, "") + write_utf8_bom(template_file_path, "") elif template_type == "SpreadsheetDocument": # Пустой макет — самозакрывающимся корнем: пустых пар платформа не пишет diff --git a/tests/skills/check-inline-drift.mjs b/tests/skills/check-inline-drift.mjs index ecc8a9c8..b370a9c8 100644 --- a/tests/skills/check-inline-drift.mjs +++ b/tests/skills/check-inline-drift.mjs @@ -111,6 +111,25 @@ const FAMILIES = [ ], }, + // ─── Запись файла в каноне выгрузки ────────────────────────────────────── + { + name: 'write_xml_file', py: 'write_xml_file', ps1: 'Write-XmlFile', + variants: [ + { id: 'base', authority: 'cf-init', + consumers: ['cfe-init', 'epf-init', 'erf-init', 'form-add', 'help-add', 'template-add'], + consumersPy: ['cfe-borrow'] }, + ], + }, + { + name: 'write_utf8_bom', py: 'write_utf8_bom', ps1: null, + variants: [ + { id: 'base', authority: 'cf-init', + consumers: ['cfe-borrow', 'cfe-init', 'epf-init', 'erf-init', 'form-add', 'form-compile', + 'help-add', 'meta-compile', 'mxl-compile', 'role-compile', 'skd-compile', + 'subsystem-compile', 'subsystem-edit', 'template-add'] }, + ], + }, + // ─── Отчёт валидаторов ─────────────────────────────────────────────────── // Два варианта по способу вывода: буферизованный Out-Line копит отчёт в $script:output, что даёт // -OutFile (та же выдача в файл) и вставку заголовка в начало; потоковый Write-Host этого не умеет. @@ -265,7 +284,6 @@ const DRIFTED = [ { name: 'get_ml_text', py: 'get_ml_text', ps1: 'Get-MLText', maxVariants: { py: 7, ps1: 6 } }, { name: 'import_fragment', py: 'import_fragment', ps1: 'Import-Fragment', maxVariants: { py: 5, ps1: 4 } }, { name: 'get_child_indent', py: 'get_child_indent', ps1: 'Get-ChildIndent', maxVariants: { py: 4, ps1: 3 } }, - { name: 'write_xml_file', py: 'write_xml_file', ps1: null, maxVariants: { py: 3 } }, ]; // ─── Извлечение тел функций ─────────────────────────────────────────────────