Skip to content

Commit

Permalink
Expose Parse and ToCss traits (#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
devongovett authored Apr 6, 2022
1 parent 0c60d46 commit 7c1db82
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 86 deletions.
10 changes: 3 additions & 7 deletions src/dependencies.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::css_modules::hash;
use crate::printer::Printer;
use crate::printer::PrinterOptions;
use crate::rules::import::ImportRule;
use crate::traits::ToCss;
use crate::values::url::Url;
Expand All @@ -24,18 +24,14 @@ pub struct ImportDependency {
impl ImportDependency {
pub fn new(rule: &ImportRule, filename: &str) -> ImportDependency {
let supports = if let Some(supports) = &rule.supports {
let mut s = String::new();
let mut printer = Printer::new(&mut s, None, false, None);
supports.to_css(&mut printer).unwrap();
let s = supports.to_css_string(PrinterOptions::default()).unwrap();
Some(s)
} else {
None
};

let media = if !rule.media.media_queries.is_empty() {
let mut s = String::new();
let mut printer = Printer::new(&mut s, None, false, None);
rule.media.to_css(&mut printer).unwrap();
let s = rule.media.to_css_string(PrinterOptions::default()).unwrap();
Some(s)
} else {
None
Expand Down
31 changes: 28 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ mod macros;
pub mod media_query;
mod parser;
mod prefixes;
mod printer;
pub mod printer;
pub mod properties;
pub mod rules;
mod selector;
pub mod stylesheet;
pub mod targets;
mod traits;
pub mod traits;
pub mod values;
pub mod vendor_prefix;

Expand All @@ -26,10 +26,13 @@ mod tests {
use crate::dependencies::Dependency;
use crate::error::{Error, ErrorLocation, MinifyErrorKind, ParserError, PrinterErrorKind, SelectorError};
use crate::properties::custom::Token;
use crate::properties::Property;
use crate::rules::CssRule;
use crate::rules::Location;
use crate::stylesheet::*;
use crate::targets::Browsers;
use crate::traits::{Parse, ToCss};
use crate::values::color::CssColor;
use indoc::indoc;
use std::collections::HashMap;

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

// regex for converting web platform tests:
Expand Down Expand Up @@ -17565,6 +17568,28 @@ mod tests {
}
_ => unreachable!(),
}

let color = CssColor::parse_string("#f0f").unwrap();
assert_eq!(color.to_css_string(PrinterOptions::default()).unwrap(), "#f0f");

let rule = CssRule::parse_string(".foo { color: red }", ParserOptions::default()).unwrap();
assert_eq!(
rule.to_css_string(PrinterOptions::default()).unwrap(),
indoc! {r#"
.foo {
color: red;
}"#}
);

let property = Property::parse_string("color", "#f0f", ParserOptions::default()).unwrap();
assert_eq!(
property.to_css_string(false, PrinterOptions::default()).unwrap(),
"color: #f0f"
);
assert_eq!(
property.to_css_string(true, PrinterOptions::default()).unwrap(),
"color: #f0f !important"
);
}

#[test]
Expand Down
3 changes: 2 additions & 1 deletion src/media_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,7 @@ fn process_condition<'i>(
#[cfg(test)]
mod tests {
use super::*;
use crate::stylesheet::PrinterOptions;

fn parse(s: &str) -> MediaQuery {
let mut input = ParserInput::new(&s);
Expand All @@ -916,7 +917,7 @@ mod tests {
let mut a = parse(a);
let b = parse(b);
a.and(&b).unwrap();
a.to_css_string()
a.to_css_string(PrinterOptions::default()).unwrap()
}

#[test]
Expand Down
50 changes: 29 additions & 21 deletions src/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ use crate::vendor_prefix::VendorPrefix;
use cssparser::{serialize_identifier, SourceLocation};
use parcel_sourcemap::{OriginalLocation, SourceMap};

#[derive(Default)]
pub struct PrinterOptions<'a> {
pub minify: bool,
pub source_map: Option<&'a mut SourceMap>,
pub targets: Option<Browsers>,
pub analyze_dependencies: bool,
pub pseudo_classes: Option<PseudoClasses<'a>>,
}

#[derive(Default, Debug)]
pub struct PseudoClasses<'a> {
pub hover: Option<&'a str>,
Expand All @@ -16,47 +25,46 @@ pub struct PseudoClasses<'a> {
pub focus_within: Option<&'a str>,
}

pub(crate) struct Printer<'a, W> {
pub sources: Option<&'a Vec<String>>,
pub struct Printer<'a, W> {
pub(crate) sources: Option<&'a Vec<String>>,
dest: &'a mut W,
source_map: Option<&'a mut SourceMap>,
pub source_index: u32,
pub(crate) source_index: u32,
indent: u8,
line: u32,
col: u32,
pub minify: bool,
pub targets: Option<Browsers>,
pub(crate) minify: bool,
pub(crate) targets: Option<Browsers>,
/// Vendor prefix override. When non-empty, it overrides
/// the vendor prefix of whatever is being printed.
pub vendor_prefix: VendorPrefix,
pub in_calc: bool,
pub css_module: Option<CssModule<'a>>,
pub dependencies: Option<&'a mut Vec<Dependency>>,
pub pseudo_classes: Option<PseudoClasses<'a>>,
pub(crate) vendor_prefix: VendorPrefix,
pub(crate) in_calc: bool,
pub(crate) css_module: Option<CssModule<'a>>,
pub(crate) dependencies: Option<Vec<Dependency>>,
pub(crate) pseudo_classes: Option<PseudoClasses<'a>>,
}

impl<'a, W: std::fmt::Write + Sized> Printer<'a, W> {
pub fn new(
dest: &'a mut W,
source_map: Option<&'a mut SourceMap>,
minify: bool,
targets: Option<Browsers>,
) -> Printer<'a, W> {
pub fn new(dest: &'a mut W, options: PrinterOptions<'a>) -> Printer<'a, W> {
Printer {
sources: None,
dest,
source_map,
source_map: options.source_map,
source_index: 0,
indent: 0,
line: 0,
col: 0,
minify,
targets,
minify: options.minify,
targets: options.targets,
vendor_prefix: VendorPrefix::empty(),
in_calc: false,
css_module: None,
dependencies: None,
pseudo_classes: None,
dependencies: if options.analyze_dependencies {
Some(Vec::new())
} else {
None
},
pseudo_classes: options.pseudo_classes,
}
}

Expand Down
19 changes: 16 additions & 3 deletions src/properties/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use crate::error::{ParserError, PrinterError};
use crate::parser::starts_with_ignore_ascii_case;
use crate::parser::ParserOptions;
use crate::prefixes::Feature;
use crate::printer::Printer;
use crate::printer::{Printer, PrinterOptions};
use crate::targets::Browsers;
use crate::traits::{Parse, ToCss};
use crate::values::string::CowArcStr;
Expand Down Expand Up @@ -379,7 +379,13 @@ macro_rules! define_properties {
}
}

pub(crate) fn value_to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError> where W: std::fmt::Write {
pub fn parse_string(name: &'i str, input: &'i str, options: ParserOptions) -> Result<Self, ParseError<'i, ParserError<'i>>> {
let mut input = ParserInput::new(input);
let mut parser = Parser::new(&mut input);
Self::parse(CowRcStr::from(name), &mut parser, &options)
}

pub fn value_to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError> where W: std::fmt::Write {
use Property::*;

match self {
Expand All @@ -398,7 +404,7 @@ macro_rules! define_properties {
}
}

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

let mut first = true;
Expand Down Expand Up @@ -470,6 +476,13 @@ macro_rules! define_properties {
write!(VendorPrefix::None);
Ok(())
}

pub fn to_css_string(&self, important: bool, options: PrinterOptions) -> Result<String, PrinterError> {
let mut s = String::new();
let mut printer = Printer::new(&mut s, options);
self.to_css(&mut printer, important)?;
Ok(s)
}
}
};
}
Expand Down
33 changes: 29 additions & 4 deletions src/properties/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::error::{ParserError, PrinterError};
use crate::macros::enum_property;
use crate::prefixes::Feature;
use crate::printer::Printer;
use crate::stylesheet::PrinterOptions;
use crate::targets::Browsers;
use crate::traits::{Parse, PropertyHandler, ToCss};
use crate::values::{
Expand Down Expand Up @@ -53,13 +54,25 @@ impl ToCss for TransformList {
if let Some(matrix) = self.to_matrix() {
// Generate based on the original transforms.
let mut base = String::new();
self.to_css_base(&mut Printer::new(&mut base, None, true, None))?;
self.to_css_base(&mut Printer::new(
&mut base,
PrinterOptions {
minify: true,
..PrinterOptions::default()
},
))?;

// Decompose the matrix into transform functions if possible.
// If the resulting length is shorter than the original, use it.
if let Some(d) = matrix.decompose() {
let mut decomposed = String::new();
d.to_css_base(&mut Printer::new(&mut decomposed, None, true, None))?;
d.to_css_base(&mut Printer::new(
&mut decomposed,
PrinterOptions {
minify: true,
..PrinterOptions::default()
},
))?;
if decomposed.len() < base.len() {
base = decomposed;
}
Expand All @@ -68,9 +81,21 @@ impl ToCss for TransformList {
// Also generate a matrix() or matrix3d() representation and compare that.
let mut mat = String::new();
if let Some(matrix) = matrix.to_matrix2d() {
Transform::Matrix(matrix).to_css(&mut Printer::new(&mut mat, None, true, None))?
Transform::Matrix(matrix).to_css(&mut Printer::new(
&mut mat,
PrinterOptions {
minify: true,
..PrinterOptions::default()
},
))?
} else {
Transform::Matrix3d(matrix).to_css(&mut Printer::new(&mut mat, None, true, None))?
Transform::Matrix3d(matrix).to_css(&mut Printer::new(
&mut mat,
PrinterOptions {
minify: true,
..PrinterOptions::default()
},
))?
}

if mat.len() < base.len() {
Expand Down
23 changes: 22 additions & 1 deletion src/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,18 @@ use self::property::PropertyRule;
use crate::context::PropertyHandlerContext;
use crate::declaration::DeclarationHandler;
use crate::dependencies::{Dependency, ImportDependency};
use crate::error::{MinifyError, PrinterError};
use crate::error::{MinifyError, ParserError, PrinterError};
use crate::parser::TopLevelRuleParser;
use crate::prefixes::Feature;
use crate::printer::Printer;
use crate::selector::{downlevel_selectors, get_prefix, is_equivalent};
use crate::stylesheet::ParserOptions;
use crate::targets::Browsers;
use crate::traits::ToCss;
use crate::values::string::CowArcStr;
use crate::vendor_prefix::VendorPrefix;
use counter_style::CounterStyleRule;
use cssparser::{parse_one_rule, ParseError, Parser, ParserInput};
use custom_media::CustomMediaRule;
use document::MozDocumentRule;
use font_face::FontFaceRule;
Expand Down Expand Up @@ -125,6 +128,24 @@ impl<'a, 'i> ToCssWithContext<'a, 'i> for CssRule<'i> {
}
}

impl<'i> CssRule<'i> {
/// Parse a single rule.
pub fn parse<'t>(
input: &mut Parser<'i, 't>,
options: &ParserOptions,
) -> Result<Self, ParseError<'i, ParserError<'i>>> {
let (_, rule) = parse_one_rule(input, &mut TopLevelRuleParser::new(&options))?;
Ok(rule)
}

/// Parse a single rule from a string.
pub fn parse_string(input: &'i str, options: ParserOptions) -> Result<Self, ParseError<'i, ParserError<'i>>> {
let mut input = ParserInput::new(input);
let mut parser = Parser::new(&mut input);
Self::parse(&mut parser, &options)
}
}

impl<'i> ToCss for CssRule<'i> {
fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
where
Expand Down
3 changes: 2 additions & 1 deletion src/selector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::compat::Feature;
use crate::error::{ParserError, PrinterError};
use crate::printer::Printer;
use crate::rules::{StyleContext, ToCssWithContext};
use crate::stylesheet::PrinterOptions;
use crate::targets::Browsers;
use crate::traits::{Parse, ToCss};
use crate::vendor_prefix::VendorPrefix;
Expand Down Expand Up @@ -82,7 +83,7 @@ impl<'i> SelectorImpl<'i> for Selectors {
type ExtraMatchingData = ();

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

0 comments on commit 7c1db82

Please sign in to comment.