#!/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 '' '' # 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 '\s*
' '
'
# 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 = $""
let updated_html = ($html_content
| str replace '' $"($css_style)\n"
)
$updated_html
}
# Add async CSS loading
export def add_async_css [html_content: string, css_file: string] {
let async_css = $'
'
let updated_html = ($html_content
| str replace '' $"($async_css)\n"
)
$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 ']+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 = $'
]+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 = '
'
let updated_html = ($html_content
| str replace '' $'
($performance_meta)'
)
$updated_html
}
# Add preconnect links for external resources
export def add_preconnect_links [html_content: string] {
let preconnect_links = '
'
let updated_html = ($html_content
| str replace '' $'
($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 '
]*loading=)[^>]*>')
for img_tag in $img_without_loading {
let original_tag = $img_tag.capture0
let lazy_tag = ($original_tag | str replace '
'
}
# 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 ']+rel="stylesheet"[^>]*>' '' | str length),
js_files: ($html_content | str replace -ar '