provisioning-outreach/presentations/rust-laspalmas-250926/auroraframe/framework/optimizers/optimize-css.nu

153 lines
No EOL
5.1 KiB
Text

#!/usr/bin/env nu
# CSS optimization utilities
# Minify CSS content
export def minify_css [css_content: string, config: record] {
let minified = ($css_content
# Remove CSS comments /* ... */
| str replace -ar '/\*[\s\S]*?\*/' ''
# Remove unnecessary whitespace
| str replace -ar '\s+' ' '
# Remove spaces around specific characters
| str replace -ar '\s*{\s*' '{'
| str replace -ar '\s*}\s*' '}'
| str replace -ar '\s*:\s*' ':'
| str replace -ar '\s*;\s*' ';'
| str replace -ar '\s*,\s*' ','
| str replace -ar '\s*>\s*' '>'
| str replace -ar '\s*\+\s*' '+'
| str replace -ar '\s*~\s*' '~'
# Remove trailing semicolons before }
| str replace -ar ';\s*}' '}'
# Remove empty rules
| str replace -ar '[^}]+\{\s*\}' ''
# Trim
| str trim
)
$minified
}
# Extract critical CSS from modules
export def extract_critical_css [modules: list<string>, css_dir: string] {
$modules | each { |module|
let module_path = $"($css_dir)/($module)"
if ($module_path | path exists) {
open $module_path
} else {
""
}
} | str join "\n"
}
# Combine CSS modules
export def combine_css_modules [modules: list<string>, css_dir: string] {
$modules | each { |module|
let module_path = $"($css_dir)/($module)"
if ($module_path | path exists) {
let content = (open $module_path)
$"/* === ($module) === */\n($content)\n"
} else {
$"/* WARNING: ($module) not found */\n"
}
} | str join "\n"
}
# Optimize CSS custom properties
export def optimize_css_variables [css_content: string] {
# This could be extended to:
# - Remove unused CSS custom properties
# - Optimize color values (hex shorthand)
# - Combine similar rules
$css_content
}
# Generate CSS source map (for debugging)
export def generate_css_sourcemap [original_modules: list<string>, minified_css: string] {
let sourcemap = {
version: 3,
sources: $original_modules,
names: [],
mappings: "",
file: "main.min.css"
}
$sourcemap | to json
}
# Analyze CSS for optimization opportunities
export def analyze_css [css_content: string] {
let lines = ($css_content | lines)
let total_lines = ($lines | length)
let comment_lines = ($lines | where ($it | str starts-with "/*") | length)
let empty_lines = ($lines | where ($it | str trim) == "" | length)
let rule_lines = ($lines | where ($it | str contains "{") | length)
{
total_lines: $total_lines,
comment_lines: $comment_lines,
empty_lines: $empty_lines,
rule_lines: $rule_lines,
content_lines: ($total_lines - $comment_lines - $empty_lines),
size_bytes: ($css_content | str length),
estimated_minified_size: (($css_content | str length) * 0.6 | math round)
}
}
# Split CSS into critical and non-critical based on selectors
export def split_critical_css [css_content: string] {
let lines = ($css_content | lines)
# Define critical selectors (above-the-fold)
let critical_selectors = [
"body", "html", ".poster", ".title", ".header",
".ocean-tech-bg", ".top-logo", ".main-title",
"@keyframes gradient-shift", "@keyframes progressBar"
]
mut critical_rules = []
mut non_critical_rules = []
mut current_rule = ""
mut in_critical_rule = false
for line in $lines {
if ($line | str contains "{") {
# Start of a new rule
let is_critical = ($critical_selectors | any { |sel| $line | str contains $sel })
$in_critical_rule = $is_critical
$current_rule = $line
} else if ($line | str contains "}") {
# End of rule
$current_rule = ($current_rule + "\n" + $line)
if $in_critical_rule {
$critical_rules = ($critical_rules | append $current_rule)
} else {
$non_critical_rules = ($non_critical_rules | append $current_rule)
}
$current_rule = ""
} else {
# Inside rule
$current_rule = ($current_rule + "\n" + $line)
}
}
{
critical: ($critical_rules | str join "\n"),
non_critical: ($non_critical_rules | str join "\n")
}
}
# CSS performance metrics
export def css_performance_metrics [css_content: string] {
let selectors = ($css_content | str replace -ar '\{[^}]*\}' '' | lines | where ($it | str trim) != "")
let properties = ($css_content | str replace -ar '[^{]*\{|\}[^{]*' '' | split row ";" | where ($it | str trim) != "")
{
total_selectors: ($selectors | length),
total_properties: ($properties | length),
avg_properties_per_rule: (if ($selectors | length) > 0 { (($properties | length) / ($selectors | length) | math round -p 1) } else { 0 }),
complex_selectors: ($selectors | where ($it | str contains " ") | length),
id_selectors: ($selectors | where ($it | str contains "#") | length),
class_selectors: ($selectors | where ($it | str contains ".") | length)
}
}