FASE 7e: CSS Inline Extraction + Minificación
- Extraído CSS inline de 15 templates POS + 13 templates Dashboard - CSS movido a archivos .css externos en pos/static/css/ y dashboard/ - Generados .min.css vía minify-assets.sh - Nginx auto-serve transparente para .min.css - Tests: 73/73 pasando - Script: scripts/extract-inline-css.py
This commit is contained in:
110
scripts/extract-inline-css.py
Normal file
110
scripts/extract-inline-css.py
Normal file
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Extract inline <style> blocks from HTML templates into external CSS files.
|
||||
|
||||
Replaces each <style>...</style> block with a <link rel="stylesheet"> tag.
|
||||
This allows browsers to cache CSS across page navigations and dramatically
|
||||
reduces HTML payload size.
|
||||
|
||||
Usage:
|
||||
python3 extract-inline-css.py
|
||||
"""
|
||||
|
||||
import glob
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def extract_css_from_template(html_path, css_output_dir, css_url_prefix):
|
||||
"""Extract <style> blocks from an HTML file into an external CSS file.
|
||||
|
||||
Returns the modified HTML content.
|
||||
"""
|
||||
with open(html_path, 'r', encoding='utf-8') as f:
|
||||
html = f.read()
|
||||
|
||||
style_blocks = list(re.finditer(
|
||||
r'<style[^>]*>(.*?)</style>',
|
||||
html,
|
||||
re.DOTALL | re.IGNORECASE
|
||||
))
|
||||
|
||||
if not style_blocks:
|
||||
return html # No inline CSS to extract
|
||||
|
||||
# Extract all CSS content
|
||||
css_parts = []
|
||||
for m in style_blocks:
|
||||
css = m.group(1).strip()
|
||||
if css:
|
||||
css_parts.append(css)
|
||||
|
||||
if not css_parts:
|
||||
return html
|
||||
|
||||
# Write external CSS file
|
||||
name = Path(html_path).stem
|
||||
css_filename = f"{name}.css"
|
||||
css_path = Path(css_output_dir) / css_filename
|
||||
css_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
combined_css = '\n\n'.join(css_parts)
|
||||
with open(css_path, 'w', encoding='utf-8') as f:
|
||||
f.write(f"/* Extracted from {Path(html_path).name} */\n\n")
|
||||
f.write(combined_css)
|
||||
f.write('\n')
|
||||
|
||||
# Replace first <style> block with <link>, remove the rest
|
||||
link_tag = f'<link rel="stylesheet" href="{css_url_prefix}{css_filename}">'
|
||||
new_html = html[:style_blocks[0].start()] + link_tag + html[style_blocks[0].end():]
|
||||
|
||||
# Remove remaining style blocks (they were concatenated into the CSS file)
|
||||
for m in reversed(style_blocks[1:]):
|
||||
new_html = new_html[:m.start()] + new_html[m.end():]
|
||||
|
||||
return new_html
|
||||
|
||||
|
||||
def process_directory(html_dir, css_output_dir, css_url_prefix):
|
||||
"""Process all HTML files in a directory."""
|
||||
templates = sorted(glob.glob(f"{html_dir}/*.html"))
|
||||
total_saved = 0
|
||||
|
||||
for html_path in templates:
|
||||
new_html = extract_css_from_template(html_path, css_output_dir, css_url_prefix)
|
||||
|
||||
# Write back the modified HTML
|
||||
with open(html_path, 'w', encoding='utf-8') as f:
|
||||
f.write(new_html)
|
||||
|
||||
original_size = Path(html_path).stat().st_size
|
||||
total_saved += original_size - len(new_html.encode('utf-8'))
|
||||
name = Path(html_path).name
|
||||
print(f" {name}: extracted CSS -> {css_url_prefix}{Path(html_path).stem}.css")
|
||||
|
||||
return total_saved
|
||||
|
||||
|
||||
def main():
|
||||
print("=== Extracting inline CSS from POS templates ===")
|
||||
saved_pos = process_directory(
|
||||
'/home/Autopartes/pos/templates',
|
||||
'/home/Autopartes/pos/static/css',
|
||||
'/pos/static/css/'
|
||||
)
|
||||
|
||||
print("\n=== Extracting inline CSS from Dashboard templates ===")
|
||||
saved_dash = process_directory(
|
||||
'/home/Autopartes/dashboard',
|
||||
'/home/Autopartes/dashboard',
|
||||
'' # Dashboard CSS is in the same directory
|
||||
)
|
||||
|
||||
total_saved_kb = (saved_pos + saved_dash) / 1024
|
||||
print(f"\n=== Done ===")
|
||||
print(f"Total HTML payload reduced by ~{total_saved_kb:.0f} KB")
|
||||
print(f"POS templates: ~{saved_pos/1024:.0f} KB")
|
||||
print(f"Dashboard templates: ~{saved_dash/1024:.0f} KB")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user