import os import re import argparse import shutil # --- Konfiguracija skripte --- PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) # Predvideva, da je skripta v root direktoriju projekta TEMPLATES_DIR_NAME = "templates" LANGUAGES = ['en', 'si', 'mk'] HEADER_TEMPLATE_NAME = "header.html" FOOTER_TEMPLATE_NAME = "footer.html" # Označevalci, ki jih skripta išče v HTML datotekah HEADER_START_MARKER = "" HEADER_END_MARKER = "" FOOTER_START_MARKER = "" FOOTER_END_MARKER = "" # Placeholder za relativne poti v predlogah ROOT_PREFIX_PLACEHOLDER = "{{ROOT_PREFIX}}" # --- Pomožne funkcije --- def load_template(lang, template_type): """ Naloži vsebino predloge (header ali footer) za določen jezik. """ template_path = os.path.join(PROJECT_ROOT, TEMPLATES_DIR_NAME, lang, f"{template_type}.html") try: with open(template_path, 'r', encoding='utf-8') as f: content = f.read() # Preveri, ali predloga vsebuje označevalce, ki jih bo skripta uporabljala if template_type == 'header' and not (HEADER_START_MARKER in content and HEADER_END_MARKER in content): raise ValueError(f"Predloga za glavo '{template_path}' mora vsebovati '{HEADER_START_MARKER}' in '{HEADER_END_MARKER}'.") if template_type == 'footer' and not (FOOTER_START_MARKER in content and FOOTER_END_MARKER in content): raise ValueError(f"Predloga za nogo '{template_path}' mora vsebovati '{FOOTER_START_MARKER}' in '{FOOTER_END_MARKER}'.") return content except FileNotFoundError: print(f"Napaka: Predloga '{template_path}' ni najdena.") return None except ValueError as e: print(f"Napaka pri predlogi: {e}") return None except Exception as e: print(f"Nepredvidena napaka pri nalaganju predloge '{template_path}': {e}") return None def find_html_files(root_dir): """ Rekurzivno poišče vse HTML datoteke v določenem korenskem imeniku. Vrne seznam absolutnih poti do datotek. """ html_files = [] for dirpath, _, filenames in os.walk(root_dir): for filename in filenames: if filename.endswith(".html"): html_files.append(os.path.join(dirpath, filename)) return html_files def calculate_root_prefix(file_path): """ Izračuna relativno pot od dane HTML datoteke do korenskega imenika projekta. Npr. za /project_root/si/projects/article/index.html vrne '../../..' """ relative_path = os.path.relpath(file_path, PROJECT_ROOT) # Izloči ime datoteke in jezikovno mapo, da dobimo globino path_parts = relative_path.split(os.sep) # Odštej 1 za jezikovno mapo (npr. 'si') in 1 za samo datoteko 'index.html' # path_parts = ['si', 'projects', 'article', 'index.html'] -> depth = 3 # root_prefix = '../../..' depth = len(path_parts) - 1 # -1, ker ne štejemo 'index.html' if depth <= 0: return "./" # Datoteka je v korenski jezikovni mapi (npr. si/index.html) else: return "../" * depth def process_file(file_path, lang_templates, dry_run=False): """ Prebere HTML datoteko, nadomesti header in footer z vsebino predlog in zapiše spremenjeno datoteko. """ print(f"Obdelujem datoteko: {file_path}") try: with open(file_path, 'r', encoding='utf-8') as f: content = f.read() except Exception as e: print(f" Napaka pri branju datoteke '{file_path}': {e}") return original_content = content # Shrani originalno vsebino za primer, če se nič ne spremeni # Izlušči jezikovno kodo iz poti datoteke lang_code = file_path.split(os.sep)[-len(os.path.relpath(file_path, PROJECT_ROOT).split(os.sep))] # Pridobi predloge za trenutni jezik header_template = lang_templates.get(lang_code, {}).get('header') footer_template = lang_templates.get(lang_code, {}).get('footer') if not header_template or not footer_template: print(f" Opozorilo: Predloge za jezik '{lang_code}' niso naložene ali so nepopolne. Preskakujem.") return # Izračunaj root prefix za to datoteko root_prefix = calculate_root_prefix(file_path) # Pripravi predloge z ustreznim root prefixom formatted_header = header_template.replace(ROOT_PREFIX_PLACEHOLDER, root_prefix) formatted_footer = footer_template.replace(ROOT_PREFIX_PLACEHOLDER, root_prefix) # --- Zamenjava Headerja --- header_pattern = re.compile(rf"{re.escape(HEADER_START_MARKER)}.*?{re.escape(HEADER_END_MARKER)}", re.DOTALL) if header_pattern.search(content): # formatted_header že vsebuje START in END markerje content = header_pattern.sub(formatted_header, content) else: print(f" Opozorilo: Označevalcev za glavo (header) ni mogoče najti v '{file_path}'.") # --- Zamenjava Footerja --- footer_pattern = re.compile(rf"{re.escape(FOOTER_START_MARKER)}.*?{re.escape(FOOTER_END_MARKER)}", re.DOTALL) if footer_pattern.search(content): # formatted_footer že vsebuje START in END markerje content = footer_pattern.sub(formatted_footer, content) else: print(f" Opozorilo: Označevalcev za nogo (footer) ni mogoče najti v '{file_path}'.") if content != original_content: if dry_run: print(f" DRY RUN: Datoteka '{file_path}' bi bila spremenjena.") # Za dry run lahko izpišeš del spremenjene vsebine ali diff # print("--- Diff (prvih 20 vrstic) ---") # import difflib # diff = difflib.unified_diff(original_content.splitlines(keepends=True), content.splitlines(keepends=True), fromfile='original', tofile='modified') # for i, line in enumerate(diff): # if i >= 20: break # print(line.strip()) # print("-----------------------------") else: # Ustvari varnostno kopijo pred spremembami backup_path = file_path + ".bak" try: shutil.copy2(file_path, backup_path) print(f" Varnostna kopija ustvarjena: {backup_path}") except Exception as e: print(f" Napaka pri ustvarjanju varnostne kopije za '{file_path}': {e}") try: with open(file_path, 'w', encoding='utf-8') as f: f.write(content) print(f" Datoteka uspešno posodobljena: {file_path}") except Exception as e: print(f" Napaka pri zapisovanju v datoteko '{file_path}': {e}") else: print(f" Datoteka '{file_path}' je že posodobljena ali ni potrebovala sprememb.") # --- Glavna funkcija --- def main(): parser = argparse.ArgumentParser(description="Avtomatizirano posodabljanje headerja in footerja v HTML datotekah.") parser.add_argument("--dry-run", action="store_true", help="Izvede posodobitev, vendar ne zapisuje sprememb v datoteke.") args = parser.parse_args() # Naloži vse predloge za vse jezike all_lang_templates = {} for lang in LANGUAGES: header_template = load_template(lang, 'header') footer_template = load_template(lang, 'footer') if header_template and footer_template: all_lang_templates[lang] = {'header': header_template, 'footer': footer_template} else: print(f"Opozorilo: Predloge za jezik '{lang}' so nepopolne. Datoteke v tem jeziku ne bodo obdelane.") if not all_lang_templates: print("Ni naloženih veljavnih predlog za noben jezik. Skripta se ustavi.") return # Obdelaj HTML datoteke po jezikih for lang in LANGUAGES: if lang not in all_lang_templates: continue # Preskoči, če predloge za ta jezik niso bile uspešno naložene lang_dir = os.path.join(PROJECT_ROOT, lang) if not os.path.isdir(lang_dir): print(f"Opozorilo: Jezikovna mapa '{lang_dir}' ne obstaja. Preskakujem.") continue print(f"\n--- Začenjam obdelavo HTML datotek za jezik: {lang.upper()} ---") html_files = find_html_files(lang_dir) if not html_files: print(f" V mapi '{lang_dir}' ni najdenih HTML datotek.") continue for file_path in html_files: process_file(file_path, all_lang_templates, args.dry_run) print("\n--- Obdelava zaključena ---") if __name__ == "__main__": main()