This commit is contained in:
1 parent
eb3b804dbc
commit
d9ed2a449f
5 files changed
+97
-169
No files matched your search
+88
-146
@@ -9,7 +9,14 @@ PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) # Predvideva, da je sk
|
||||
|
||||
IMAGES_DIR_NAME = "images"
|
||||
ORIGINAL_IMAGES_SUBDIR_NAME = "original" # Podmapa znotraj IMAGES_DIR_NAME
|
||||
HTML_ROOT_DIRS = ['en', 'si', 'mk'] # Jezikovne mape, kjer se nahajajo HTML datoteke za posodobitev
|
||||
|
||||
# Mape, v katerih skripta išče datoteke za posodobitev referenc
|
||||
DIRECTORIES_TO_SCAN = ['en', 'si', 'mk', 'css']
|
||||
# Dodatne datoteke v korenski mapi za preverjanje
|
||||
FILES_IN_ROOT_TO_SCAN = ['main.js']
|
||||
|
||||
# Končnice datotek, v katerih iščemo in posodabljamo reference na slike
|
||||
FILE_EXTENSIONS_TO_UPDATE = ['.html', '.css', '.js']
|
||||
|
||||
WEBP_QUALITY = 80 # Kakovost kompresije za WebP (0-100). Višja številka = boljša kakovost, večja datoteka.
|
||||
MAX_IMAGE_DIMENSION = 1920 # Maksimalna dimenzija (širina ali višina) za pomanjšanje, če je slika večja. Ohranijo se razmerja. Če je 0, se ne pomanjšuje.
|
||||
@@ -32,30 +39,18 @@ def optimize_image(image_path, output_path, quality, max_dim, dry_run=False):
|
||||
with Image.open(image_path) as img:
|
||||
original_size = img.size
|
||||
|
||||
# Pretvorba v RGB, če je potrebno (WebP ne podpira npr. paletnih slik brez RGB pretvorbe)
|
||||
if img.mode in ('P', 'LA', 'RGBA'):
|
||||
if img.mode == 'RGBA':
|
||||
# Za RGBA slike, ki so shranjene v WebP, se shrani z alfa kanalom.
|
||||
# Če želimo brez alfa, bi morali ustvariti belo ozadje:
|
||||
# new_img = Image.new("RGB", img.size, (255, 255, 255))
|
||||
# new_img.paste(img, mask=img.split()[3])
|
||||
# img = new_img
|
||||
pass # Ohranimo RGBA za WebP z alfa kanalom
|
||||
else:
|
||||
img = img.convert("RGB")
|
||||
if img.mode != 'RGBA':
|
||||
img = img.convert("RGBA")
|
||||
|
||||
# Pomanjšanje slike, če je prevelika
|
||||
if max_dim > 0 and (img.width > max_dim or img.height > max_dim):
|
||||
print(f" Pomanjšujem sliko {os.path.basename(image_path)} iz {img.width}x{img.height} ...", end="")
|
||||
img.thumbnail((max_dim, max_dim), Image.LANCZOS) # Lanczos za kakovostno pomanjšanje
|
||||
img.thumbnail((max_dim, max_dim), Image.LANCZOS)
|
||||
print(f" na {img.width}x{img.height}")
|
||||
else:
|
||||
print(f" Obdelujem sliko {os.path.basename(image_path)} ({img.width}x{img.height})...", end="")
|
||||
|
||||
if not dry_run:
|
||||
# Shrani v WebP
|
||||
# Za RGBA WebP slike, `lossless=True` ali `quality` določita kompresijo.
|
||||
# `method` (0-6) nadzoruje hitrost/kakovost kodiranja. Višja = počasneje/boljše.
|
||||
img.save(output_path, "webp", quality=quality, method=6)
|
||||
print(f" Shrani v {os.path.basename(output_path)} (kvaliteta: {quality}).")
|
||||
else:
|
||||
@@ -69,111 +64,77 @@ def optimize_image(image_path, output_path, quality, max_dim, dry_run=False):
|
||||
print(f" Napaka pri optimizaciji slike '{image_path}': {e}")
|
||||
return False
|
||||
|
||||
def update_html_references(html_file_path, old_filename_with_ext, new_filename_with_ext, dry_run=False):
|
||||
def update_file_references(file_path, old_filename_with_ext, new_filename_with_ext, dry_run=False):
|
||||
"""
|
||||
Poišče staro ime slike v HTML datoteki in ga zamenja z novim imenom WebP.
|
||||
Poišče staro ime slike v datoteki (HTML, CSS, JS) in ga zamenja z novim imenom WebP.
|
||||
"""
|
||||
try:
|
||||
with open(html_file_path, 'r', encoding='utf-8') as f:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
except Exception as e:
|
||||
print(f" Napaka pri branju HTML datoteke '{html_file_path}': {e}")
|
||||
print(f" Napaka pri branju datoteke '{file_path}': {e}")
|
||||
return False
|
||||
|
||||
original_content = content
|
||||
changed = False
|
||||
# Uporabimo preprosto zamenjavo niza, ki je varna, saj zamenjujemo celotno ime datoteke z končnico.
|
||||
# To bo delovalo za poti v narekovajih (HTML, JS) in v url() (CSS).
|
||||
if old_filename_with_ext in content:
|
||||
content = content.replace(old_filename_with_ext, new_filename_with_ext)
|
||||
|
||||
# Izdelava regularnega izraza, ki bo iskal staro ime datoteke znotraj poti
|
||||
# in ga zamenjal z novim. Poskrbimo, da ujemanje ni preveč široko.
|
||||
# Iščemo vzorce kot so src=".../staro_ime.ext", url('.../staro_ime.ext'), itd.
|
||||
|
||||
# Prvi del ujame začetek atributa/URL-ja (npr. src=" ali url()...)
|
||||
# Drugi del ujame *katerokoli pot* pred imenom datoteke (npr. ../images/)
|
||||
# Tretji del ujame staro ime datoteke z razširitvijo
|
||||
# Četrti del ujame zaključek atributa/URL-ja
|
||||
|
||||
# Regex pattern to match filename.ext in various HTML/CSS contexts
|
||||
# Example: 1-logo.png -> 1-logo.webp
|
||||
# It must replace only the filename, not parts of other filenames.
|
||||
|
||||
# This pattern is specifically designed to handle common cases where image names appear
|
||||
# in src/srcset/href attributes or url() CSS functions.
|
||||
# It uses named groups for clarity and robustness.
|
||||
# Group `before_path` captures anything before the actual filename to ensure we only
|
||||
# target image references and not random text.
|
||||
# Group `path` captures the relative path (e.g., ../images/).
|
||||
if content != original_content:
|
||||
if not dry_run:
|
||||
backup_path = file_path + ".bak"
|
||||
try:
|
||||
# Preverimo, ali datoteka obstaja, preden jo kopiramo
|
||||
if os.path.exists(file_path):
|
||||
shutil.copy2(file_path, backup_path)
|
||||
except Exception as e:
|
||||
print(f" Napaka pri ustvarjanju varnostne kopije za '{file_path}': {e}")
|
||||
return False
|
||||
|
||||
# We need to escape the old filename for regex safety.
|
||||
escaped_old_filename = re.escape(old_filename_with_ext)
|
||||
|
||||
# Pattern to find old_filename_with_ext in common image contexts.
|
||||
# This pattern looks for the filename preceded by either:
|
||||
# - `src="` or `srcset="` or `href="` followed by any path characters
|
||||
# - `url(` followed by optional quotes and any path characters
|
||||
# It attempts to capture the path prefix to preserve it.
|
||||
|
||||
# This is a complex regex. Let's simplify the strategy slightly to avoid over-matching.
|
||||
# Iterate through potential contexts and replace just the filename within that context.
|
||||
|
||||
# Contexts: src="...", srcset="...", url('...'), url("..."), url(...)
|
||||
|
||||
patterns = [
|
||||
# For src, srcset, href attributes (usually contain path/filename.ext)
|
||||
re.compile(rf'(?P<attr>src|srcset|href)=["\'](?P<path>.*?){escaped_old_filename}(?P<end>["\'])', re.IGNORECASE),
|
||||
# For url() in CSS (can be with single, double quotes or no quotes)
|
||||
re.compile(rf'(url\([\'"]*)(?P<path>.*?){escaped_old_filename}([\'"]*\))', re.IGNORECASE)
|
||||
]
|
||||
|
||||
for pattern in patterns:
|
||||
content, num_replacements = pattern.subn(
|
||||
lambda m: f"{m.group('attr')}=\"{m.group('path')}{new_filename_with_ext}\"" if 'attr' in m.groupdict() else f"{m.group(1)}{m.group('path')}{new_filename_with_ext}{m.group(3)}",
|
||||
content
|
||||
)
|
||||
if num_replacements > 0:
|
||||
changed = True
|
||||
print(f" Zamenjano {num_replacements} referenc za '{old_filename_with_ext}' z '{new_filename_with_ext}' v '{html_file_path}'.")
|
||||
|
||||
if changed and not dry_run:
|
||||
backup_path = html_file_path + ".bak"
|
||||
try:
|
||||
shutil.copy2(html_file_path, backup_path)
|
||||
# print(f" Varnostna kopija ustvarjena: {backup_path}") # Odkomentiraj za več izpisa
|
||||
except Exception as e:
|
||||
print(f" Napaka pri ustvarjanju varnostne kopije za '{html_file_path}': {e}")
|
||||
return False
|
||||
|
||||
try:
|
||||
with open(html_file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
# print(f" HTML datoteka posodobljena: {html_file_path}") # Odkomentiraj za več izpisa
|
||||
try:
|
||||
with open(file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
print(f" Posodobljene reference za '{old_filename_with_ext}' v '{os.path.relpath(file_path, PROJECT_ROOT)}'.")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f" Napaka pri zapisovanju v datoteko '{file_path}': {e}")
|
||||
return False
|
||||
else:
|
||||
print(f" DRY RUN: Reference za '{old_filename_with_ext}' bi bile posodobljene v '{os.path.relpath(file_path, PROJECT_ROOT)}'.")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f" Napaka pri zapisovanju v HTML datoteko '{html_file_path}': {e}")
|
||||
return False
|
||||
elif changed and dry_run:
|
||||
print(f" DRY RUN: HTML datoteka '{html_file_path}' bi bila posodobljena (reference za '{old_filename_with_ext}' z '{new_filename_with_ext}').")
|
||||
return True # Return true in dry_run if changes would have occurred
|
||||
else:
|
||||
# print(f" Ni referenc za '{old_filename_with_ext}' v '{html_file_path}'.") # Odkomentiraj za več izpisa
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def find_html_files(root_dir):
|
||||
def find_files_to_update(scan_dirs, root_files):
|
||||
"""
|
||||
Rekurzivno poišče vse HTML datoteke v določenem korenskem imeniku.
|
||||
Vrne seznam absolutnih poti do datotek.
|
||||
Rekurzivno poišče vse datoteke z ustreznimi končnicami v podanih mapah.
|
||||
"""
|
||||
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
|
||||
found_files = []
|
||||
# Najprej poišči datoteke v navedenih mapah
|
||||
for directory in scan_dirs:
|
||||
dir_path = os.path.join(PROJECT_ROOT, directory)
|
||||
if os.path.isdir(dir_path):
|
||||
for dirpath, _, filenames in os.walk(dir_path):
|
||||
for filename in filenames:
|
||||
if any(filename.endswith(ext) for ext in FILE_EXTENSIONS_TO_UPDATE):
|
||||
found_files.append(os.path.join(dirpath, filename))
|
||||
else:
|
||||
print(f"Opozorilo: Mapa za skeniranje '{dir_path}' ne obstaja. Preskakujem.")
|
||||
|
||||
# Nato dodaj posamezne datoteke iz korenske mape
|
||||
for filename in root_files:
|
||||
file_path = os.path.join(PROJECT_ROOT, filename)
|
||||
if os.path.isfile(file_path):
|
||||
found_files.append(file_path)
|
||||
|
||||
# Vrne unikaten, sortiran seznam poti
|
||||
return sorted(list(set(found_files)))
|
||||
|
||||
# --- Glavna funkcija ---
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Skripta za optimizacijo slik (pretvorba v WebP) in posodobitev HTML referenc.")
|
||||
parser = argparse.ArgumentParser(description="Skripta za optimizacijo slik (pretvorba v WebP) in posodobitev referenc v HTML, CSS in JS datotekah.")
|
||||
parser.add_argument("--dry-run", action="store_true", help="Izvede operacije, vendar ne spreminja datotek in ne premika originalnih slik.")
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -185,19 +146,18 @@ def main():
|
||||
return
|
||||
|
||||
if not args.dry_run:
|
||||
# Ustvari mapo za originalne slike, če ne obstaja
|
||||
os.makedirs(original_images_full_path, exist_ok=True)
|
||||
print(f"Mapa za originalne slike: '{original_images_full_path}' (ustvarjena, če ni obstajala).")
|
||||
else:
|
||||
print(f"DRY RUN: Mapa za originalne slike bi bila '{original_images_full_path}'.")
|
||||
|
||||
|
||||
optimized_images_map = [] # Seznam slovarjev: {'old_name': 'slika.jpg', 'new_name': 'slika.webp', 'old_full_path': ..., 'new_full_path': ...}
|
||||
optimized_images_map = []
|
||||
|
||||
print("\n--- ZAČETEK OPTIMIZACIJE SLIK ---")
|
||||
for filename in os.listdir(images_full_path):
|
||||
if filename == ORIGINAL_IMAGES_SUBDIR_NAME:
|
||||
continue # Preskoči mapo za originalne slike
|
||||
continue
|
||||
|
||||
file_path = os.path.join(images_full_path, filename)
|
||||
|
||||
@@ -213,27 +173,14 @@ def main():
|
||||
new_filename = f"{name}.webp"
|
||||
new_file_path = os.path.join(images_full_path, new_filename)
|
||||
|
||||
# Preveri, če WebP slika že obstaja in je starejša od originalne
|
||||
if os.path.exists(new_file_path) and os.path.getmtime(new_file_path) > os.path.getmtime(file_path):
|
||||
print(f" WebP različica '{new_filename}' že obstaja in je novejša od originala. Preskakujem optimizacijo.")
|
||||
# Vseeno jo dodaj v mapo za posodobitev referenc
|
||||
optimized_images_map.append({
|
||||
'old_name': filename,
|
||||
'new_name': new_filename,
|
||||
'old_full_path': file_path,
|
||||
'new_full_path': new_file_path
|
||||
})
|
||||
optimized_images_map.append({'old_name': filename, 'new_name': new_filename})
|
||||
continue
|
||||
|
||||
if optimize_image(file_path, new_file_path, WEBP_QUALITY, MAX_IMAGE_DIMENSION, args.dry_run):
|
||||
optimized_images_map.append({
|
||||
'old_name': filename,
|
||||
'new_name': new_filename,
|
||||
'old_full_path': file_path,
|
||||
'new_full_path': new_file_path
|
||||
})
|
||||
optimized_images_map.append({'old_name': filename, 'new_name': new_filename})
|
||||
if not args.dry_run:
|
||||
# Premakni originalno sliko v 'original' mapo
|
||||
try:
|
||||
shutil.move(file_path, os.path.join(original_images_full_path, filename))
|
||||
print(f" Originalna slika premaknjena: '{filename}' -> '{ORIGINAL_IMAGES_SUBDIR_NAME}/'.")
|
||||
@@ -244,45 +191,40 @@ def main():
|
||||
|
||||
else:
|
||||
print(f" Preskakujem datoteko (ni slika za optimizacijo): '{filename}'.")
|
||||
else:
|
||||
print(f" Preskakujem (ni datoteka): '{filename}'.")
|
||||
|
||||
if not optimized_images_map:
|
||||
print("\nNi slik za optimizacijo ali pa so že optimizirane. Preskakujem posodabljanje HTML referenc.")
|
||||
print("\nNi slik za optimizacijo ali pa so že optimizirane. Preskakujem posodabljanje referenc.")
|
||||
print("\n--- OPTIMIZACIJA SLIK ZAKLJUČENA ---")
|
||||
return
|
||||
|
||||
print("\n--- ZAČETEK POSODABLJANJA HTML REFERENC ---")
|
||||
print("\n--- ZAČETEK POSODABLJANJA REFERENC V DATOTEKAH ---")
|
||||
|
||||
all_html_files = []
|
||||
for lang_dir_name in HTML_ROOT_DIRS:
|
||||
lang_full_path = os.path.join(PROJECT_ROOT, lang_dir_name)
|
||||
if os.path.isdir(lang_full_path):
|
||||
all_html_files.extend(find_html_files(lang_full_path))
|
||||
else:
|
||||
print(f"Opozorilo: Jezikovna mapa '{lang_full_path}' ne obstaja. Preskakujem iskanje HTML datotek v njej.")
|
||||
all_files_to_update = find_files_to_update(DIRECTORIES_TO_SCAN, FILES_IN_ROOT_TO_SCAN)
|
||||
|
||||
if not all_html_files:
|
||||
print("Ni najdenih HTML datotek za posodobitev referenc.")
|
||||
if not all_files_to_update:
|
||||
print("Ni najdenih datotek za posodobitev referenc (.html, .css, .js).")
|
||||
print("\n--- OPTIMIZACIJA SLIK ZAKLJUČENA ---")
|
||||
return
|
||||
|
||||
updated_html_files_count = 0
|
||||
for html_file in all_html_files:
|
||||
file_changed = False
|
||||
updated_files_count = 0
|
||||
processed_files = set()
|
||||
|
||||
for file_path in all_files_to_update:
|
||||
if file_path in processed_files:
|
||||
continue
|
||||
|
||||
file_changed_in_this_run = False
|
||||
for img_info in optimized_images_map:
|
||||
old_name = img_info['old_name']
|
||||
new_name = img_info['new_name']
|
||||
|
||||
# Kliče update_html_references in preveri, ali je bila datoteka spremenjena
|
||||
if update_html_references(html_file, old_name, new_name, args.dry_run):
|
||||
file_changed = True
|
||||
if update_file_references(file_path, img_info['old_name'], img_info['new_name'], args.dry_run):
|
||||
file_changed_in_this_run = True
|
||||
|
||||
if file_changed:
|
||||
updated_html_files_count += 1
|
||||
# print(f" Posodobljene reference v: {html_file}") # Odkomentiraj za več izpisa
|
||||
if file_changed_in_this_run:
|
||||
updated_files_count += 1
|
||||
|
||||
processed_files.add(file_path)
|
||||
|
||||
print(f"\nPosodobljenih je bilo {updated_html_files_count} HTML datotek (vključno z DRY RUN).")
|
||||
print(f"\nPregledanih je bilo {len(all_files_to_update)} datotek.")
|
||||
print(f"Posodobljenih je bilo {updated_files_count} datotek (vključno z DRY RUN).")
|
||||
print("\n--- OPTIMIZACIJA SLIK ZAKLJUČENA ---")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in new issue
Block a user