1+ use atty:: Stream ;
12use clap:: { ArgGroup , Parser } ;
23use lightningcss:: bundler:: { Bundler , FileProvider } ;
34use lightningcss:: stylesheet:: { MinifyOptions , ParserOptions , PrinterOptions , StyleSheet } ;
@@ -18,9 +19,9 @@ static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc;
1819 . args( & [ "targets" , "browserslist" ] ) ,
1920) ) ]
2021struct CliArgs {
21- /// Target CSS file
22+ /// Target CSS file (default: stdin)
2223 #[ clap( value_parser) ]
23- input_file : String ,
24+ input_file : Option < String > ,
2425 /// Destination file for the output
2526 #[ clap( short, long, group = "output_file" , value_parser) ]
2627 output_file : Option < String > ,
@@ -67,13 +68,36 @@ struct SourceMapJson<'a> {
6768
6869pub fn main ( ) -> Result < ( ) , std:: io:: Error > {
6970 let cli_args = CliArgs :: parse ( ) ;
70- let source = fs:: read_to_string ( & cli_args. input_file ) ?;
71-
7271 let project_root = std:: env:: current_dir ( ) ?;
73- let absolute_path = fs:: canonicalize ( & cli_args. input_file ) ?;
74- let filename = pathdiff:: diff_paths ( absolute_path, & project_root) . unwrap ( ) ;
75- let filename = filename. to_str ( ) . unwrap ( ) ;
7672
73+ // If we're given an input file, read from it and adjust its name.
74+ //
75+ // If we're not given an input file and stdin was redirected, read
76+ // from it and create a fake name. Return an error if stdin was not
77+ // redirected (otherwise the program will hang waiting for input).
78+ //
79+ let ( filename, source) = match & cli_args. input_file {
80+ Some ( f) => {
81+ let absolute_path = fs:: canonicalize ( f) ?;
82+ let filename = pathdiff:: diff_paths ( absolute_path, & project_root) . unwrap ( ) ;
83+ let filename = filename. to_string_lossy ( ) . into_owned ( ) ;
84+ let contents = fs:: read_to_string ( f) ?;
85+ ( filename, contents)
86+ }
87+ None => {
88+ // Don't silently wait for input if stdin was not redirected.
89+ if atty:: is ( Stream :: Stdin ) {
90+ return Err ( io:: Error :: new (
91+ io:: ErrorKind :: Other ,
92+ "Not reading from stdin as it was not redirected" ,
93+ ) ) ;
94+ }
95+ let filename = format ! ( "stdin-{}" , std:: process:: id( ) ) ;
96+ let contents = io:: read_to_string ( io:: stdin ( ) ) ?;
97+ ( filename, contents)
98+ }
99+ } ;
100+
77101 let css_modules = if let Some ( _) = cli_args. css_modules {
78102 let pattern = if let Some ( pattern) = cli_args. css_modules_pattern . as_ref ( ) {
79103 match lightningcss:: css_modules:: Pattern :: parse ( pattern) {
@@ -121,13 +145,13 @@ pub fn main() -> Result<(), std::io::Error> {
121145
122146 let mut stylesheet = if cli_args. bundle {
123147 let mut bundler = Bundler :: new ( & fs, source_map. as_mut ( ) , options) ;
124- bundler. bundle ( Path :: new ( & cli_args . input_file ) ) . unwrap ( )
148+ bundler. bundle ( Path :: new ( & filename ) ) . unwrap ( )
125149 } else {
126150 if let Some ( sm) = & mut source_map {
127151 sm. add_source ( & filename) ;
128152 let _ = sm. set_source_content ( 0 , & source) ;
129153 }
130- options. filename = filename. to_owned ( ) ;
154+ options. filename = filename;
131155 StyleSheet :: parse ( & source, options) . unwrap ( )
132156 } ;
133157
0 commit comments