#!/usr/bin/env python3 # add-template v1.5 — Add template to 1C object # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import os import re import sys import uuid from lxml import etree NSMAP = {"md": "http://v8.1c.ru/8.3/MDClasses"} TYPE_MAP = { "HTML": {"TemplateType": "HTMLDocument", "Ext": ".html"}, "Text": {"TemplateType": "TextDocument", "Ext": ".txt"}, "SpreadsheetDocument": {"TemplateType": "SpreadsheetDocument", "Ext": ".xml"}, "BinaryData": {"TemplateType": "BinaryData", "Ext": ".bin"}, "DataCompositionSchema": {"TemplateType": "DataCompositionSchema", "Ext": ".xml"}, } def save_xml_with_bom(tree, path): """Save XML tree to file with UTF-8 BOM.""" xml_bytes = etree.tostring(tree, xml_declaration=True, encoding="UTF-8") xml_bytes = xml_bytes.replace(b"", b'') if not xml_bytes.endswith(b"\n"): xml_bytes += b"\n" with open(path, "wb") as f: f.write(b"\xef\xbb\xbf") f.write(xml_bytes) def write_text_with_bom(path, text): """Write text to file with UTF-8 BOM.""" with open(path, "w", encoding="utf-8-sig") as f: f.write(text) def detect_format_version(d): while d: cfg_path = os.path.join(d, "Configuration.xml") if os.path.isfile(cfg_path): with open(cfg_path, "r", encoding="utf-8-sig") as f: head = f.read(2000) m = re.search(r']+version="(\d+\.\d+)"', head) if m: return m.group(1) parent = os.path.dirname(d) if parent == d: break d = parent return "2.17" def main(): sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") parser = argparse.ArgumentParser(description="Add template to 1C object", allow_abbrev=False) parser.add_argument("-ObjectName", "-ProcessorName", required=True) parser.add_argument("-TemplateName", required=True) parser.add_argument("-TemplateType", required=True, choices=["HTML", "Text", "SpreadsheetDocument", "BinaryData", "DataCompositionSchema"]) parser.add_argument("-Synonym", default=None) parser.add_argument("-SrcDir", default="src") parser.add_argument("-SetMainSKD", action="store_true") args = parser.parse_args() object_name = args.ObjectName template_name = args.TemplateName template_type = args.TemplateType synonym = args.Synonym if args.Synonym is not None else template_name src_dir = args.SrcDir set_main_skd = args.SetMainSKD tmpl = TYPE_MAP[template_type] format_version = detect_format_version(os.path.abspath(src_dir)) # --- Checks --- object_type_folders = [ "Reports", "DataProcessors", "Documents", "Catalogs", "InformationRegisters", "AccumulationRegisters", "ChartsOfCharacteristicTypes", "ChartsOfAccounts", "ChartsOfCalculationTypes", "BusinessProcesses", "Tasks", "ExchangePlans", ] root_xml_path = os.path.join(src_dir, f"{object_name}.xml") if not os.path.exists(root_xml_path): candidates = [] for folder in object_type_folders: probe = os.path.join(src_dir, folder, f"{object_name}.xml") if os.path.exists(probe): candidates.append(os.path.join(src_dir, folder)) if len(candidates) == 1: src_dir = candidates[0] root_xml_path = os.path.join(src_dir, f"{object_name}.xml") print(f"[INFO] SrcDir расширен до: {src_dir}") elif len(candidates) > 1: print(f"Объект '{object_name}' найден в нескольких подпапках: {', '.join(candidates)}", file=sys.stderr) print(f"Укажи SrcDir явно", file=sys.stderr) sys.exit(1) else: print(f"Корневой файл объекта не найден: {root_xml_path}", file=sys.stderr) print(f"Ожидается: /.xml", file=sys.stderr) print(f"Подсказка: SrcDir должен указывать на папку типа объектов (например Reports), а не на корень конфигурации", file=sys.stderr) sys.exit(1) processor_dir = os.path.join(src_dir, object_name) templates_dir = os.path.join(processor_dir, "Templates") template_meta_path = os.path.join(templates_dir, f"{template_name}.xml") if os.path.exists(template_meta_path): print(f"Макет уже существует: {template_meta_path}", file=sys.stderr) sys.exit(1) # --- Create directories --- template_ext_dir = os.path.join(templates_dir, template_name, "Ext") os.makedirs(template_ext_dir, exist_ok=True) # --- 1. Template metadata (Templates/.xml) --- template_uuid = str(uuid.uuid4()) template_meta_xml = ( '\n' '\n' f'\t\n' '' ) write_text_with_bom(template_meta_path, template_meta_xml) # --- 2. Template content (Templates//Ext/Template.) --- template_file_path = os.path.join(template_ext_dir, f"Template{tmpl['Ext']}") if template_type == "HTML": content = ( '\n' '\n' '\n' '\t\n' '\t\n' '\n' '\n' '\n' '' ) write_text_with_bom(template_file_path, content) elif template_type == "Text": write_text_with_bom(template_file_path, "") elif template_type == "SpreadsheetDocument": content = ( '\n' '\n' '' ) write_text_with_bom(template_file_path, content) elif template_type == "BinaryData": with open(template_file_path, "wb") as f: pass # empty file elif template_type == "DataCompositionSchema": content = ( '\n' '\n' '\t\n' '\t\tИсточникДанных1\n' '\t\tLocal\n' '\t\n' '' ) write_text_with_bom(template_file_path, content) # --- 3. Modify root XML --- root_xml_full = os.path.abspath(root_xml_path) parser_xml = etree.XMLParser(remove_blank_text=False) tree = etree.parse(root_xml_full, parser_xml) root = tree.getroot() ns = "http://v8.1c.ru/8.3/MDClasses" child_objects = root.find(".//md:ChildObjects", NSMAP) if child_objects is None: print(f"Не найден элемент ChildObjects в {root_xml_path}", file=sys.stderr) sys.exit(1) # Add