Web

CSS minifier

CSS made small and ready for the browsers you support (lightningcss): minified with rules merged, vendor prefixes added and nesting and new syntax lowered for a browserslist query, and errors reported by line.

Version 1.0.0 · 4 functions · 1 crate

#css#performance#assets#browsers

Functions

What use css_minify.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use css_minify, css_for_browsers from css_minify (Quillo 0.6).

css_minify(css: str) → stror an error

css minified: spaces and comments gone, values shortened, rules merged. Gives an error value with the line and column for CSS that does not parse.

css_for_browsers(css: str, browsers: str, minify: bool) → stror an error

css made to work in the browsers browsers names (a browserslist query: "defaults", "> 0.5%, last 2 versions, not dead", "safari >= 13"): vendor prefixes added, nesting, range media queries, rgb(r g b / a) and other new syntax written the old way where those browsers need it. minify false keeps it readable.

css_minify_file(in_path: str, out_path: str, browsers: str) → anyor an error

Reads a stylesheet, makes it for browsers (empty: only minified) and writes it minified to out_path: { bytes_in, bytes_out, saved_percent }.

css_check(css: str) → any

What is wrong in a stylesheet: { ok, errors: [{ message, line, column }] }, lines from 1. Rules and declarations a browser would drop are listed too, while the rest is still read.

Get it

$ quillo install css_minify               # css_minify.qwer into this folder$ quillo install css_minify --example     # and its example, css_minify.qwe

Or with curl:

$ curl -O https://quillolang.org/plugins/files/css_minify.qwer$ curl -O https://quillolang.org/plugins/files/css_minify.qwe$ curl -O https://quillolang.org/plugins/files/css_minify_sample.css

Then, in your program, all of it or only what you call:

main.qwe
use css_minify.qweruse css_minify, css_for_browsers from css_minify      // Quillo 0.6: only these

It uses this crate, which cargo fetches the first time the plugin is built:

[dependencies]
lightningcss = { version = "1.0.0-alpha.72", default-features = false, features = ["browserslist"] }

Example

css_minify.qwe
// A site's stylesheet built at start: minified for production and made to work in older// Safari, with a check that reports mistakes by line.////   quillo run css_minify.qwe      then open http://localhost:8080/app.css and http://localhost:8080/demouse "css_minify.qwer"let BROWSERS = "> 0.5%, last 2 versions, safari >= 13, not dead"let BUILT = css_minify_file("css_minify_sample.css", "data/app.min.css", BROWSERS)?route GET /app.css = file("data/app.min.css")route GET /demo = {    built: BUILT,    minified: css_minify(".a { color: #ff0000; margin: 0px 0px 0px 0px }\n.b { color: #ff0000; margin: 0 }")?,    old_safari: css_for_browsers(".card { user-select: none; backdrop-filter: blur(8px); & .title { color: rgb(46 125 50 / 50%) } }", "safari 12", false)?,    check: css_check(".ok { color: red }\n.bad { color: red;; width: 10px }\n.broken { color: }\n@media screen and (min-width: { }"),}
$ quillo run css_minify.qwe$ curl 'localhost:8080/demo'$ curl 'localhost:8080/app.css'

Source

css_minify.qwer
//! CSS made small and ready for the browsers you support (lightningcss): minified with rules merged, vendor prefixes added and modern syntax (nesting, range media queries, new color functions) lowered for a browserslist query, and checked for errors with their line and column.//! version: 1.0.0//!//! [dependencies]//! lightningcss = { version = "1.0.0-alpha.72", default-features = false, features = ["browserslist"] }use lightningcss::printer::PrinterOptions;use lightningcss::stylesheet::{MinifyOptions, ParserOptions, StyleSheet};use lightningcss::targets::{Browsers, Targets};use serde_json::{json, Value};use std::sync::{Arc, RwLock};fn targets(query: &str) -> Result<Targets, String> {    if query.trim().is_empty() {        return Ok(Targets::default());    }    let browsers = Browsers::from_browserslist(query.split(',').map(str::trim)).map_err(|e| format!("browserslist `{}`: {}", query, e))?;    Ok(Targets::from(browsers))}fn process(css: &str, query: &str, minify: bool, filename: &str) -> Result<String, String> {    let t = targets(query)?;    let opts = ParserOptions { filename: filename.to_string(), ..ParserOptions::default() };    let mut sheet = StyleSheet::parse(css, opts).map_err(|e| e.to_string())?;    sheet.minify(MinifyOptions { targets: t, ..MinifyOptions::default() }).map_err(|e| e.to_string())?;    let out = sheet.to_css(PrinterOptions { minify, targets: t, ..PrinterOptions::default() }).map_err(|e| e.to_string())?;    Ok(out.code)}/// `css` minified: spaces and comments gone, values shortened, rules merged. Gives an error value with the line and column/// for CSS that does not parse.pub fn css_minify(css: &str) -> Result<String, String> {    process(css, "", true, "style.css")}/// `css` made to work in the browsers `browsers` names (a browserslist query: "defaults", "> 0.5%, last 2 versions, not dead",/// "safari >= 13"): vendor prefixes added, nesting, range media queries, `rgb(r g b / a)` and other new syntax written the old/// way where those browsers need it. `minify` false keeps it readable.pub fn css_for_browsers(css: &str, browsers: &str, minify: bool) -> Result<String, String> {    process(css, browsers, minify, "style.css")}/// Reads a stylesheet, makes it for `browsers` (empty: only minified) and writes it minified to `out_path`:/// `{ bytes_in, bytes_out, saved_percent }`.pub fn css_minify_file(in_path: &str, out_path: &str, browsers: &str) -> Result<Value, String> {    let css = std::fs::read_to_string(in_path).map_err(|e| format!("{}: {}", in_path, e))?;    let out = process(&css, browsers, true, in_path)?;    if let Some(dir) = std::path::Path::new(out_path).parent() {        std::fs::create_dir_all(dir).ok();    }    std::fs::write(out_path, &out).map_err(|e| format!("{}: {}", out_path, e))?;    let saved = if css.is_empty() { 0.0 } else { (1.0 - out.len() as f64 / css.len() as f64) * 100.0 };    Ok(json!({ "bytes_in": css.len(), "bytes_out": out.len(), "saved_percent": (saved * 10.0).round() / 10.0 }))}/// What is wrong in a stylesheet: `{ ok, errors: [{ message, line, column }] }`, lines from 1. Rules and declarations a browser/// would drop are listed too, while the rest is still read.pub fn css_check(css: &str) -> Value {    let warnings = Arc::new(RwLock::new(Vec::new()));    let opts = ParserOptions { filename: "style.css".into(), error_recovery: true, warnings: Some(warnings.clone()), ..ParserOptions::default() };    let mut errors: Vec<Value> = vec![];    match StyleSheet::parse(css, opts) {        Ok(_) => {}        Err(e) => errors.push(json!({ "message": e.kind.to_string(), "line": e.loc.as_ref().map(|l| l.line + 1), "column": e.loc.as_ref().map(|l| l.column) })),    }    if let Ok(w) = warnings.read() {        for e in w.iter() {            errors.push(json!({ "message": e.kind.to_string(), "line": e.loc.as_ref().map(|l| l.line + 1), "column": e.loc.as_ref().map(|l| l.column) }));        }    }    json!({ "ok": errors.is_empty(), "errors": errors })}
Thread
87Useful? Like it, or add to its thread below.

Thread 0 posts

On CSS minifier: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.