diff --git a/Cargo.lock b/Cargo.lock index 074cb22b..ce9d90e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,12 +262,6 @@ dependencies = [ "syn", ] -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "convert_case" version = "0.5.0" @@ -382,19 +376,6 @@ dependencies = [ "matches", ] -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case 0.4.0", - "proc-macro2", - "quote", - "rustc_version", - "syn", -] - [[package]] name = "difflib" version = "0.4.0" @@ -674,6 +655,7 @@ version = "1.0.0-alpha.38" dependencies = [ "assert_cmd", "assert_fs", + "atty", "bitflags", "browserslist-rs", "clap", @@ -807,7 +789,7 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1be75210f300e9fbf386ccac1c8eaaed23410e2f7f7aa9295b78c436a172ef51" dependencies = [ - "convert_case 0.5.0", + "convert_case", "napi-derive-backend", "proc-macro2", "quote", @@ -820,7 +802,7 @@ version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ba4800264fac8a7726b208d5dd4c6d637d1027d73b026061a69d3339a0a930" dependencies = [ - "convert_case 0.5.0", + "convert_case", "once_cell", "proc-macro2", "quote", @@ -913,7 +895,6 @@ version = "0.24.9" dependencies = [ "bitflags", "cssparser", - "derive_more", "fxhash", "log", "phf", @@ -1316,15 +1297,6 @@ dependencies = [ "syn", ] -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - [[package]] name = "ryu" version = "1.0.9" @@ -1377,12 +1349,6 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" -[[package]] -name = "semver" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0486718e92ec9a68fbed73bb5ef687d71103b142595b406835649bebd33f72c7" - [[package]] name = "serde" version = "1.0.136" diff --git a/Cargo.toml b/Cargo.toml index 9adf63ef..dd4d28ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ crate-type = ["rlib"] default = ["bundler", "grid", "nodejs", "sourcemap"] browserslist = ["browserslist-rs"] bundler = ["dashmap", "sourcemap", "rayon"] -cli = ["clap", "serde_json", "browserslist", "jemallocator"] +cli = ["atty", "clap", "serde_json", "browserslist", "jemallocator"] grid = [] jsonschema = ["schemars", "serde", "parcel_selectors/jsonschema"] nodejs = ["dep:serde"] @@ -51,6 +51,7 @@ lazy_static = "1.4.0" const-str = "0.3.1" pathdiff = "0.2.1" # CLI deps +atty = { version = "0.2", optional = true } clap = { version = "3.0.6", features = ["derive"], optional = true } browserslist-rs = { version = "0.7.0", optional = true } rayon = { version = "1.5.1", optional = true } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 4a6c2662..c032b573 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.63.0" +channel = "1.65.0" components = ["rustfmt", "clippy"] diff --git a/src/main.rs b/src/main.rs index 3e7c2ae2..f8ad803b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use atty::Stream; use clap::{ArgGroup, Parser}; use lightningcss::bundler::{Bundler, FileProvider}; use lightningcss::stylesheet::{MinifyOptions, ParserOptions, PrinterOptions, StyleSheet}; @@ -18,9 +19,9 @@ static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; .args(&["targets", "browserslist"]), ))] struct CliArgs { - /// Target CSS file + /// Target CSS file (default: stdin) #[clap(value_parser)] - input_file: String, + input_file: Option, /// Destination file for the output #[clap(short, long, group = "output_file", value_parser)] output_file: Option, @@ -67,13 +68,36 @@ struct SourceMapJson<'a> { pub fn main() -> Result<(), std::io::Error> { let cli_args = CliArgs::parse(); - let source = fs::read_to_string(&cli_args.input_file)?; - let project_root = std::env::current_dir()?; - let absolute_path = fs::canonicalize(&cli_args.input_file)?; - let filename = pathdiff::diff_paths(absolute_path, &project_root).unwrap(); - let filename = filename.to_str().unwrap(); + // If we're given an input file, read from it and adjust its name. + // + // If we're not given an input file and stdin was redirected, read + // from it and create a fake name. Return an error if stdin was not + // redirected (otherwise the program will hang waiting for input). + // + let (filename, source) = match &cli_args.input_file { + Some(f) => { + let absolute_path = fs::canonicalize(f)?; + let filename = pathdiff::diff_paths(absolute_path, &project_root).unwrap(); + let filename = filename.to_string_lossy().into_owned(); + let contents = fs::read_to_string(f)?; + (filename, contents) + } + None => { + // Don't silently wait for input if stdin was not redirected. + if atty::is(Stream::Stdin) { + return Err(io::Error::new( + io::ErrorKind::Other, + "Not reading from stdin as it was not redirected", + )); + } + let filename = format!("stdin-{}", std::process::id()); + let contents = io::read_to_string(io::stdin())?; + (filename, contents) + } + }; + let css_modules = if let Some(_) = cli_args.css_modules { let pattern = if let Some(pattern) = cli_args.css_modules_pattern.as_ref() { match lightningcss::css_modules::Pattern::parse(pattern) { @@ -121,13 +145,13 @@ pub fn main() -> Result<(), std::io::Error> { let mut stylesheet = if cli_args.bundle { let mut bundler = Bundler::new(&fs, source_map.as_mut(), options); - bundler.bundle(Path::new(&cli_args.input_file)).unwrap() + bundler.bundle(Path::new(&filename)).unwrap() } else { if let Some(sm) = &mut source_map { sm.add_source(&filename); let _ = sm.set_source_content(0, &source); } - options.filename = filename.to_owned(); + options.filename = filename; StyleSheet::parse(&source, options).unwrap() }; diff --git a/tests/cli_integration_tests.rs b/tests/cli_integration_tests.rs index fff378ea..4fe1ef7a 100644 --- a/tests/cli_integration_tests.rs +++ b/tests/cli_integration_tests.rs @@ -154,16 +154,6 @@ fn valid_input_file() -> Result<(), Box> { Ok(()) } -#[test] -fn no_input_file() -> Result<(), Box> { - let mut cmd = Command::cargo_bin("lightningcss")?; - cmd.assert().failure().stderr(predicate::str::contains( - "The following required arguments were not provided:\n ", - )); - - Ok(()) -} - #[test] fn empty_input_file() -> Result<(), Box> { let file = assert_fs::NamedTempFile::new("test.css")?;