mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-07 20:20:20 +03:00
fix(cfe-borrow,template-add,help-add,interface-edit): вывод py-порта не зависит от ОС (#57)
Тот же writer без newline="", что чинился в form-add.py, остался ещё в четырёх py-портах, и пишут они не модули, а 1С XML: заимствованные объекты и метаданные формы (cfe-borrow), Template.xml и XML-макеты (template-add), Help.xml (help-add), вновь создаваемый CommandInterface.xml (interface-edit). Контент там собирается литералами с \n, поэтому текстовый режим Python давал CRLF на Windows — «случайно правильно» — и LF на macOS, ломая канон #57 ровно там, где он только что установлен. Проверено на маке ДО фикса: cfe-borrow 0 CRLF + 33 одиночных LF, template-add 0 + 2, interface-edit 0 + 5. Порчи \r\r\n не было, но это везение: подай такой writer CRLF-контент — каждая строка стала бы \r\r\n. Почему не поймали раньше: аудит гонялся на Windows, где текстовый режим даёт канон; снэпшоты нормализуют EOL; байтовый preserves ни разу не проверялся на маке. Разделены два пути, которые я сперва смешал в cfe-borrow: - save_xml_file — канон (CRLF, без хвоста) для файлов, которые СОЗДАЁМ; - save_text_bom — пишет как есть, для файлов, которые ПРАВИМ: переводы строк уже пришли из самого файла и менять их нельзя (контракт #44/#46/#47). Туда же добавлено чтение с newline="" — иначе CRLF терялся ещё на входе. interface-edit чинится и в PS-порте: ветка -CreateIfMissing давала смешанный EOL (3 CRLF + 2 одиночных LF) уже на Windows. Аудит #57 её пропустил, потому что фильтровал файлы по расширению .xml, а кейс создаёт файл с именем без расширения. Канон, как выяснилось, зависит от типа артефакта: XML — CRLF, текстовый макет — CRLF, а HTML-макет платформа хранит с LF (корпус: 399 LF из 400). Поэтому HTML через канон-writer НЕ идёт. preserves добавлен четырём навыкам (у них его не было вовсе) + отдельно на Help.xml. Именно прогон на маке и даёт покрытие: на Windows эти кейсы зелены и без фикса. Windows 641/641 обоими портами, мак 590/0/51, дрейфа снэпшотов нет. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
668b145010
commit
caf038a192
@@ -1,4 +1,4 @@
|
|||||||
# cfe-borrow v1.12 — Borrow objects from configuration into extension (CFE)
|
# cfe-borrow v1.13 — Borrow objects from configuration into extension (CFE)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)][string]$ExtensionPath,
|
[Parameter(Mandatory)][string]$ExtensionPath,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# cfe-borrow v1.12 — Borrow objects from configuration into extension (CFE)
|
# cfe-borrow v1.13 — Borrow objects from configuration into extension (CFE)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -419,10 +419,26 @@ def save_xml_bom(tree, path):
|
|||||||
|
|
||||||
|
|
||||||
def save_text_bom(path, text):
|
def save_text_bom(path, text):
|
||||||
with open(path, "w", encoding="utf-8-sig") as fh:
|
"""Записать текст как есть, ничего не нормализуя.
|
||||||
|
|
||||||
|
Для файлов, которые мы ПРАВИМ: переводы строк уже пришли из самого файла, и
|
||||||
|
менять их нельзя (контракт #44/#46/#47). newline="" обязателен — без него
|
||||||
|
текстовый режим Python дал бы CRLF на Windows и LF на macOS, то есть вывод
|
||||||
|
навыка зависел бы от ОС.
|
||||||
|
"""
|
||||||
|
with open(path, "w", encoding="utf-8-sig", newline="") as fh:
|
||||||
fh.write(text)
|
fh.write(text)
|
||||||
|
|
||||||
|
|
||||||
|
def save_xml_file(path, text):
|
||||||
|
"""XML в каноне выгрузки Конфигуратора: CRLF, без перевода строки в конце.
|
||||||
|
|
||||||
|
Для файлов, которые мы СОЗДАЁМ. Правило: создаём — пишем канон, правим
|
||||||
|
существующий — наследуем его стиль (см. save_text_bom).
|
||||||
|
"""
|
||||||
|
save_text_bom(path, text.replace("\r\n", "\n").replace("\n", "\r\n").rstrip("\r\n"))
|
||||||
|
|
||||||
|
|
||||||
def new_guid():
|
def new_guid():
|
||||||
return str(uuid.uuid4())
|
return str(uuid.uuid4())
|
||||||
|
|
||||||
@@ -997,7 +1013,9 @@ def main():
|
|||||||
warn(f"Cannot merge attributes: {obj_file} not found")
|
warn(f"Cannot merge attributes: {obj_file} not found")
|
||||||
return
|
return
|
||||||
|
|
||||||
with open(obj_file, "r", encoding="utf-8-sig") as fh:
|
# newline="" => без трансляции: иначе CRLF молча схлопнется в LF при чтении
|
||||||
|
# и файл будет переписан в LF (#44/#46/#47).
|
||||||
|
with open(obj_file, "r", encoding="utf-8-sig", newline="") as fh:
|
||||||
obj_content = fh.read()
|
obj_content = fh.read()
|
||||||
|
|
||||||
# Collect existing attribute names for dedup (text-based)
|
# Collect existing attribute names for dedup (text-based)
|
||||||
@@ -1056,7 +1074,9 @@ def main():
|
|||||||
obj_file = os.path.join(ext_dir, dir_name, f"{obj_name}.xml")
|
obj_file = os.path.join(ext_dir, dir_name, f"{obj_name}.xml")
|
||||||
|
|
||||||
# Read existing object XML (needed for dedup + enrichment)
|
# Read existing object XML (needed for dedup + enrichment)
|
||||||
with open(obj_file, "r", encoding="utf-8-sig") as fh:
|
# newline="" => без трансляции: иначе CRLF молча схлопнется в LF при чтении
|
||||||
|
# и файл будет переписан в LF (#44/#46/#47).
|
||||||
|
with open(obj_file, "r", encoding="utf-8-sig", newline="") as fh:
|
||||||
obj_content = fh.read()
|
obj_content = fh.read()
|
||||||
|
|
||||||
# Dedup: skip attributes/TS already present in object's ChildObjects (idempotent re-borrow)
|
# Dedup: skip attributes/TS already present in object's ChildObjects (idempotent re-borrow)
|
||||||
@@ -1133,7 +1153,7 @@ def main():
|
|||||||
target_dir = os.path.join(ext_dir, CHILD_TYPE_DIR_MAP[rt["TypeName"]])
|
target_dir = os.path.join(ext_dir, CHILD_TYPE_DIR_MAP[rt["TypeName"]])
|
||||||
os.makedirs(target_dir, exist_ok=True)
|
os.makedirs(target_dir, exist_ok=True)
|
||||||
target_file = os.path.join(target_dir, f"{rt['ObjName']}.xml")
|
target_file = os.path.join(target_dir, f"{rt['ObjName']}.xml")
|
||||||
save_text_bom(target_file, borrowed_xml)
|
save_xml_file(target_file, borrowed_xml)
|
||||||
add_to_child_objects(rt["TypeName"], rt["ObjName"])
|
add_to_child_objects(rt["TypeName"], rt["ObjName"])
|
||||||
borrowed_files.append(target_file)
|
borrowed_files.append(target_file)
|
||||||
info(f" Auto-borrowed: {rt['TypeName']}.{rt['ObjName']}")
|
info(f" Auto-borrowed: {rt['TypeName']}.{rt['ObjName']}")
|
||||||
@@ -1198,7 +1218,7 @@ def main():
|
|||||||
t_target_dir = os.path.join(ext_dir, CHILD_TYPE_DIR_MAP[target_type_name])
|
t_target_dir = os.path.join(ext_dir, CHILD_TYPE_DIR_MAP[target_type_name])
|
||||||
os.makedirs(t_target_dir, exist_ok=True)
|
os.makedirs(t_target_dir, exist_ok=True)
|
||||||
t_target_file = os.path.join(t_target_dir, f"{target_obj_name}.xml")
|
t_target_file = os.path.join(t_target_dir, f"{target_obj_name}.xml")
|
||||||
save_text_bom(t_target_file, t_borrowed_xml)
|
save_xml_file(t_target_file, t_borrowed_xml)
|
||||||
add_to_child_objects(target_type_name, target_obj_name)
|
add_to_child_objects(target_type_name, target_obj_name)
|
||||||
borrowed_files.append(t_target_file)
|
borrowed_files.append(t_target_file)
|
||||||
info(f" Auto-borrowed for deep path: {target_type_name}.{target_obj_name}")
|
info(f" Auto-borrowed for deep path: {target_type_name}.{target_obj_name}")
|
||||||
@@ -1222,7 +1242,7 @@ def main():
|
|||||||
s_target_dir = os.path.join(ext_dir, CHILD_TYPE_DIR_MAP[srt["TypeName"]])
|
s_target_dir = os.path.join(ext_dir, CHILD_TYPE_DIR_MAP[srt["TypeName"]])
|
||||||
os.makedirs(s_target_dir, exist_ok=True)
|
os.makedirs(s_target_dir, exist_ok=True)
|
||||||
s_target_file = os.path.join(s_target_dir, f"{srt['ObjName']}.xml")
|
s_target_file = os.path.join(s_target_dir, f"{srt['ObjName']}.xml")
|
||||||
save_text_bom(s_target_file, s_borrowed_xml)
|
save_xml_file(s_target_file, s_borrowed_xml)
|
||||||
add_to_child_objects(srt["TypeName"], srt["ObjName"])
|
add_to_child_objects(srt["TypeName"], srt["ObjName"])
|
||||||
borrowed_files.append(s_target_file)
|
borrowed_files.append(s_target_file)
|
||||||
info(f" Auto-borrowed (deep): {srt['TypeName']}.{srt['ObjName']}")
|
info(f" Auto-borrowed (deep): {srt['TypeName']}.{srt['ObjName']}")
|
||||||
@@ -1279,7 +1299,7 @@ def main():
|
|||||||
os.makedirs(form_meta_dir, exist_ok=True)
|
os.makedirs(form_meta_dir, exist_ok=True)
|
||||||
|
|
||||||
form_meta_file = os.path.join(form_meta_dir, f"{form_name}.xml")
|
form_meta_file = os.path.join(form_meta_dir, f"{form_name}.xml")
|
||||||
save_text_bom(form_meta_file, "\n".join(form_meta_lines))
|
save_xml_file(form_meta_file, "\n".join(form_meta_lines))
|
||||||
info(f" Created: {form_meta_file}")
|
info(f" Created: {form_meta_file}")
|
||||||
|
|
||||||
# 5. Generate Form.xml with BaseForm
|
# 5. Generate Form.xml with BaseForm
|
||||||
@@ -1365,7 +1385,7 @@ def main():
|
|||||||
target_dir = os.path.join(ext_dir, "CommonPictures")
|
target_dir = os.path.join(ext_dir, "CommonPictures")
|
||||||
os.makedirs(target_dir, exist_ok=True)
|
os.makedirs(target_dir, exist_ok=True)
|
||||||
target_file = os.path.join(target_dir, f"{pic_name}.xml")
|
target_file = os.path.join(target_dir, f"{pic_name}.xml")
|
||||||
save_text_bom(target_file, borrowed_xml)
|
save_xml_file(target_file, borrowed_xml)
|
||||||
add_to_child_objects("CommonPicture", pic_name)
|
add_to_child_objects("CommonPicture", pic_name)
|
||||||
auto_borrowed_pics.append(pic_name)
|
auto_borrowed_pics.append(pic_name)
|
||||||
borrowed_files.append(target_file)
|
borrowed_files.append(target_file)
|
||||||
@@ -1414,7 +1434,7 @@ def main():
|
|||||||
target_dir = os.path.join(ext_dir, "StyleItems")
|
target_dir = os.path.join(ext_dir, "StyleItems")
|
||||||
os.makedirs(target_dir, exist_ok=True)
|
os.makedirs(target_dir, exist_ok=True)
|
||||||
target_file = os.path.join(target_dir, f"{style_name}.xml")
|
target_file = os.path.join(target_dir, f"{style_name}.xml")
|
||||||
save_text_bom(target_file, borrowed_xml)
|
save_xml_file(target_file, borrowed_xml)
|
||||||
add_to_child_objects("StyleItem", style_name)
|
add_to_child_objects("StyleItem", style_name)
|
||||||
borrowed_files.append(target_file)
|
borrowed_files.append(target_file)
|
||||||
info(f" Auto-borrowed: StyleItem.{style_name}")
|
info(f" Auto-borrowed: StyleItem.{style_name}")
|
||||||
@@ -1478,7 +1498,7 @@ def main():
|
|||||||
target_dir = os.path.join(ext_dir, "Enums")
|
target_dir = os.path.join(ext_dir, "Enums")
|
||||||
os.makedirs(target_dir, exist_ok=True)
|
os.makedirs(target_dir, exist_ok=True)
|
||||||
target_file = os.path.join(target_dir, f"{enum_name}.xml")
|
target_file = os.path.join(target_dir, f"{enum_name}.xml")
|
||||||
save_text_bom(target_file, borrowed_xml)
|
save_xml_file(target_file, borrowed_xml)
|
||||||
add_to_child_objects("Enum", enum_name)
|
add_to_child_objects("Enum", enum_name)
|
||||||
borrowed_files.append(target_file)
|
borrowed_files.append(target_file)
|
||||||
info(f" Auto-borrowed: Enum.{enum_name} (with {len(ev_xmls)} EnumValue(s))")
|
info(f" Auto-borrowed: Enum.{enum_name} (with {len(ev_xmls)} EnumValue(s))")
|
||||||
@@ -1572,7 +1592,7 @@ def main():
|
|||||||
form_xml_dir = os.path.join(form_meta_dir, form_name, "Ext")
|
form_xml_dir = os.path.join(form_meta_dir, form_name, "Ext")
|
||||||
os.makedirs(form_xml_dir, exist_ok=True)
|
os.makedirs(form_xml_dir, exist_ok=True)
|
||||||
form_xml_file = os.path.join(form_xml_dir, "Form.xml")
|
form_xml_file = os.path.join(form_xml_dir, "Form.xml")
|
||||||
save_text_bom(form_xml_file, "".join(parts))
|
save_xml_file(form_xml_file, "".join(parts))
|
||||||
info(f" Created: {form_xml_file}")
|
info(f" Created: {form_xml_file}")
|
||||||
|
|
||||||
# 6. Create empty Module.bsl — but NEVER overwrite an existing one (re-borrow must
|
# 6. Create empty Module.bsl — but NEVER overwrite an existing one (re-borrow must
|
||||||
@@ -1656,7 +1676,7 @@ def main():
|
|||||||
target_dir = os.path.join(ext_dir, dir_name)
|
target_dir = os.path.join(ext_dir, dir_name)
|
||||||
os.makedirs(target_dir, exist_ok=True)
|
os.makedirs(target_dir, exist_ok=True)
|
||||||
target_file = os.path.join(target_dir, f"{obj_name}.xml")
|
target_file = os.path.join(target_dir, f"{obj_name}.xml")
|
||||||
save_text_bom(target_file, borrowed_xml)
|
save_xml_file(target_file, borrowed_xml)
|
||||||
info(f" Created: {target_file}")
|
info(f" Created: {target_file}")
|
||||||
|
|
||||||
add_to_child_objects(type_name, obj_name)
|
add_to_child_objects(type_name, obj_name)
|
||||||
@@ -1683,7 +1703,7 @@ def main():
|
|||||||
os.makedirs(target_dir, exist_ok=True)
|
os.makedirs(target_dir, exist_ok=True)
|
||||||
|
|
||||||
target_file = os.path.join(target_dir, f"{obj_name}.xml")
|
target_file = os.path.join(target_dir, f"{obj_name}.xml")
|
||||||
save_text_bom(target_file, borrowed_xml)
|
save_xml_file(target_file, borrowed_xml)
|
||||||
info(f" Created: {target_file}")
|
info(f" Created: {target_file}")
|
||||||
|
|
||||||
add_to_child_objects(type_name, obj_name)
|
add_to_child_objects(type_name, obj_name)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# help-add v1.12 — Add built-in help to 1C object
|
# help-add v1.13 — Add built-in help to 1C object
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# help-add v1.12 — Add built-in help to 1C object
|
# help-add v1.13 — Add built-in help to 1C object
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -253,11 +253,24 @@ def save_xml_with_bom(tree, path):
|
|||||||
|
|
||||||
|
|
||||||
def write_text_with_bom(path, text):
|
def write_text_with_bom(path, text):
|
||||||
"""Write text to file with UTF-8 BOM."""
|
"""Write text to file with UTF-8 BOM.
|
||||||
with open(path, "w", encoding="utf-8-sig") as f:
|
|
||||||
|
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)
|
f.write(text)
|
||||||
|
|
||||||
|
|
||||||
|
def write_xml_file(path, text):
|
||||||
|
"""XML в каноне выгрузки Конфигуратора: CRLF, без перевода строки в конце.
|
||||||
|
|
||||||
|
Для Help.xml. HTML-страница сюда НЕ идёт — у неё свой канон (LF).
|
||||||
|
"""
|
||||||
|
write_text_with_bom(path, text.replace("\r\n", "\n").replace("\n", "\r\n").rstrip("\r\n"))
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
sys.stdout.reconfigure(encoding="utf-8")
|
sys.stdout.reconfigure(encoding="utf-8")
|
||||||
sys.stderr.reconfigure(encoding="utf-8")
|
sys.stderr.reconfigure(encoding="utf-8")
|
||||||
@@ -301,7 +314,7 @@ def main():
|
|||||||
'</Help>'
|
'</Help>'
|
||||||
)
|
)
|
||||||
|
|
||||||
write_text_with_bom(help_xml_path, help_xml)
|
write_xml_file(help_xml_path, help_xml)
|
||||||
|
|
||||||
# --- 2. Help/<lang>.html ---
|
# --- 2. Help/<lang>.html ---
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# interface-edit v1.10 — Edit 1C CommandInterface.xml
|
# interface-edit v1.11 — Edit 1C CommandInterface.xml
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)][Alias('Path')][string]$CIPath,
|
[Parameter(Mandatory)][Alias('Path')][string]$CIPath,
|
||||||
@@ -202,7 +202,12 @@ if (-not (Test-Path $CIPath)) {
|
|||||||
</CommandInterface>
|
</CommandInterface>
|
||||||
"@
|
"@
|
||||||
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
||||||
[System.IO.File]::WriteAllText($CIPath, $emptyCI, $utf8Bom)
|
# Файл СОЗДАЁМ — пишем канон выгрузки: CRLF, без перевода строки в конце.
|
||||||
|
# (Правка существующего файла, наоборот, наследует его стиль — это делает
|
||||||
|
# основной путь сохранения ниже.) Нормализация нужна потому, что here-string
|
||||||
|
# берёт переводы строк из самого .ps1, а он в репозитории хранится с LF.
|
||||||
|
$emptyCI = ($emptyCI -replace "`r`n", "`n") -replace "`n", "`r`n"
|
||||||
|
[System.IO.File]::WriteAllText($CIPath, $emptyCI.TrimEnd("`r", "`n"), $utf8Bom)
|
||||||
Write-Host "[INFO] Created new CommandInterface.xml: $CIPath"
|
Write-Host "[INFO] Created new CommandInterface.xml: $CIPath"
|
||||||
} else {
|
} else {
|
||||||
Write-Error "File not found: $CIPath (use -CreateIfMissing to create)"
|
Write-Error "File not found: $CIPath (use -CreateIfMissing to create)"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# interface-edit v1.10 — Edit 1C CommandInterface.xml
|
# interface-edit v1.11 — Edit 1C CommandInterface.xml
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -438,7 +438,12 @@ def main():
|
|||||||
f'\tversion="{format_version}">\n'
|
f'\tversion="{format_version}">\n'
|
||||||
f'</CommandInterface>'
|
f'</CommandInterface>'
|
||||||
)
|
)
|
||||||
with open(ci_path, "w", encoding="utf-8-sig") as fh:
|
# Файл СОЗДАЁМ — пишем канон выгрузки: CRLF в разделителях. (Правка
|
||||||
|
# существующего файла, наоборот, наследует его стиль — это делает
|
||||||
|
# save_xml_bom через _detect_xml_style.) newline="" обязателен: без него
|
||||||
|
# текстовый режим дал бы CRLF на Windows и LF на macOS.
|
||||||
|
empty_ci = empty_ci.replace("\r\n", "\n").replace("\n", "\r\n")
|
||||||
|
with open(ci_path, "w", encoding="utf-8-sig", newline="") as fh:
|
||||||
fh.write(empty_ci)
|
fh.write(empty_ci)
|
||||||
print(f"[INFO] Created new CommandInterface.xml: {ci_path}")
|
print(f"[INFO] Created new CommandInterface.xml: {ci_path}")
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# template-add v1.14 — Add template to 1C object
|
# template-add v1.15 — Add template to 1C object
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# template-add v1.14 — Add template to 1C object
|
# template-add v1.15 — Add template to 1C object
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -246,11 +246,25 @@ def save_xml_with_bom(tree, path):
|
|||||||
|
|
||||||
|
|
||||||
def write_text_with_bom(path, text):
|
def write_text_with_bom(path, text):
|
||||||
"""Write text to file with UTF-8 BOM."""
|
"""Write text to file with UTF-8 BOM.
|
||||||
with open(path, "w", encoding="utf-8-sig") as f:
|
|
||||||
|
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)
|
f.write(text)
|
||||||
|
|
||||||
|
|
||||||
|
def write_xml_file(path, text):
|
||||||
|
"""XML в каноне выгрузки Конфигуратора: CRLF, без перевода строки в конце.
|
||||||
|
|
||||||
|
Для XML-макетов (SpreadsheetDocument, DataCompositionSchema) и Template.xml.
|
||||||
|
HTML-макет сюда НЕ идёт — у него свой канон (LF).
|
||||||
|
"""
|
||||||
|
write_text_with_bom(path, text.replace("\r\n", "\n").replace("\n", "\r\n").rstrip("\r\n"))
|
||||||
|
|
||||||
|
|
||||||
def detect_format_version(d):
|
def detect_format_version(d):
|
||||||
while d:
|
while d:
|
||||||
cfg_path = os.path.join(d, "Configuration.xml")
|
cfg_path = os.path.join(d, "Configuration.xml")
|
||||||
@@ -376,7 +390,7 @@ def main():
|
|||||||
'</MetaDataObject>'
|
'</MetaDataObject>'
|
||||||
)
|
)
|
||||||
|
|
||||||
write_text_with_bom(template_meta_path, template_meta_xml)
|
write_xml_file(template_meta_path, template_meta_xml)
|
||||||
|
|
||||||
# --- 2. Template content (Templates/<TemplateName>/Ext/Template.<ext>) ---
|
# --- 2. Template content (Templates/<TemplateName>/Ext/Template.<ext>) ---
|
||||||
|
|
||||||
@@ -408,7 +422,7 @@ def main():
|
|||||||
' xmlns:xs="http://www.w3.org/2001/XMLSchema">\n'
|
' xmlns:xs="http://www.w3.org/2001/XMLSchema">\n'
|
||||||
'</SpreadsheetDocument>'
|
'</SpreadsheetDocument>'
|
||||||
)
|
)
|
||||||
write_text_with_bom(template_file_path, content)
|
write_xml_file(template_file_path, content)
|
||||||
|
|
||||||
elif template_type == "BinaryData":
|
elif template_type == "BinaryData":
|
||||||
with open(template_file_path, "wb") as f:
|
with open(template_file_path, "wb") as f:
|
||||||
@@ -431,7 +445,7 @@ def main():
|
|||||||
'\t</dataSource>\n'
|
'\t</dataSource>\n'
|
||||||
'</DataCompositionSchema>'
|
'</DataCompositionSchema>'
|
||||||
)
|
)
|
||||||
write_text_with_bom(template_file_path, content)
|
write_xml_file(template_file_path, content)
|
||||||
|
|
||||||
# --- 3. Modify root XML ---
|
# --- 3. Modify root XML ---
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,38 @@
|
|||||||
"preRun": [
|
"preRun": [
|
||||||
{
|
{
|
||||||
"script": "meta-compile/scripts/meta-compile",
|
"script": "meta-compile/scripts/meta-compile",
|
||||||
"input": { "type": "Catalog", "name": "Товары" },
|
"input": {
|
||||||
"args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" }
|
"type": "Catalog",
|
||||||
|
"name": "Товары"
|
||||||
|
},
|
||||||
|
"args": {
|
||||||
|
"-JsonPath": "{inputFile}",
|
||||||
|
"-OutputDir": "{workDir}"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"script": "cfe-init/scripts/cfe-init",
|
"script": "cfe-init/scripts/cfe-init",
|
||||||
"args": { "-Name": "Тест", "-OutputDir": "{workDir}/ext", "-ConfigPath": "{workDir}" }
|
"args": {
|
||||||
|
"-Name": "Тест",
|
||||||
|
"-OutputDir": "{workDir}/ext",
|
||||||
|
"-ConfigPath": "{workDir}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"params": { "extensionPath": "ext", "object": "Catalog.Товары" }
|
"params": {
|
||||||
|
"extensionPath": "ext",
|
||||||
|
"object": "Catalog.Товары"
|
||||||
|
},
|
||||||
|
"expect": {
|
||||||
|
"preserves": {
|
||||||
|
"file": "Ext/Catalogs/Товары.xml",
|
||||||
|
"bom": true,
|
||||||
|
"eol": "crlf",
|
||||||
|
"encoding": "UTF-8",
|
||||||
|
"finalNewline": false,
|
||||||
|
"noCR13": true,
|
||||||
|
"selfClose": "tight",
|
||||||
|
"noEmptyPairs": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,15 +13,27 @@
|
|||||||
"objectName": "МояОбработка"
|
"objectName": "МояОбработка"
|
||||||
},
|
},
|
||||||
"expect": {
|
"expect": {
|
||||||
"preserves": {
|
"preserves": [
|
||||||
"file": "МояОбработка.xml",
|
{
|
||||||
"bom": true,
|
"file": "МояОбработка.xml",
|
||||||
"eol": "crlf",
|
"bom": true,
|
||||||
"encoding": "UTF-8",
|
"eol": "crlf",
|
||||||
"finalNewline": false,
|
"encoding": "UTF-8",
|
||||||
"noCR13": true,
|
"finalNewline": false,
|
||||||
"selfClose": "tight",
|
"noCR13": true,
|
||||||
"noEmptyPairs": true
|
"selfClose": "tight",
|
||||||
}
|
"noEmptyPairs": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"file": "МояОбработка/Ext/Help.xml",
|
||||||
|
"bom": true,
|
||||||
|
"eol": "crlf",
|
||||||
|
"encoding": "UTF-8",
|
||||||
|
"finalNewline": false,
|
||||||
|
"noCR13": true,
|
||||||
|
"selfClose": "tight",
|
||||||
|
"noEmptyPairs": true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,18 +3,49 @@
|
|||||||
"preRun": [
|
"preRun": [
|
||||||
{
|
{
|
||||||
"script": "meta-compile/scripts/meta-compile",
|
"script": "meta-compile/scripts/meta-compile",
|
||||||
"input": { "type": "Catalog", "name": "Товары" },
|
"input": {
|
||||||
"args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" }
|
"type": "Catalog",
|
||||||
|
"name": "Товары"
|
||||||
|
},
|
||||||
|
"args": {
|
||||||
|
"-JsonPath": "{inputFile}",
|
||||||
|
"-OutputDir": "{workDir}"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"script": "subsystem-compile/scripts/subsystem-compile",
|
"script": "subsystem-compile/scripts/subsystem-compile",
|
||||||
"input": { "name": "Склад", "objects": ["Catalogs.Товары"] },
|
"input": {
|
||||||
"args": { "-DefinitionFile": "{inputFile}", "-OutputDir": "{workDir}" }
|
"name": "Склад",
|
||||||
|
"objects": [
|
||||||
|
"Catalogs.Товары"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"args": {
|
||||||
|
"-DefinitionFile": "{inputFile}",
|
||||||
|
"-OutputDir": "{workDir}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"params": { "ciPath": "Subsystems/Склад/CommandInterface" },
|
"params": {
|
||||||
|
"ciPath": "Subsystems/Склад/CommandInterface"
|
||||||
|
},
|
||||||
"input": [
|
"input": [
|
||||||
{ "operation": "place", "value": "{\"command\": \"Catalog.Товары\", \"group\": \"NavigationPanel.Important\"}" }
|
{
|
||||||
|
"operation": "place",
|
||||||
|
"value": "{\"command\": \"Catalog.Товары\", \"group\": \"NavigationPanel.Important\"}"
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"CreateIfMissing": true
|
"CreateIfMissing": true,
|
||||||
|
"expect": {
|
||||||
|
"preserves": {
|
||||||
|
"file": "Subsystems/Склад/CommandInterface",
|
||||||
|
"bom": true,
|
||||||
|
"eol": "crlf",
|
||||||
|
"encoding": "UTF-8",
|
||||||
|
"finalNewline": false,
|
||||||
|
"noCR13": true,
|
||||||
|
"selfClose": "tight",
|
||||||
|
"noEmptyPairs": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,27 @@
|
|||||||
"preRun": [
|
"preRun": [
|
||||||
{
|
{
|
||||||
"script": "epf-init/scripts/init",
|
"script": "epf-init/scripts/init",
|
||||||
"args": { "-Name": "МояОбработка", "-SrcDir": "{workDir}" }
|
"args": {
|
||||||
|
"-Name": "МояОбработка",
|
||||||
|
"-SrcDir": "{workDir}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"params": { "objectName": "МояОбработка", "templateName": "Макет", "templateType": "SpreadsheetDocument" }
|
"params": {
|
||||||
|
"objectName": "МояОбработка",
|
||||||
|
"templateName": "Макет",
|
||||||
|
"templateType": "SpreadsheetDocument"
|
||||||
|
},
|
||||||
|
"expect": {
|
||||||
|
"preserves": {
|
||||||
|
"file": "МояОбработка/Templates/Макет/Ext/Template.xml",
|
||||||
|
"bom": true,
|
||||||
|
"eol": "crlf",
|
||||||
|
"encoding": "UTF-8",
|
||||||
|
"finalNewline": false,
|
||||||
|
"noCR13": true,
|
||||||
|
"selfClose": "tight",
|
||||||
|
"noEmptyPairs": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user