diff --git a/README.md b/README.md index a9ad502c..ef9e70e0 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ An extremely fast CSS parser, transformer, and minifier written in Rust. Use it - Removing default property sub-values which will be inferred by browsers. - Many micro-optimizations, e.g. converting to shorter units, removing unnecessary quotation marks, etc. - **Vendor prefixing** – Lightning CSS accepts a list of browser targets, and automatically adds (and removes) vendor prefixes. +- **Browserslist configuration** – Lightning CSS supports opt-in browserslist configuration discovery to resolve browser targets and integrate with your existing tools and config setup. - **Syntax lowering** – Lightning CSS parses modern CSS syntax, and generates more compatible output where needed, based on browser targets. - CSS Nesting (draft spec) - Custom media queries (draft spec) @@ -197,6 +198,46 @@ To see all of the available options, use the `--help` argument: npx lightningcss --help ``` +#### Browserslist configuration + +If the `--browserslist` option is provided, then `lightningcss` finds browserslist configuration, +selects queries by environment and loads the resulting queries as targets. + +Configuration discovery and targets resolution is modeled after the original `browserslist` nodeJS package. +The configuration is resolved in the following order: + +- If a `BROWSERSLIST` environment variable is present, then load targets from its value. This is analog to the `--targets` CLI option. + _Example:_ `BROWSERSLIST="firefox ESR" lightningcss [OPTIONS] ` +- If a `BROWSERSLIST_CONFIG` environment variable is present, then resolve the file at the provided path. + Then parse and use targets from `package.json` or any browserslist configuration file pointed to by the environment variable. + _Example:_ `BROWSERSLIST_CONFIG="../config/browserslist" lightningcss [OPTIONS] ` +- If none of the above apply, then find, parse and use targets from the first `browserslist`, `.browserslistrc` + or `package.json` configuration file in any parent directory. + +Browserslist configuration files may contain sections denoted by angular brackets `[]`. +Use these to specify different targets for different environments. +Targets which are not placed in a section are added to `defaults` and used if no section applies matches the environment. + +_Example:_ + +``` +# Defaults, applied when no other section matches the provided environment. +firefox ESR + +[staging] +# Targets applied only to the staging environment. +samsung >= 4 +``` + +When using parsed configuration from `browserslist`, `.browserslistrc` or `package.json` configuration files, +the environment determined by + +- the `BROWSERSLIST_ENV` environment variable if present, +- otherwise the `NODE_ENV` environment variable if present, +- otherwise `production` is used. + +If no targets are found for the resulting environment, then the `defaults` configuration section is used. + ### Error recovery By default, Lightning CSS is strict, and will error when parsing an invalid rule or declaration. However, sometimes you may encounter a third party library that you can't easily modify, which unintentionally contains invalid syntax, or IE-specific hacks. In these cases, you can enable the `errorRecovery` option (or `--error-recovery` CLI flag). This will skip over invalid rules and declarations, omitting them in the output, and producing a warning instead of an error. You should also open an issue or PR to fix the issue in the library if possible. @@ -207,7 +248,7 @@ By default, Lightning CSS is strict, and will error when parsing an invalid rule performance and build size charts ``` -$ node bench.js bootstrap-4.css +$ node bench.js bootstrap-4.css cssnano: 544.809ms 159636 bytes @@ -229,7 +270,7 @@ lightningcss: 1.973ms 23666 bytes -$ node bench.js tailwind.css +$ node bench.js tailwind.css cssnano: 2.198s 1925626 bytes diff --git a/src/main.rs b/src/main.rs index e62f588c..b95e9908 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use clap::Parser; +use clap::{ArgGroup, Parser}; use lightningcss::bundler::{Bundler, FileProvider}; use lightningcss::stylesheet::{MinifyOptions, ParserOptions, PrinterOptions, StyleSheet}; use lightningcss::targets::Browsers; @@ -13,6 +13,10 @@ static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] +#[clap(group( + ArgGroup::new("targets-resolution") + .args(&["targets", "browserslist"]), +))] struct CliArgs { /// Target CSS file #[clap(value_parser)] @@ -46,6 +50,8 @@ struct CliArgs { #[clap(short, long, value_parser)] targets: Vec, #[clap(long, value_parser)] + browserslist: bool, + #[clap(long, value_parser)] error_recovery: bool, } @@ -124,11 +130,14 @@ pub fn main() -> Result<(), std::io::Error> { StyleSheet::parse(&source, options).unwrap() }; - let targets = if cli_args.targets.is_empty() { - None - } else { + let targets = if !cli_args.targets.is_empty() { Browsers::from_browserslist(cli_args.targets).unwrap() + } else if cli_args.browserslist { + Browsers::load_browserslist().unwrap() + } else { + None }; + stylesheet .minify(MinifyOptions { targets, diff --git a/src/targets.rs b/src/targets.rs index cddfc1ad..c87c92e1 100644 --- a/src/targets.rs +++ b/src/targets.rs @@ -42,11 +42,40 @@ impl Browsers { ) -> Result