Skip to content

Commit

Permalink
CLI support for piping (#380)
Browse files Browse the repository at this point in the history
  • Loading branch information
oylenshpeegul authored Jan 3, 2023
1 parent 50c066b commit 3a5a30a
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 58 deletions.
40 changes: 3 additions & 37 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand All @@ -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 }
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[toolchain]
channel = "1.63.0"
channel = "1.65.0"
components = ["rustfmt", "clippy"]
42 changes: 33 additions & 9 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use atty::Stream;
use clap::{ArgGroup, Parser};
use lightningcss::bundler::{Bundler, FileProvider};
use lightningcss::stylesheet::{MinifyOptions, ParserOptions, PrinterOptions, StyleSheet};
Expand All @@ -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<String>,
/// Destination file for the output
#[clap(short, long, group = "output_file", value_parser)]
output_file: Option<String>,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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()
};

Expand Down
10 changes: 0 additions & 10 deletions tests/cli_integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,6 @@ fn valid_input_file() -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}

#[test]
fn no_input_file() -> Result<(), Box<dyn std::error::Error>> {
let mut cmd = Command::cargo_bin("lightningcss")?;
cmd.assert().failure().stderr(predicate::str::contains(
"The following required arguments were not provided:\n <INPUT_FILE>",
));

Ok(())
}

#[test]
fn empty_input_file() -> Result<(), Box<dyn std::error::Error>> {
let file = assert_fs::NamedTempFile::new("test.css")?;
Expand Down

0 comments on commit 3a5a30a

Please sign in to comment.