143 lines
4.7 KiB
Python
143 lines
4.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Asset build script for Kobelly's Base website
|
|
Handles CSS and JS minification with cache busting
|
|
"""
|
|
|
|
import os
|
|
import hashlib
|
|
import shutil
|
|
from datetime import datetime
|
|
from cssmin import cssmin
|
|
from jsmin import jsmin
|
|
|
|
def get_file_hash(filepath):
|
|
"""Generate MD5 hash of file content for cache busting"""
|
|
with open(filepath, 'rb') as f:
|
|
return hashlib.md5(f.read()).hexdigest()[:8]
|
|
|
|
def minify_css(input_file, output_file):
|
|
"""Minify CSS file"""
|
|
try:
|
|
with open(input_file, 'r', encoding='utf-8') as f:
|
|
css_content = f.read()
|
|
|
|
minified_css = cssmin(css_content)
|
|
|
|
with open(output_file, 'w', encoding='utf-8') as f:
|
|
f.write(minified_css)
|
|
|
|
print(f"✓ CSS minified: {input_file} → {output_file}")
|
|
return True
|
|
except Exception as e:
|
|
print(f"✗ Error minifying CSS {input_file}: {e}")
|
|
return False
|
|
|
|
def minify_js(input_file, output_file):
|
|
"""Minify JavaScript file"""
|
|
try:
|
|
with open(input_file, 'r', encoding='utf-8') as f:
|
|
js_content = f.read()
|
|
|
|
minified_js = jsmin(js_content)
|
|
|
|
with open(output_file, 'w', encoding='utf-8') as f:
|
|
f.write(minified_js)
|
|
|
|
print(f"✓ JS minified: {input_file} → {output_file}")
|
|
return True
|
|
except Exception as e:
|
|
print(f"✗ Error minifying JS {input_file}: {e}")
|
|
return False
|
|
|
|
def create_cache_busted_assets():
|
|
"""Create cache-busted versions of assets"""
|
|
static_dir = 'static'
|
|
css_dir = os.path.join(static_dir, 'css')
|
|
js_dir = os.path.join(static_dir, 'js')
|
|
|
|
# Ensure directories exist
|
|
os.makedirs(css_dir, exist_ok=True)
|
|
os.makedirs(js_dir, exist_ok=True)
|
|
|
|
# CSS files
|
|
css_files = [
|
|
('main.css', 'main.min.css')
|
|
]
|
|
|
|
# JS files
|
|
js_files = [
|
|
('main.js', 'main.min.js')
|
|
]
|
|
|
|
print("🔨 Building assets...")
|
|
print(f"📅 Build time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
print()
|
|
|
|
# Process CSS files
|
|
for input_file, output_file in css_files:
|
|
input_path = os.path.join(css_dir, input_file)
|
|
output_path = os.path.join(css_dir, output_file)
|
|
|
|
if os.path.exists(input_path):
|
|
if minify_css(input_path, output_path):
|
|
# Generate cache-busted filename
|
|
file_hash = get_file_hash(output_path)
|
|
cache_busted_name = f"main.{file_hash}.min.css"
|
|
cache_busted_path = os.path.join(css_dir, cache_busted_name)
|
|
|
|
# Copy minified file to cache-busted version
|
|
shutil.copy2(output_path, cache_busted_path)
|
|
print(f"✓ Cache-busted CSS created: {cache_busted_name}")
|
|
else:
|
|
print(f"⚠️ CSS file not found: {input_path}")
|
|
|
|
print()
|
|
|
|
# Process JS files
|
|
for input_file, output_file in js_files:
|
|
input_path = os.path.join(js_dir, input_file)
|
|
output_path = os.path.join(js_dir, output_file)
|
|
|
|
if os.path.exists(input_path):
|
|
if minify_js(input_path, output_path):
|
|
# Generate cache-busted filename
|
|
file_hash = get_file_hash(output_path)
|
|
cache_busted_name = f"main.{file_hash}.min.js"
|
|
cache_busted_path = os.path.join(js_dir, cache_busted_name)
|
|
|
|
# Copy minified file to cache-busted version
|
|
shutil.copy2(output_path, cache_busted_path)
|
|
print(f"✓ Cache-busted JS created: {cache_busted_name}")
|
|
else:
|
|
print(f"⚠️ JS file not found: {input_path}")
|
|
|
|
print()
|
|
print("🎉 Asset build completed!")
|
|
|
|
def clean_old_assets():
|
|
"""Clean old cache-busted assets"""
|
|
static_dir = 'static'
|
|
css_dir = os.path.join(static_dir, 'css')
|
|
js_dir = os.path.join(static_dir, 'js')
|
|
|
|
# Remove old cache-busted files
|
|
for directory in [css_dir, js_dir]:
|
|
if os.path.exists(directory):
|
|
for filename in os.listdir(directory):
|
|
if filename.startswith('main.') and filename.endswith('.min.css') or filename.endswith('.min.js'):
|
|
if not filename in ['main.min.css', 'main.min.js']: # Keep the base minified files
|
|
filepath = os.path.join(directory, filename)
|
|
os.remove(filepath)
|
|
print(f"🗑️ Removed old asset: {filename}")
|
|
|
|
if __name__ == '__main__':
|
|
import sys
|
|
|
|
if len(sys.argv) > 1 and sys.argv[1] == 'clean':
|
|
print("🧹 Cleaning old assets...")
|
|
clean_old_assets()
|
|
print("✓ Cleanup completed!")
|
|
else:
|
|
clean_old_assets()
|
|
create_cache_busted_assets() |