Skip to content

Commit 7c1db82

Browse files
authored
Expose Parse and ToCss traits (parcel-bundler#140)
1 parent 0c60d46 commit 7c1db82

File tree

13 files changed

+162
-86
lines changed

13 files changed

+162
-86
lines changed

src/dependencies.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::css_modules::hash;
2-
use crate::printer::Printer;
2+
use crate::printer::PrinterOptions;
33
use crate::rules::import::ImportRule;
44
use crate::traits::ToCss;
55
use crate::values::url::Url;
@@ -24,18 +24,14 @@ pub struct ImportDependency {
2424
impl ImportDependency {
2525
pub fn new(rule: &ImportRule, filename: &str) -> ImportDependency {
2626
let supports = if let Some(supports) = &rule.supports {
27-
let mut s = String::new();
28-
let mut printer = Printer::new(&mut s, None, false, None);
29-
supports.to_css(&mut printer).unwrap();
27+
let s = supports.to_css_string(PrinterOptions::default()).unwrap();
3028
Some(s)
3129
} else {
3230
None
3331
};
3432

3533
let media = if !rule.media.media_queries.is_empty() {
36-
let mut s = String::new();
37-
let mut printer = Printer::new(&mut s, None, false, None);
38-
rule.media.to_css(&mut printer).unwrap();
34+
let s = rule.media.to_css_string(PrinterOptions::default()).unwrap();
3935
Some(s)
4036
} else {
4137
None

src/lib.rs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ mod macros;
1010
pub mod media_query;
1111
mod parser;
1212
mod prefixes;
13-
mod printer;
13+
pub mod printer;
1414
pub mod properties;
1515
pub mod rules;
1616
mod selector;
1717
pub mod stylesheet;
1818
pub mod targets;
19-
mod traits;
19+
pub mod traits;
2020
pub mod values;
2121
pub mod vendor_prefix;
2222

@@ -26,10 +26,13 @@ mod tests {
2626
use crate::dependencies::Dependency;
2727
use crate::error::{Error, ErrorLocation, MinifyErrorKind, ParserError, PrinterErrorKind, SelectorError};
2828
use crate::properties::custom::Token;
29+
use crate::properties::Property;
2930
use crate::rules::CssRule;
3031
use crate::rules::Location;
3132
use crate::stylesheet::*;
3233
use crate::targets::Browsers;
34+
use crate::traits::{Parse, ToCss};
35+
use crate::values::color::CssColor;
3336
use indoc::indoc;
3437
use std::collections::HashMap;
3538

@@ -11840,7 +11843,7 @@ mod tests {
1184011843
let mut input = ParserInput::new(s);
1184111844
let mut parser = Parser::new(&mut input);
1184211845
let v = CssColor::parse(&mut parser).unwrap().to_rgb();
11843-
format!(".foo{{color:{}}}", v.to_css_string())
11846+
format!(".foo{{color:{}}}", v.to_css_string(PrinterOptions::default()).unwrap())
1184411847
}
1184511848

1184611849
// regex for converting web platform tests:
@@ -17565,6 +17568,28 @@ mod tests {
1756517568
}
1756617569
_ => unreachable!(),
1756717570
}
17571+
17572+
let color = CssColor::parse_string("#f0f").unwrap();
17573+
assert_eq!(color.to_css_string(PrinterOptions::default()).unwrap(), "#f0f");
17574+
17575+
let rule = CssRule::parse_string(".foo { color: red }", ParserOptions::default()).unwrap();
17576+
assert_eq!(
17577+
rule.to_css_string(PrinterOptions::default()).unwrap(),
17578+
indoc! {r#"
17579+
.foo {
17580+
color: red;
17581+
}"#}
17582+
);
17583+
17584+
let property = Property::parse_string("color", "#f0f", ParserOptions::default()).unwrap();
17585+
assert_eq!(
17586+
property.to_css_string(false, PrinterOptions::default()).unwrap(),
17587+
"color: #f0f"
17588+
);
17589+
assert_eq!(
17590+
property.to_css_string(true, PrinterOptions::default()).unwrap(),
17591+
"color: #f0f !important"
17592+
);
1756817593
}
1756917594

1757017595
#[test]

src/media_query.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,7 @@ fn process_condition<'i>(
905905
#[cfg(test)]
906906
mod tests {
907907
use super::*;
908+
use crate::stylesheet::PrinterOptions;
908909

909910
fn parse(s: &str) -> MediaQuery {
910911
let mut input = ParserInput::new(&s);
@@ -916,7 +917,7 @@ mod tests {
916917
let mut a = parse(a);
917918
let b = parse(b);
918919
a.and(&b).unwrap();
919-
a.to_css_string()
920+
a.to_css_string(PrinterOptions::default()).unwrap()
920921
}
921922

922923
#[test]

src/printer.rs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ use crate::vendor_prefix::VendorPrefix;
77
use cssparser::{serialize_identifier, SourceLocation};
88
use parcel_sourcemap::{OriginalLocation, SourceMap};
99

10+
#[derive(Default)]
11+
pub struct PrinterOptions<'a> {
12+
pub minify: bool,
13+
pub source_map: Option<&'a mut SourceMap>,
14+
pub targets: Option<Browsers>,
15+
pub analyze_dependencies: bool,
16+
pub pseudo_classes: Option<PseudoClasses<'a>>,
17+
}
18+
1019
#[derive(Default, Debug)]
1120
pub struct PseudoClasses<'a> {
1221
pub hover: Option<&'a str>,
@@ -16,47 +25,46 @@ pub struct PseudoClasses<'a> {
1625
pub focus_within: Option<&'a str>,
1726
}
1827

19-
pub(crate) struct Printer<'a, W> {
20-
pub sources: Option<&'a Vec<String>>,
28+
pub struct Printer<'a, W> {
29+
pub(crate) sources: Option<&'a Vec<String>>,
2130
dest: &'a mut W,
2231
source_map: Option<&'a mut SourceMap>,
23-
pub source_index: u32,
32+
pub(crate) source_index: u32,
2433
indent: u8,
2534
line: u32,
2635
col: u32,
27-
pub minify: bool,
28-
pub targets: Option<Browsers>,
36+
pub(crate) minify: bool,
37+
pub(crate) targets: Option<Browsers>,
2938
/// Vendor prefix override. When non-empty, it overrides
3039
/// the vendor prefix of whatever is being printed.
31-
pub vendor_prefix: VendorPrefix,
32-
pub in_calc: bool,
33-
pub css_module: Option<CssModule<'a>>,
34-
pub dependencies: Option<&'a mut Vec<Dependency>>,
35-
pub pseudo_classes: Option<PseudoClasses<'a>>,
40+
pub(crate) vendor_prefix: VendorPrefix,
41+
pub(crate) in_calc: bool,
42+
pub(crate) css_module: Option<CssModule<'a>>,
43+
pub(crate) dependencies: Option<Vec<Dependency>>,
44+
pub(crate) pseudo_classes: Option<PseudoClasses<'a>>,
3645
}
3746

3847
impl<'a, W: std::fmt::Write + Sized> Printer<'a, W> {
39-
pub fn new(
40-
dest: &'a mut W,
41-
source_map: Option<&'a mut SourceMap>,
42-
minify: bool,
43-
targets: Option<Browsers>,
44-
) -> Printer<'a, W> {
48+
pub fn new(dest: &'a mut W, options: PrinterOptions<'a>) -> Printer<'a, W> {
4549
Printer {
4650
sources: None,
4751
dest,
48-
source_map,
52+
source_map: options.source_map,
4953
source_index: 0,
5054
indent: 0,
5155
line: 0,
5256
col: 0,
53-
minify,
54-
targets,
57+
minify: options.minify,
58+
targets: options.targets,
5559
vendor_prefix: VendorPrefix::empty(),
5660
in_calc: false,
5761
css_module: None,
58-
dependencies: None,
59-
pseudo_classes: None,
62+
dependencies: if options.analyze_dependencies {
63+
Some(Vec::new())
64+
} else {
65+
None
66+
},
67+
pseudo_classes: options.pseudo_classes,
6068
}
6169
}
6270

src/properties/mod.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use crate::error::{ParserError, PrinterError};
3131
use crate::parser::starts_with_ignore_ascii_case;
3232
use crate::parser::ParserOptions;
3333
use crate::prefixes::Feature;
34-
use crate::printer::Printer;
34+
use crate::printer::{Printer, PrinterOptions};
3535
use crate::targets::Browsers;
3636
use crate::traits::{Parse, ToCss};
3737
use crate::values::string::CowArcStr;
@@ -379,7 +379,13 @@ macro_rules! define_properties {
379379
}
380380
}
381381

382-
pub(crate) fn value_to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError> where W: std::fmt::Write {
382+
pub fn parse_string(name: &'i str, input: &'i str, options: ParserOptions) -> Result<Self, ParseError<'i, ParserError<'i>>> {
383+
let mut input = ParserInput::new(input);
384+
let mut parser = Parser::new(&mut input);
385+
Self::parse(CowRcStr::from(name), &mut parser, &options)
386+
}
387+
388+
pub fn value_to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError> where W: std::fmt::Write {
383389
use Property::*;
384390

385391
match self {
@@ -398,7 +404,7 @@ macro_rules! define_properties {
398404
}
399405
}
400406

401-
pub(crate) fn to_css<W>(&self, dest: &mut Printer<W>, important: bool) -> Result<(), PrinterError> where W: std::fmt::Write {
407+
pub fn to_css<W>(&self, dest: &mut Printer<W>, important: bool) -> Result<(), PrinterError> where W: std::fmt::Write {
402408
use Property::*;
403409

404410
let mut first = true;
@@ -470,6 +476,13 @@ macro_rules! define_properties {
470476
write!(VendorPrefix::None);
471477
Ok(())
472478
}
479+
480+
pub fn to_css_string(&self, important: bool, options: PrinterOptions) -> Result<String, PrinterError> {
481+
let mut s = String::new();
482+
let mut printer = Printer::new(&mut s, options);
483+
self.to_css(&mut printer, important)?;
484+
Ok(s)
485+
}
473486
}
474487
};
475488
}

src/properties/transform.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::error::{ParserError, PrinterError};
55
use crate::macros::enum_property;
66
use crate::prefixes::Feature;
77
use crate::printer::Printer;
8+
use crate::stylesheet::PrinterOptions;
89
use crate::targets::Browsers;
910
use crate::traits::{Parse, PropertyHandler, ToCss};
1011
use crate::values::{
@@ -53,13 +54,25 @@ impl ToCss for TransformList {
5354
if let Some(matrix) = self.to_matrix() {
5455
// Generate based on the original transforms.
5556
let mut base = String::new();
56-
self.to_css_base(&mut Printer::new(&mut base, None, true, None))?;
57+
self.to_css_base(&mut Printer::new(
58+
&mut base,
59+
PrinterOptions {
60+
minify: true,
61+
..PrinterOptions::default()
62+
},
63+
))?;
5764

5865
// Decompose the matrix into transform functions if possible.
5966
// If the resulting length is shorter than the original, use it.
6067
if let Some(d) = matrix.decompose() {
6168
let mut decomposed = String::new();
62-
d.to_css_base(&mut Printer::new(&mut decomposed, None, true, None))?;
69+
d.to_css_base(&mut Printer::new(
70+
&mut decomposed,
71+
PrinterOptions {
72+
minify: true,
73+
..PrinterOptions::default()
74+
},
75+
))?;
6376
if decomposed.len() < base.len() {
6477
base = decomposed;
6578
}
@@ -68,9 +81,21 @@ impl ToCss for TransformList {
6881
// Also generate a matrix() or matrix3d() representation and compare that.
6982
let mut mat = String::new();
7083
if let Some(matrix) = matrix.to_matrix2d() {
71-
Transform::Matrix(matrix).to_css(&mut Printer::new(&mut mat, None, true, None))?
84+
Transform::Matrix(matrix).to_css(&mut Printer::new(
85+
&mut mat,
86+
PrinterOptions {
87+
minify: true,
88+
..PrinterOptions::default()
89+
},
90+
))?
7291
} else {
73-
Transform::Matrix3d(matrix).to_css(&mut Printer::new(&mut mat, None, true, None))?
92+
Transform::Matrix3d(matrix).to_css(&mut Printer::new(
93+
&mut mat,
94+
PrinterOptions {
95+
minify: true,
96+
..PrinterOptions::default()
97+
},
98+
))?
7499
}
75100

76101
if mat.len() < base.len() {

src/rules/mod.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,18 @@ use self::property::PropertyRule;
2121
use crate::context::PropertyHandlerContext;
2222
use crate::declaration::DeclarationHandler;
2323
use crate::dependencies::{Dependency, ImportDependency};
24-
use crate::error::{MinifyError, PrinterError};
24+
use crate::error::{MinifyError, ParserError, PrinterError};
25+
use crate::parser::TopLevelRuleParser;
2526
use crate::prefixes::Feature;
2627
use crate::printer::Printer;
2728
use crate::selector::{downlevel_selectors, get_prefix, is_equivalent};
29+
use crate::stylesheet::ParserOptions;
2830
use crate::targets::Browsers;
2931
use crate::traits::ToCss;
3032
use crate::values::string::CowArcStr;
3133
use crate::vendor_prefix::VendorPrefix;
3234
use counter_style::CounterStyleRule;
35+
use cssparser::{parse_one_rule, ParseError, Parser, ParserInput};
3336
use custom_media::CustomMediaRule;
3437
use document::MozDocumentRule;
3538
use font_face::FontFaceRule;
@@ -125,6 +128,24 @@ impl<'a, 'i> ToCssWithContext<'a, 'i> for CssRule<'i> {
125128
}
126129
}
127130

131+
impl<'i> CssRule<'i> {
132+
/// Parse a single rule.
133+
pub fn parse<'t>(
134+
input: &mut Parser<'i, 't>,
135+
options: &ParserOptions,
136+
) -> Result<Self, ParseError<'i, ParserError<'i>>> {
137+
let (_, rule) = parse_one_rule(input, &mut TopLevelRuleParser::new(&options))?;
138+
Ok(rule)
139+
}
140+
141+
/// Parse a single rule from a string.
142+
pub fn parse_string(input: &'i str, options: ParserOptions) -> Result<Self, ParseError<'i, ParserError<'i>>> {
143+
let mut input = ParserInput::new(input);
144+
let mut parser = Parser::new(&mut input);
145+
Self::parse(&mut parser, &options)
146+
}
147+
}
148+
128149
impl<'i> ToCss for CssRule<'i> {
129150
fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
130151
where

src/selector.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::compat::Feature;
22
use crate::error::{ParserError, PrinterError};
33
use crate::printer::Printer;
44
use crate::rules::{StyleContext, ToCssWithContext};
5+
use crate::stylesheet::PrinterOptions;
56
use crate::targets::Browsers;
67
use crate::traits::{Parse, ToCss};
78
use crate::vendor_prefix::VendorPrefix;
@@ -82,7 +83,7 @@ impl<'i> SelectorImpl<'i> for Selectors {
8283
type ExtraMatchingData = ();
8384

8485
fn to_css<W: fmt::Write>(selectors: &SelectorList<'i, Self>, dest: &mut W) -> std::fmt::Result {
85-
let mut printer = Printer::new(dest, None, false, None);
86+
let mut printer = Printer::new(dest, PrinterOptions::default());
8687
serialize_selector_list(selectors.0.iter(), &mut printer, None, false).map_err(|_| std::fmt::Error)
8788
}
8889
}

0 commit comments

Comments
 (0)