provisioning-outreach/presentations/rust-laspalmas-250926/auroraframe/scripts/optimize-html.nu

226 lines
8.1 KiB
Text
Raw Permalink Normal View History

#!/usr/bin/env nu
# HTML optimization utilities
# Minify HTML content
export def minify_html [html_content: string, config: record] {
let minified = ($html_content
# Remove HTML comments (but keep IE conditionals)
| str replace -ar '<!--(?!\s*\[if)[^>]*-->' ''
# Remove unnecessary whitespace between tags
| str replace -ar '>\s+<' '><'
# Remove extra whitespace in text content (preserve single spaces)
| str replace -ar '\s+' ' '
# Remove whitespace around block elements
| str replace -ar '\s*<(div|section|article|header|footer|main|nav)\s*' '<$1'
| str replace -ar '\s*</(div|section|article|header|footer|main|nav)>\s*' '</$1>'
# Remove optional closing tags (basic list)
| str replace -ar '</li>\s*<li>' '</li><li>'
| str replace -ar '</p>\s*<p>' '</p><p>'
# Remove unnecessary quotes around attributes (safe cases)
| str replace -ar '=([a-zA-Z0-9-_]+)(\s|>)' '=$1$2'
# Trim
| str trim
)
$minified
}
# Inline critical CSS into HTML
export def inline_critical_css [html_content: string, critical_css: string] {
# Find the head section and inject critical CSS
let css_style = $"<style>($critical_css)</style>"
let updated_html = ($html_content
| str replace '</head>' $"($css_style)\n</head>"
)
$updated_html
}
# Add async CSS loading
export def add_async_css [html_content: string, css_file: string] {
let async_css = $'<link rel="preload" href="($css_file)" as="style" onload="this.onload=null;this.rel=\'stylesheet\'">
<noscript><link rel="stylesheet" href="($css_file)"></noscript>'
let updated_html = ($html_content
| str replace '</head>' $"($async_css)\n</head>"
)
$updated_html
}
# Inline small SVGs
export def inline_small_svgs [html_content: string, svg_dir: string, max_size: int] {
# Find SVG references and inline if small enough
let svg_refs = ($html_content | parse -r '<img[^>]+src="([^"]+\.svg)"[^>]*>')
mut updated_html = $html_content
for svg_ref in $svg_refs {
let svg_path = $svg_ref.capture0
let full_path = $"($svg_dir)/($svg_path)"
if ($full_path | path exists) {
let svg_content = (open $full_path)
if ($svg_content | str length) <= $max_size {
# Inline the SVG by replacing the img tag
let img_pattern = $'<img[^>]+src="($svg_path)"[^>]*>'
$updated_html = ($updated_html | str replace -r $img_pattern $svg_content)
}
}
}
$updated_html
}
# Optimize meta tags
export def optimize_meta_tags [html_content: string] {
# Add performance and SEO meta tags
let performance_meta = '<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="theme-color" content="#00d4ff">
<meta name="description" content="Provisioning - Automatización de Infraestructura con Rust | Rust Las Palmas Meetup 2025">'
let updated_html = ($html_content
| str replace '<meta charset="utf-8">' $'<meta charset="utf-8">
($performance_meta)'
)
$updated_html
}
# Add preconnect links for external resources
export def add_preconnect_links [html_content: string] {
let preconnect_links = '<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>'
let updated_html = ($html_content
| str replace '</title>' $'</title>
($preconnect_links)'
)
$updated_html
}
# Remove unnecessary attributes
export def remove_unnecessary_attributes [html_content: string] {
let cleaned = ($html_content
# Remove type="text/css" (default for style tags)
| str replace -ar '\s+type="text/css"' ''
# Remove type="text/javascript" (default for script tags in HTML5)
| str replace -ar '\s+type="text/javascript"' ''
# Remove method="get" (default for forms)
| str replace -ar '\s+method="get"' ''
)
$cleaned
}
# Optimize images (basic attributes)
export def optimize_img_attributes [html_content: string] {
# Add loading="lazy" to images below the fold
# Add loading="lazy" to images that don't already have it
mut optimized = $html_content
# Find img tags that don't have loading attribute
let img_without_loading = ($html_content | parse -r '<img(?![^>]*loading=)[^>]*>')
for img_tag in $img_without_loading {
let original_tag = $img_tag.capture0
let lazy_tag = ($original_tag | str replace '<img' '<img loading="lazy"')
$optimized = ($optimized | str replace $original_tag $lazy_tag)
}
$optimized
}
# Generate Content Security Policy
export def generate_csp [config: record] {
let csp = "default-src 'self'; style-src 'self' 'unsafe-inline' fonts.googleapis.com; font-src fonts.gstatic.com; img-src 'self' data:; script-src 'none';"
$'<meta http-equiv="Content-Security-Policy" content="($csp)">'
}
# Analyze HTML for optimization opportunities
export def analyze_html [html_content: string] {
let size = ($html_content | str length)
let lines = ($html_content | lines | length)
let tags = ($html_content | str replace -ar '<[^>]+>' '' | str length)
let tag_count = (($size - $tags) / 10) # Rough estimate
let external_resources = {
css_files: ($html_content | str replace -ar '<link[^>]+rel="stylesheet"[^>]*>' '' | str length),
js_files: ($html_content | str replace -ar '<script[^>]+src[^>]*>' '' | str length),
images: ($html_content | str replace -ar '<img[^>]+>' '' | str length)
}
{
size_bytes: $size,
lines: $lines,
estimated_tags: $tag_count,
external_css: (($size - $external_resources.css_files) > 0),
external_js: (($size - $external_resources.js_files) > 0),
images: (($size - $external_resources.images) > 0),
minification_potential: (($size * 0.3) | math round)
}
}
# Validate HTML structure (basic)
export def validate_html_structure [html_content: string] {
let has_doctype = (($html_content | str starts-with "<!DOCTYPE") or ($html_content | str contains "<!DOCTYPE"))
let has_html_tag = ($html_content | str contains "<html")
let has_head = ($html_content | str contains "<head>")
let has_body = ($html_content | str contains "<body")
let has_title = ($html_content | str contains "<title>")
{
valid_structure: ($has_doctype and $has_html_tag and $has_head and $has_body and $has_title),
has_doctype: $has_doctype,
has_html_tag: $has_html_tag,
has_head: $has_head,
has_body: $has_body,
has_title: $has_title
}
}
# Extract critical above-the-fold content
export def extract_critical_html [html_content: string] {
# Extract content likely to be above the fold
let critical_selectors = [
".header", ".main-title", ".title", ".ocean-tech-bg",
".top-logo", ".provisioning-logo"
]
# This is a simplified approach - extract elements with critical classes
let critical_elements = ($critical_selectors | each { |selector|
let class_name = ($selector | str replace '.' '')
$html_content | parse -r $'<[^>]*class="[^"]*($class_name)[^"]*"[^>]*>.*?</[^>]+>'
} | flatten)
# Return the original content for now (simplified)
$html_content
}
# Generate HTML performance hints
export def generate_performance_hints [html_content: string] {
mut hints = []
# Check for common performance issues
if ($html_content | str contains 'style=') {
$hints = ($hints | append "Consider moving inline styles to CSS files")
}
if ($html_content | str contains '<script') and not ($html_content | str contains 'defer') {
$hints = ($hints | append "Consider adding 'defer' to script tags")
}
if ($html_content | str contains '<img') and not ($html_content | str contains 'loading="lazy"') {
$hints = ($hints | append "Consider adding 'loading=lazy' to images below the fold")
}
if not ($html_content | str contains 'preconnect') {
$hints = ($hints | append "Consider adding preconnect links for external resources")
}
$hints
}