11use clap:: Parser ;
22use parcel_css:: stylesheet:: { MinifyOptions , ParserOptions , PrinterOptions , StyleSheet } ;
3- use std:: { ffi, fs, io, path} ;
43use serde:: Serialize ;
4+ use std:: { ffi, fs, io, path} ;
55
66#[ derive( Parser , Debug ) ]
77#[ clap( author, about, long_about = None ) ]
88struct CliArgs {
9- /// Target CSS file
10- input_file : String ,
11- /// Destination file for the output
12- #[ clap( short, long, group = "output_file" ) ]
13- output_file : Option < String > ,
14- /// Minify the output
15- #[ clap( short, long) ]
16- minify : bool ,
17- /// Enable parsing CSS nesting
18- #[ clap( short, long) ]
19- nesting : bool ,
20- /// Enable CSS modules in output
21- #[ clap( short, long, group = "css_modules" ) ]
22- css_modules : bool ,
23- /// Default: <output_file>.json
24- #[ clap( long, requires = "css_modules" ) ]
25- css_modules_output_file : Option < String > ,
26- /// Enable sourcemap, at <output_file>.map
27- #[ clap( short, long, requires = "output_file" ) ]
28- sourcemap : bool ,
9+ /// Target CSS file
10+ input_file : String ,
11+ /// Destination file for the output
12+ #[ clap( short, long, group = "output_file" ) ]
13+ output_file : Option < String > ,
14+ /// Minify the output
15+ #[ clap( short, long) ]
16+ minify : bool ,
17+ /// Enable parsing CSS nesting
18+ #[ clap( short, long) ]
19+ nesting : bool ,
20+ /// Enable CSS modules in output
21+ #[ clap( short, long, group = "css_modules" ) ]
22+ css_modules : bool ,
23+ /// Default: <output_file>.json
24+ #[ clap( long, requires = "css_modules" ) ]
25+ css_modules_output_file : Option < String > ,
26+ /// Enable sourcemap, at <output_file>.map
27+ #[ clap( short, long, requires = "output_file" ) ]
28+ sourcemap : bool ,
2929}
3030
3131#[ derive( Serialize ) ]
@@ -35,103 +35,108 @@ struct SourceMapJson<'a> {
3535 mappings : String ,
3636 sources : & ' a Vec < String > ,
3737 sources_content : & ' a Vec < String > ,
38- names : & ' a Vec < String >
38+ names : & ' a Vec < String > ,
3939}
4040
4141pub fn main ( ) -> Result < ( ) , std:: io:: Error > {
42- let cli_args = CliArgs :: parse ( ) ;
43- let source = fs:: read_to_string ( & cli_args. input_file ) ?;
44-
45- let filename = path:: Path :: new ( & cli_args. input_file )
46- . file_name ( )
47- . unwrap ( )
48- . to_str ( )
49- . unwrap ( )
50- . into ( ) ;
51- let mut stylesheet = StyleSheet :: parse (
52- filename,
53- & source,
54- ParserOptions {
55- nesting : cli_args. nesting ,
56- css_modules : cli_args. css_modules ,
57- ..ParserOptions :: default ( )
58- } ,
59- )
60- . unwrap ( ) ;
42+ let cli_args = CliArgs :: parse ( ) ;
43+ let source = fs:: read_to_string ( & cli_args. input_file ) ?;
6144
62- if cli_args. minify {
63- stylesheet. minify ( MinifyOptions :: default ( ) ) . unwrap ( ) ;
64- }
45+ let filename = path:: Path :: new ( & cli_args. input_file )
46+ . file_name ( )
47+ . unwrap ( )
48+ . to_str ( )
49+ . unwrap ( )
50+ . into ( ) ;
51+ let mut stylesheet = StyleSheet :: parse (
52+ filename,
53+ & source,
54+ ParserOptions {
55+ nesting : cli_args. nesting ,
56+ css_modules : cli_args. css_modules ,
57+ ..ParserOptions :: default ( )
58+ } ,
59+ )
60+ . unwrap ( ) ;
6561
66- let mut res = stylesheet
67- . to_css ( PrinterOptions {
68- minify : cli_args. minify ,
69- source_map : cli_args. sourcemap ,
70- ..PrinterOptions :: default ( )
71- } )
72- . unwrap ( ) ;
62+ if cli_args. minify {
63+ stylesheet. minify ( MinifyOptions :: default ( ) ) . unwrap ( ) ;
64+ }
7365
74- let map = if let Some ( ref mut source_map) = res. source_map {
75- source_map. set_source_content ( 0 , & res. code ) . map_err ( |_| io:: Error :: new ( io:: ErrorKind :: Other , "Error setting sourcemap" ) ) ?;
76- let mut vlq_output: Vec < u8 > = Vec :: new ( ) ;
77- source_map. write_vlq ( & mut vlq_output) . map_err ( |_| io:: Error :: new ( io:: ErrorKind :: Other , "Error writing sourcemap vlq" ) ) ?;
66+ let mut res = stylesheet
67+ . to_css ( PrinterOptions {
68+ minify : cli_args. minify ,
69+ source_map : cli_args. sourcemap ,
70+ ..PrinterOptions :: default ( )
71+ } )
72+ . unwrap ( ) ;
7873
79- let sm = SourceMapJson {
80- version : 3 ,
81- mappings : unsafe { String :: from_utf8_unchecked ( vlq_output) } ,
82- sources : source_map. get_sources ( ) ,
83- sources_content : source_map. get_sources_content ( ) ,
84- names : source_map. get_names ( )
85- } ;
74+ let map = if let Some ( ref mut source_map) = res. source_map {
75+ source_map
76+ . set_source_content ( 0 , & res. code )
77+ . map_err ( |_| io:: Error :: new ( io:: ErrorKind :: Other , "Error setting sourcemap" ) ) ?;
78+ let mut vlq_output: Vec < u8 > = Vec :: new ( ) ;
79+ source_map
80+ . write_vlq ( & mut vlq_output)
81+ . map_err ( |_| io:: Error :: new ( io:: ErrorKind :: Other , "Error writing sourcemap vlq" ) ) ?;
8682
87- serde_json:: to_vec ( & sm) . ok ( )
88- } else {
89- None
83+ let sm = SourceMapJson {
84+ version : 3 ,
85+ mappings : unsafe { String :: from_utf8_unchecked ( vlq_output) } ,
86+ sources : source_map. get_sources ( ) ,
87+ sources_content : source_map. get_sources_content ( ) ,
88+ names : source_map. get_names ( ) ,
9089 } ;
91- if let Some ( output_file) = & cli_args. output_file {
92- let mut code = res. code ;
93- if cli_args. sourcemap {
94- if let Some ( map_buf) = map {
95- let map_filename: String = output_file. to_owned ( ) + ".map" ;
96- code += & format ! ( "\n /*# sourceMappingURL={} */\n " , map_filename) ;
97- fs:: write ( map_filename, map_buf) ?;
98- }
99- }
100-
101- fs:: write ( output_file, code. as_bytes ( ) ) ?;
10290
103- if cli_args. css_modules {
104- let css_modules_filename = cli_args
105- . css_modules_output_file
106- . unwrap_or ( infer_css_modules_filename ( cli_args. output_file ) ?) ;
107- if let Some ( exports) = res. exports {
108- let css_modules_json = serde_json:: to_string ( & exports) ?;
109- fs:: write ( css_modules_filename, css_modules_json) ?;
110- }
111- }
91+ serde_json:: to_vec ( & sm) . ok ( )
92+ } else {
93+ None
94+ } ;
95+ if let Some ( output_file) = & cli_args. output_file {
96+ let mut code = res. code ;
97+ if cli_args. sourcemap {
98+ if let Some ( map_buf) = map {
99+ let map_filename: String = output_file. to_owned ( ) + ".map" ;
100+ code += & format ! ( "\n /*# sourceMappingURL={} */\n " , map_filename) ;
101+ fs:: write ( map_filename, map_buf) ?;
102+ }
103+ }
112104
105+ fs:: write ( output_file, code. as_bytes ( ) ) ?;
113106
114- } else {
115- println ! ( "{}" , res. code) ;
116- if cli_args. css_modules {
117- let css_modules_json = serde_json:: to_string ( & res. exports ) ?;
118- println ! ( "{}" , css_modules_json) ;
119- }
107+ if cli_args. css_modules {
108+ let css_modules_filename = cli_args
109+ . css_modules_output_file
110+ . unwrap_or ( infer_css_modules_filename ( cli_args. output_file ) ?) ;
111+ if let Some ( exports) = res. exports {
112+ let css_modules_json = serde_json:: to_string ( & exports) ?;
113+ fs:: write ( css_modules_filename, css_modules_json) ?;
114+ }
115+ }
116+ } else {
117+ println ! ( "{}" , res. code) ;
118+ if cli_args. css_modules {
119+ let css_modules_json = serde_json:: to_string ( & res. exports ) ?;
120+ println ! ( "{}" , css_modules_json) ;
120121 }
122+ }
121123
122- Ok ( ( ) )
124+ Ok ( ( ) )
123125}
124126
125127fn infer_css_modules_filename ( output_file : Option < String > ) -> Result < String , std:: io:: Error > {
126- if let Some ( file) = output_file {
127- let path = path:: Path :: new ( & file) ;
128- if path. extension ( ) == Some ( ffi:: OsStr :: new ( "json" ) ) {
129- Err ( io:: Error :: new ( io:: ErrorKind :: Other , "Cannot infer a css modules json filename, since the output file extension is '.json'" ) )
130- } else {
131- // unwrap: the filename option is a String from clap, so is valid utf-8
132- Ok ( path. with_extension ( "json" ) . to_str ( ) . unwrap ( ) . into ( ) )
133- }
128+ if let Some ( file) = output_file {
129+ let path = path:: Path :: new ( & file) ;
130+ if path. extension ( ) == Some ( ffi:: OsStr :: new ( "json" ) ) {
131+ Err ( io:: Error :: new (
132+ io:: ErrorKind :: Other ,
133+ "Cannot infer a css modules json filename, since the output file extension is '.json'" ,
134+ ) )
134135 } else {
135- Ok ( "styles.json" . into ( ) )
136+ // unwrap: the filename option is a String from clap, so is valid utf-8
137+ Ok ( path. with_extension ( "json" ) . to_str ( ) . unwrap ( ) . into ( ) )
136138 }
139+ } else {
140+ Ok ( "styles.json" . into ( ) )
141+ }
137142}
0 commit comments