diff --git a/derive/src/to_css.rs b/derive/src/to_css.rs index bd515efa..c10f3929 100644 --- a/derive/src/to_css.rs +++ b/derive/src/to_css.rs @@ -25,10 +25,7 @@ pub fn derive_to_css(input: TokenStream) -> TokenStream { let output = quote! { impl #impl_generics ToCss for #ident #ty_generics #where_clause { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #imp } } diff --git a/examples/custom_at_rule.rs b/examples/custom_at_rule.rs index 749566d1..2e0fff47 100644 --- a/examples/custom_at_rule.rs +++ b/examples/custom_at_rule.rs @@ -1,10 +1,10 @@ -use std::{collections::HashMap, convert::Infallible, fmt::Write}; +use std::{collections::HashMap, convert::Infallible}; use cssparser::*; use rspack_lightningcss::{ declaration::DeclarationBlock, error::PrinterError, - printer::Printer, + printer::PrinterTrait, properties::custom::{Token, TokenOrValue}, rules::{style::StyleRule, CssRule, CssRuleList, Location}, selector::{Component, Selector}, @@ -285,7 +285,7 @@ impl<'i, V: Visitor<'i, AtRule>> Visit<'i, AtRule, V> for AtRule { } impl ToCss for AtRule { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { AtRule::Tailwind(rule) => { let _ = rule.loc; // TODO: source maps diff --git a/examples/wpt_adapter.rs b/examples/wpt_adapter.rs index ac6c28c1..579f322c 100644 --- a/examples/wpt_adapter.rs +++ b/examples/wpt_adapter.rs @@ -1,6 +1,6 @@ //! Test-only JSONL bridge for the WPT harness. No production parser behavior is changed. use cssparser::{Parser, ParserInput}; -use lightningcss::{ +use rspack_lightningcss::{ properties::{ custom::{CustomPropertyName, TokenList, TokenOrValue, UnresolvedColor}, Property, PropertyId, diff --git a/napi/src/at_rule_parser.rs b/napi/src/at_rule_parser.rs index 50cbd2c7..648fd491 100644 --- a/napi/src/at_rule_parser.rs +++ b/napi/src/at_rule_parser.rs @@ -1,9 +1,10 @@ -use std::{collections::HashMap, fmt::Write}; +use std::collections::HashMap; use cssparser::*; use rspack_lightningcss::{ declaration::DeclarationBlock, error::ParserError, + printer::PrinterTrait, rules::{CssRuleList, Location}, stylesheet::ParserOptions, traits::{AtRuleParser, ToCss}, @@ -161,13 +162,10 @@ impl<'i> AtRuleParser<'i> for CustomAtRuleParser { } impl<'i> ToCss for AtRule<'i> { - fn to_css( + fn to_css( &self, - dest: &mut rspack_lightningcss::printer::Printer, - ) -> Result<(), rspack_lightningcss::error::PrinterError> - where - W: std::fmt::Write, - { + dest: &mut PrinterT, + ) -> Result<(), rspack_lightningcss::error::PrinterError> { dest.write_char('@')?; serialize_identifier(&self.name, dest)?; if let Some(prelude) = &self.prelude { diff --git a/src/declaration.rs b/src/declaration.rs index e9e83aba..101f8bba 100644 --- a/src/declaration.rs +++ b/src/declaration.rs @@ -1,13 +1,11 @@ //! CSS declarations. use std::borrow::Cow; -use std::fmt::Write; use std::ops::Range; use crate::context::{DeclarationContext, PropertyHandlerContext}; use crate::error::{ParserError, PrinterError, PrinterErrorKind}; use crate::parser::ParserOptions; -use crate::printer::Printer; use crate::properties::box_shadow::BoxShadowHandler; use crate::properties::custom::{CustomProperty, CustomPropertyName}; use crate::properties::masking::MaskHandler; @@ -125,10 +123,7 @@ impl<'i> DeclarationBlock<'i> { } impl<'i> ToCss for DeclarationBlock<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let len = self.declarations.len() + self.important_declarations.len(); let mut i = 0; @@ -153,10 +148,10 @@ impl<'i> ToCss for DeclarationBlock<'i> { impl<'i> DeclarationBlock<'i> { /// Writes the declarations to a CSS block, including starting and ending braces. - pub fn to_css_block(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + pub fn to_css_block( + &self, + dest: &mut PrinterT, + ) -> Result<(), PrinterError> { dest.whitespace()?; dest.write_char('{')?; dest.indent(); @@ -190,16 +185,13 @@ impl<'i> DeclarationBlock<'i> { } /// Writes the declarations to a CSS declaration block. - pub fn to_css_declarations( + pub fn to_css_declarations( &self, - dest: &mut Printer, + dest: &mut PrinterT, has_nested_rules: bool, selectors: &SelectorList, source_index: u32, - ) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + ) -> Result<(), PrinterError> { let mut i = 0; let len = self.len(); @@ -209,14 +201,14 @@ impl<'i> DeclarationBlock<'i> { // The CSS modules `composes` property is handled specially, and omitted during printing. // We need to add the classes it references to the list for the selectors in this rule. if let crate::properties::Property::Composes(composes) = &decl { - if dest.is_nested() && dest.css_module.is_some() { + if dest.is_nested() && dest.css_module_config().is_some() { return Err(dest.error(PrinterErrorKind::InvalidComposesNesting, composes.loc)); } - if let Some(css_module) = &mut dest.css_module { - css_module - .handle_composes(&selectors, &composes, source_index) - .map_err(|e| dest.error(e, composes.loc))?; + if let Some(result) = dest + .with_css_module_mut(|css_module| css_module.handle_composes(&selectors, &composes, source_index)) + { + result.map_err(|e| dest.error(e, composes.loc))?; continue; } } @@ -226,7 +218,7 @@ impl<'i> DeclarationBlock<'i> { } decl.to_css(dest, $important)?; - if i != len - 1 || !dest.minify || has_nested_rules { + if i != len - 1 || !dest.options().minify || has_nested_rules { dest.write_char(';')?; } diff --git a/src/lib.rs b/src/lib.rs index 7426fe99..263cc5d7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32642,14 +32642,11 @@ b\0 c'); ) .unwrap(); let result = stylesheet - .to_css( - PrinterOptions { - minify: true, - analyze_dependencies: Some(Default::default()), - ..Default::default() - }, - None::<&mut ()>, - ) + .to_css(PrinterOptions { + minify: true, + analyze_dependencies: Some(Default::default()), + ..Default::default() + }) .unwrap(); let dependencies = result.dependencies.unwrap(); assert_eq!(dependencies.len(), 1); @@ -32680,13 +32677,11 @@ b\0 c'); .unwrap(); let mut sm = parcel_sourcemap::SourceMap::new("/"); let result = stylesheet - .to_css( - PrinterOptions { - minify: true, - ..Default::default() - }, - Some(&mut sm), - ) + .to_css(PrinterOptions { + minify: true, + source_map: Some(&mut sm), + ..Default::default() + }) .unwrap(); let column = result.code.find(".bar").unwrap() as u32; let mapping = sm.find_closest_mapping(0, column).unwrap(); diff --git a/src/macros.rs b/src/macros.rs index be6a9d31..a3d52033 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -83,7 +83,7 @@ macro_rules! enum_property { } impl ToCss for $name { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> where W: std::fmt::Write { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { dest.write_str(self.as_str())?; Ok(()) } @@ -153,7 +153,7 @@ macro_rules! shorthand_property { } impl$(<$l>)? ToCss for $name$(<$l>)? { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> where W: std::fmt::Write { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let mut needs_space = false; macro_rules! print_one { ($k: ident, $t: ty) => { @@ -756,10 +756,7 @@ macro_rules! rect_shorthand { } impl ToCss for $name { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { Rect::new(&self.top, &self.right, &self.bottom, &self.left).to_css(dest) } } @@ -799,10 +796,7 @@ macro_rules! size_shorthand { } impl ToCss for $name { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { Size2D(&self.$a_key, &self.$b_key).to_css(dest) } } diff --git a/src/media_query.rs b/src/media_query.rs index 2d246bb5..c41c678b 100644 --- a/src/media_query.rs +++ b/src/media_query.rs @@ -2,7 +2,6 @@ use crate::error::{ErrorWithLocation, MinifyError, MinifyErrorKind, ParserError, PrinterError}; use crate::macros::enum_property; use crate::parser::starts_with_ignore_ascii_case; -use crate::printer::Printer; use crate::properties::custom::{EnvironmentVariable, TokenList}; #[cfg(feature = "visitor")] use crate::rules::container::{ContainerSizeFeatureId, ScrollStateFeatureId}; @@ -24,7 +23,6 @@ use cssparser::*; use rspack_lightningcss_static_self::IntoOwned; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; -use std::fmt::Write; #[cfg(feature = "serde")] use crate::serialization::ValueWrapper; @@ -161,10 +159,7 @@ impl<'i> MediaList<'i> { } impl<'i> ToCss for MediaList<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if self.media_queries.is_empty() { dest.write_str("not all")?; return Ok(()); @@ -419,10 +414,7 @@ impl<'i> MediaQuery<'i> { } impl<'i> ToCss for MediaQuery<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if let Some(qual) = self.qualifier { qual.to_css(dest)?; dest.write_char(' ')?; @@ -811,14 +803,11 @@ fn parse_paren_block<'t, 'i, P: QueryCondition<'i>>( }) } -pub(crate) fn to_css_with_parens_if_needed( +pub(crate) fn to_css_with_parens_if_needed( value: V, - dest: &mut Printer, + dest: &mut PrinterT, needs_parens: bool, -) -> Result<(), PrinterError> -where - W: std::fmt::Write, -{ +) -> Result<(), PrinterError> { if needs_parens { dest.write_char('(')?; } @@ -829,22 +818,19 @@ where Ok(()) } -pub(crate) fn operation_to_css<'i, V: ToCss + QueryCondition<'i>, W>( +pub(crate) fn operation_to_css<'i, V: ToCss + QueryCondition<'i>, PrinterT: crate::printer::PrinterTrait>( operator: Operator, conditions: &Vec, - dest: &mut Printer, -) -> Result<(), PrinterError> -where - W: std::fmt::Write, -{ + dest: &mut PrinterT, +) -> Result<(), PrinterError> { let mut iter = conditions.iter(); let first = iter.next().unwrap(); - to_css_with_parens_if_needed(first, dest, first.needs_parens(Some(operator), &dest.targets.current))?; + to_css_with_parens_if_needed(first, dest, first.needs_parens(Some(operator), &dest.targets().current))?; for item in iter { dest.write_char(' ')?; operator.to_css(dest)?; dest.write_char(' ')?; - to_css_with_parens_if_needed(item, dest, item.needs_parens(Some(operator), &dest.targets.current))?; + to_css_with_parens_if_needed(item, dest, item.needs_parens(Some(operator), &dest.targets().current))?; } Ok(()) @@ -861,10 +847,7 @@ impl<'i> MediaCondition<'i> { } impl<'i> ToCss for MediaCondition<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match *self { MediaCondition::Feature(ref f) => f.to_css(dest), MediaCondition::Not(ref c) => { @@ -872,7 +855,7 @@ impl<'i> ToCss for MediaCondition<'i> { negated.to_css(dest) } else { dest.write_str("not ")?; - to_css_with_parens_if_needed(&**c, dest, c.needs_parens(None, &dest.targets.current)) + to_css_with_parens_if_needed(&**c, dest, c.needs_parens(None, &dest.targets().current)) } } MediaCondition::Operation { @@ -908,10 +891,7 @@ pub enum MediaFeatureComparison { } impl ToCss for MediaFeatureComparison { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { use MediaFeatureComparison::*; match self { Equal => dest.delim('=', true), @@ -1169,10 +1149,7 @@ where } impl<'i, FeatureId: FeatureToCss> ToCss for QueryFeature<'i, FeatureId> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { QueryFeature::Boolean { name } => { dest.write_char('(')?; @@ -1186,7 +1163,7 @@ impl<'i, FeatureId: FeatureToCss> ToCss for QueryFeature<'i, FeatureId> { } QueryFeature::Range { name, operator, value } => { // If range syntax is unsupported, use min/max prefix if possible. - if should_compile!(dest.targets.current, MediaRangeSyntax) { + if should_compile!(dest.targets().current, MediaRangeSyntax) { return write_min_max(operator, name, value, dest, false); } @@ -1202,7 +1179,7 @@ impl<'i, FeatureId: FeatureToCss> ToCss for QueryFeature<'i, FeatureId> { end, end_operator, } => { - if should_compile!(dest.targets.current, MediaIntervalSyntax) { + if should_compile!(dest.targets().current, MediaIntervalSyntax) { write_min_max(&start_operator.opposite(), name, start, dest, true)?; dest.write_str(" and ")?; return write_min_max(end_operator, name, end, dest, true); @@ -1305,10 +1282,7 @@ impl<'i, FeatureId: ValueType> ValueType for MediaFeatureName<'i, FeatureId> { } impl<'i, FeatureId: FeatureToCss> ToCss for MediaFeatureName<'i, FeatureId> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { Self::Standard(v) => v.to_css(dest), Self::Custom(v) => v.to_css(dest), @@ -1318,10 +1292,11 @@ impl<'i, FeatureId: FeatureToCss> ToCss for MediaFeatureName<'i, FeatureId> { } impl<'i, FeatureId: FeatureToCss> FeatureToCss for MediaFeatureName<'i, FeatureId> { - fn to_css_with_prefix(&self, prefix: &str, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css_with_prefix( + &self, + prefix: &str, + dest: &mut PrinterT, + ) -> Result<(), PrinterError> { match self { Self::Standard(v) => v.to_css_with_prefix(prefix, dest), Self::Custom(v) => { @@ -1497,16 +1472,19 @@ define_query_features! { } pub(crate) trait FeatureToCss: ToCss { - fn to_css_with_prefix(&self, prefix: &str, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write; + fn to_css_with_prefix( + &self, + prefix: &str, + dest: &mut PrinterT, + ) -> Result<(), PrinterError>; } impl FeatureToCss for MediaFeatureId { - fn to_css_with_prefix(&self, prefix: &str, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css_with_prefix( + &self, + prefix: &str, + dest: &mut PrinterT, + ) -> Result<(), PrinterError> { match self { MediaFeatureId::WebKitDevicePixelRatio => { dest.write_str("-webkit-")?; @@ -1523,16 +1501,13 @@ impl FeatureToCss for MediaFeatureId { } #[inline] -fn write_min_max( +fn write_min_max( operator: &MediaFeatureComparison, name: &MediaFeatureName, value: &MediaFeatureValue, - dest: &mut Printer, + dest: &mut PrinterT, is_range: bool, -) -> Result<(), PrinterError> -where - W: std::fmt::Write, -{ +) -> Result<(), PrinterError> { let prefix = match operator { MediaFeatureComparison::GreaterThan => { if is_range { @@ -1698,10 +1673,7 @@ impl<'i> MediaFeatureValue<'i> { } impl<'i> ToCss for MediaFeatureValue<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { MediaFeatureValue::Length(len) => len.to_css(dest), MediaFeatureValue::Number(num) => num.to_css(dest), diff --git a/src/parser.rs b/src/parser.rs index e847a5ab..f44454db 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,7 +1,6 @@ use crate::declaration::{parse_declaration, DeclarationBlock, DeclarationList}; use crate::error::{Error, ParserError, PrinterError}; use crate::media_query::*; -use crate::printer::Printer; use crate::properties::custom::TokenList; use crate::rules::container::{ContainerCondition, ContainerName, ContainerRule}; use crate::rules::font_feature_values::FontFeatureValuesRule; @@ -124,7 +123,7 @@ impl<'i> crate::traits::AtRuleParser<'i> for DefaultAtRuleParser { #[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))] pub struct DefaultAtRule; impl crate::traits::ToCss for DefaultAtRule { - fn to_css(&self, _: &mut Printer) -> Result<(), PrinterError> { + fn to_css(&self, _: &mut PrinterT) -> Result<(), PrinterError> { Err(PrinterError { kind: crate::error::PrinterErrorKind::FmtError, loc: None, diff --git a/src/printer.rs b/src/printer.rs index bb21cd82..5a64abf9 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -13,7 +13,6 @@ use parcel_sourcemap::{OriginalLocation, SourceMap}; use std::fmt::Write; /// Options that control how CSS is serialized to a string. -#[derive(Default)] pub struct PrinterOptions<'a> { /// Whether to minify the CSS, i.e. remove white space. pub minify: bool, @@ -38,6 +37,34 @@ pub struct PrinterOptions<'a> { pub pseudo_classes: Option>, } +impl<'a> Default for PrinterOptions<'a> { + fn default() -> Self { + PrinterOptions { + minify: false, + #[cfg(feature = "sourcemap")] + source_map: None, + project_root: None, + targets: Targets::default(), + analyze_dependencies: None, + pseudo_classes: None, + } + } +} + +pub(crate) struct PrinterState<'a, 'c> { + pub(crate) loc: Location, + pub(crate) generated_line: u32, + pub(crate) generated_col: u32, + pub(crate) indent: u8, + pub(crate) targets: TargetsWithSupportsScope, + pub(crate) vendor_prefix: VendorPrefix, + pub(crate) in_calc: bool, + pub(crate) css_module: Option>, + pub(crate) dependencies: Option>, + pub(crate) remove_imports: bool, + pub(crate) context: Option<&'a StyleContext<'a, 'c>>, +} + /// A mapping of user action pseudo classes to replace with class names. /// /// See [PrinterOptions](PrinterOptions). @@ -60,78 +87,67 @@ pub struct PseudoClasses<'a> { /// implements [std::fmt::Write](std::fmt::Write), such as a [String](String). /// /// A `Printer` keeps track of the current line and column position, and uses -/// this to generate a source map if provided in the options. +/// this to generate a source map if one is provided. /// /// `Printer` also includes helper functions that assist with writing output /// that respects options such as `minify`, and `css_modules`. pub struct Printer<'a, 'c, W> { pub(crate) sources: Option<&'c Vec>, dest: &'a mut W, + pub(crate) options: PrinterOptions<'a>, + pub(crate) state: PrinterState<'a, 'c>, #[cfg(feature = "sourcemap")] - #[cfg_attr(docsrs, doc(cfg(feature = "sourcemap")))] pub(crate) source_map: Option<&'a mut SourceMap>, #[cfg(feature = "sourcemap")] - #[cfg_attr(docsrs, doc(cfg(feature = "sourcemap")))] pub(crate) source_maps: Vec>, #[cfg(feature = "sourcemap")] pub(crate) source_map_source_indices: &'c [Option], - pub(crate) loc: Location, - indent: u8, - line: u32, - col: u32, - pub(crate) minify: bool, - pub(crate) targets: TargetsWithSupportsScope, - /// Vendor prefix override. When non-empty, it overrides - /// the vendor prefix of whatever is being printed. - pub(crate) vendor_prefix: VendorPrefix, - pub(crate) in_calc: bool, - pub(crate) css_module: Option>, - pub(crate) dependencies: Option>, - pub(crate) remove_imports: bool, - pub(crate) pseudo_classes: Option>, - context: Option<&'a StyleContext<'a, 'c>>, } impl<'a, 'c, W: std::fmt::Write + Sized> Printer<'a, 'c, W> { /// Create a new Printer wrapping the given destination. - pub fn new(dest: &'a mut W, options: PrinterOptions<'a>) -> Self { + #[cfg_attr(not(feature = "sourcemap"), allow(unused_mut))] + pub fn new(dest: &'a mut W, mut options: PrinterOptions<'a>) -> Self { + let dependencies = if options.analyze_dependencies.is_some() { + Some(Vec::new()) + } else { + None + }; + let remove_imports = matches!(&options.analyze_dependencies, Some(d) if d.remove_imports); Printer { sources: None, dest, #[cfg(feature = "sourcemap")] - source_map: options.source_map, + source_map: options.source_map.take(), + state: PrinterState { + loc: Location { + source_index: 0, + line: 0, + column: 1, + }, + generated_line: 0, + generated_col: 0, + indent: 0, + targets: TargetsWithSupportsScope::new(options.targets), + vendor_prefix: VendorPrefix::empty(), + in_calc: false, + css_module: None, + dependencies, + remove_imports, + context: None, + }, + options, #[cfg(feature = "sourcemap")] source_maps: Vec::new(), #[cfg(feature = "sourcemap")] source_map_source_indices: &[], - loc: Location { - source_index: 0, - line: 0, - column: 1, - }, - indent: 0, - line: 0, - col: 0, - minify: options.minify, - targets: TargetsWithSupportsScope::new(options.targets), - vendor_prefix: VendorPrefix::empty(), - in_calc: false, - css_module: None, - dependencies: if options.analyze_dependencies.is_some() { - Some(Vec::new()) - } else { - None - }, - remove_imports: matches!(&options.analyze_dependencies, Some(d) if d.remove_imports), - pseudo_classes: options.pseudo_classes, - context: None, } } /// Returns the current source filename that is being printed. pub fn filename(&self) -> &'c str { if let Some(sources) = self.sources { - if let Some(f) = sources.get(self.loc.source_index as usize) { + if let Some(f) = sources.get(self.state.loc.source_index as usize) { f } else { "unknown.css" @@ -146,7 +162,7 @@ impl<'a, 'c, W: std::fmt::Write + Sized> Printer<'a, 'c, W> { /// Use `write_char` instead if you wish to force a space character to be written, /// regardless of the `minify` option. pub fn whitespace(&mut self) -> Result<(), PrinterError> { - if self.minify { + if self.options.minify { return Ok(()); } @@ -167,13 +183,13 @@ impl<'a, 'c, W: std::fmt::Write + Sized> Printer<'a, 'c, W> { /// Writes a newline character followed by indentation. /// If the `minify` option is enabled, then nothing is printed. pub fn newline(&mut self) -> Result<(), PrinterError> { - if self.minify { + if self.options.minify { return Ok(()); } self.write_char('\n')?; - if self.indent > 0 { - self.write_str(&" ".repeat(self.indent as usize))?; + if self.state.indent > 0 { + self.write_str(&" ".repeat(self.state.indent as usize))?; } Ok(()) @@ -181,77 +197,27 @@ impl<'a, 'c, W: std::fmt::Write + Sized> Printer<'a, 'c, W> { /// Increases the current indent level. pub fn indent(&mut self) { - self.indent += 2; + self.state.indent += 2; } /// Decreases the current indent level. pub fn dedent(&mut self) { - self.indent -= 2; + self.state.indent -= 2; } /// Increases the current indent level by the given number of characters. pub fn indent_by(&mut self, amt: u8) { - self.indent += amt; + self.state.indent += amt; } /// Decreases the current indent level by the given number of characters. pub fn dedent_by(&mut self, amt: u8) { - self.indent -= amt; + self.state.indent -= amt; } /// Returns whether the indent level is greater than one. pub fn is_nested(&self) -> bool { - self.indent > 2 - } - - /// Adds a mapping to the source map, if any. - #[cfg(feature = "sourcemap")] - #[cfg_attr(docsrs, doc(cfg(feature = "sourcemap")))] - pub fn add_mapping(&mut self, loc: Location) { - self.loc = loc; - - if let Some(map) = &mut self.source_map { - let mut original = OriginalLocation { - original_line: loc.line, - original_column: loc.column - 1, - source: self - .source_map_source_indices - .get(loc.source_index as usize) - .copied() - .flatten() - .unwrap_or(loc.source_index), - name: None, - }; - - // Remap using input source map if possible. - if let Some(Some(sm)) = self.source_maps.get_mut(loc.source_index as usize) { - let mut found_mapping = false; - if let Some(mapping) = sm.find_closest_mapping(loc.line, loc.column - 1) { - if let Some(orig) = mapping.original { - let sources_len = map.get_sources().len(); - let source_index = map.add_source(sm.get_source(orig.source).unwrap()); - let name = orig.name.map(|name| map.add_name(sm.get_name(name).unwrap())); - original.original_line = orig.original_line; - original.original_column = orig.original_column; - original.source = source_index; - original.name = name; - - if map.get_sources().len() > sources_len { - let content = sm.get_source_content(orig.source).unwrap().to_owned(); - let _ = map.set_source_content(source_index as usize, &content); - } - - found_mapping = true; - } - } - - if !found_mapping { - return; - } - } - - map.add_mapping(self.line, self.col, Some(original)) - } + self.state.indent > 2 } /// Writes a CSS identifier to the underlying destination, escaping it @@ -259,20 +225,20 @@ impl<'a, 'c, W: std::fmt::Write + Sized> Printer<'a, 'c, W> { /// is added, and the mapping is added to the CSS module. pub fn write_ident(&mut self, ident: &str, handle_css_module: bool) -> Result<(), PrinterError> { if handle_css_module { - if let Some(css_module) = &mut self.css_module { + if let Some(css_module) = &mut self.state.css_module { let dest = &mut self.dest; let mut first = true; css_module.config.pattern.write( - &css_module.hashes[self.loc.source_index as usize], - &css_module.sources[self.loc.source_index as usize], + &css_module.hashes[self.state.loc.source_index as usize], + &css_module.sources[self.state.loc.source_index as usize], ident, if let Some(content_hashes) = &css_module.content_hashes { - &content_hashes[self.loc.source_index as usize] + &content_hashes[self.state.loc.source_index as usize] } else { "" }, |s| { - self.col += s.len() as u32; + self.state.generated_col += s.len() as u32; if first { first = false; serialize_identifier(s, dest) @@ -282,7 +248,7 @@ impl<'a, 'c, W: std::fmt::Write + Sized> Printer<'a, 'c, W> { }, )?; - css_module.add_local(&ident, &ident, self.loc.source_index); + css_module.add_local(&ident, &ident, self.state.loc.source_index); return Ok(()); } } @@ -294,26 +260,26 @@ impl<'a, 'c, W: std::fmt::Write + Sized> Printer<'a, 'c, W> { pub(crate) fn write_dashed_ident(&mut self, ident: &str, is_declaration: bool) -> Result<(), PrinterError> { self.write_str("--")?; - match &mut self.css_module { + match &mut self.state.css_module { Some(css_module) if css_module.config.dashed_idents => { let dest = &mut self.dest; css_module.config.pattern.write( - &css_module.hashes[self.loc.source_index as usize], - &css_module.sources[self.loc.source_index as usize], + &css_module.hashes[self.state.loc.source_index as usize], + &css_module.sources[self.state.loc.source_index as usize], &ident[2..], if let Some(content_hashes) = &css_module.content_hashes { - &content_hashes[self.loc.source_index as usize] + &content_hashes[self.state.loc.source_index as usize] } else { "" }, |s| { - self.col += s.len() as u32; + self.state.generated_col += s.len() as u32; serialize_name(s, dest) }, )?; if is_declaration { - css_module.add_dashed(ident, self.loc.source_index); + css_module.add_dashed(ident, self.state.loc.source_index); } } _ => { @@ -336,51 +302,90 @@ impl<'a, 'c, W: std::fmt::Write + Sized> Printer<'a, 'c, W> { } } - pub(crate) fn with_context) -> Result>( - &mut self, - selectors: &SelectorList, - f: F, - ) -> Result { - let parent = std::mem::take(&mut self.context); + pub(crate) fn take_dependencies(&mut self) -> Option> { + self.state.dependencies.take() + } + + /// Adds a mapping to the source map, if any. + #[cfg(feature = "sourcemap")] + #[cfg_attr(docsrs, doc(cfg(feature = "sourcemap")))] + pub fn add_mapping(&mut self, loc: Location) { + self.state.loc = loc; + + if let Some(map) = &mut self.source_map { + let mut original = OriginalLocation { + original_line: loc.line, + original_column: loc.column - 1, + source: self + .source_map_source_indices + .get(loc.source_index as usize) + .copied() + .flatten() + .unwrap_or(loc.source_index), + name: None, + }; + + // Remap using input source map if possible. + if let Some(Some(sm)) = self.source_maps.get_mut(loc.source_index as usize) { + let mut found_mapping = false; + if let Some(mapping) = sm.find_closest_mapping(loc.line, loc.column - 1) { + if let Some(orig) = mapping.original { + let sources_len = map.get_sources().len(); + let source_index = map.add_source(sm.get_source(orig.source).unwrap()); + let name = orig.name.map(|name| map.add_name(sm.get_name(name).unwrap())); + original.original_line = orig.original_line; + original.original_column = orig.original_column; + original.source = source_index; + original.name = name; + + if map.get_sources().len() > sources_len { + let content = sm.get_source_content(orig.source).unwrap().to_owned(); + let _ = map.set_source_content(source_index as usize, &content); + } + + found_mapping = true; + } + } + + if !found_mapping { + return; + } + } + + map.add_mapping(self.state.generated_line, self.state.generated_col, Some(original)); + } + } + + fn with_context(&mut self, selectors: &SelectorList, f: impl FnOnce(&mut Self) -> T) -> T { + let parent = self.state.context.take(); let ctx = StyleContext { selectors: unsafe { std::mem::transmute(selectors) }, parent, }; - // I can't figure out what lifetime to use here to convince the compiler that - // the reference doesn't live beyond the function call. - self.context = Some(unsafe { std::mem::transmute(&ctx) }); + // The context is only installed for the duration of the callback. + self.state.context = Some(unsafe { std::mem::transmute(&ctx) }); let res = f(self); - self.context = parent; + self.state.context = parent; res } - pub(crate) fn with_cleared_context) -> Result>( - &mut self, - f: F, - ) -> Result { - let parent = std::mem::take(&mut self.context); + fn with_cleared_context(&mut self, f: impl FnOnce(&mut Self) -> T) -> T { + let parent = self.state.context.take(); let res = f(self); - self.context = parent; + self.state.context = parent; res } - pub(crate) fn with_parent_context) -> Result>( - &mut self, - f: F, - ) -> Result { - let parent = std::mem::take(&mut self.context); + fn with_parent_context(&mut self, f: impl FnOnce(&mut Self) -> T) -> T { + let parent = self.state.context.take(); if let Some(parent) = parent { - self.context = parent.parent; + self.state.context = parent.parent; } let res = f(self); - self.context = parent; + self.state.context = parent; res } - - pub(crate) fn context(&self) -> Option<&'a StyleContext<'a, 'c>> { - self.context.clone() - } } impl<'a, 'c, W: std::fmt::Write + Sized> Write for Printer<'a, 'c, W> { @@ -388,13 +393,13 @@ impl<'a, 'c, W: std::fmt::Write + Sized> Write for Printer<'a, 'c, W> { let mut last_line_start = 0; for (idx, c) in s.char_indices() { if c == '\n' { - self.line += 1; + self.state.generated_line += 1; last_line_start = idx + 1; } } - self.col = if last_line_start == 0 { - self.col + s.len() as u32 + self.state.generated_col = if last_line_start == 0 { + self.state.generated_col + s.len() as u32 } else { (s.len() - last_line_start) as u32 }; @@ -403,16 +408,239 @@ impl<'a, 'c, W: std::fmt::Write + Sized> Write for Printer<'a, 'c, W> { fn write_char(&mut self, c: char) -> std::fmt::Result { if c == '\n' { - self.line += 1; - self.col = 0; + self.state.generated_line += 1; + self.state.generated_col = 0; } else { - self.col += 1; + self.state.generated_col += 1; } self.dest.write_char(c) } } +// Supertrait methods can be called through a public generic bound. Require a +// crate-local token to run a callback with an installed style context. +pub(crate) struct ContextAccess; + +mod private { + use super::*; + + pub(crate) trait Sealed { + fn targets(&self) -> &TargetsWithSupportsScope; + fn targets_mut(&mut self) -> &mut TargetsWithSupportsScope; + fn vendor_prefix(&self) -> VendorPrefix; + fn set_vendor_prefix(&mut self, prefix: VendorPrefix); + fn loc(&self) -> Location; + fn in_calc(&self) -> bool; + fn set_in_calc(&mut self, in_calc: bool); + fn css_module_config(&self) -> Option<&crate::css_modules::Config>; + fn with_css_module_mut(&mut self, f: impl FnOnce(&mut CssModule<'_, '_>) -> T) -> Option; + fn is_nested(&self) -> bool; + fn has_dependencies(&self) -> bool; + fn add_dependency(&mut self, dep: Dependency); + fn remove_imports(&self) -> bool; + fn has_context(&self) -> bool; + fn with_context( + &mut self, + access: ContextAccess, + selectors: &SelectorList, + f: impl FnOnce(&mut Self) -> T, + ) -> T; + fn with_cleared_context(&mut self, access: ContextAccess, f: impl FnOnce(&mut Self) -> T) -> T; + fn with_parent_context(&mut self, access: ContextAccess, f: impl FnOnce(&mut Self) -> T) -> T; + fn with_current_context( + &mut self, + access: ContextAccess, + f: impl FnOnce(&mut Self, Option<&StyleContext<'_, '_>>) -> T, + ) -> T; + fn with_pseudo_class( + &mut self, + get: impl for<'p> FnOnce(&PseudoClasses<'p>) -> Option<&'p str>, + f: impl FnOnce(&mut Self, Option<&str>) -> T, + ) -> T; + } +} + +/// A printer abstraction used by CSS serialization implementations. +#[allow(missing_docs)] +#[allow(private_bounds)] +pub trait PrinterTrait: std::fmt::Write + private::Sealed { + fn options(&self) -> &PrinterOptions<'_>; + fn filename(&self) -> &str; + fn error(&self, kind: PrinterErrorKind, loc: crate::dependencies::Location) -> Error { + Error { + kind, + loc: Some(ErrorLocation { + filename: self.filename().into(), + line: loc.line - 1, + column: loc.column, + }), + } + } + + fn whitespace(&mut self) -> Result<(), PrinterError>; + fn delim(&mut self, c: char, ws_before: bool) -> Result<(), PrinterError>; + fn newline(&mut self) -> Result<(), PrinterError>; + #[cfg(feature = "sourcemap")] + fn add_mapping(&mut self, loc: Location); + fn indent(&mut self); + fn dedent(&mut self); + fn indent_by(&mut self, amt: u8); + fn dedent_by(&mut self, amt: u8); + fn write_ident(&mut self, ident: &str, handle_css_module: bool) -> Result<(), PrinterError>; + fn write_dashed_ident(&mut self, ident: &str, is_declaration: bool) -> Result<(), PrinterError>; + + fn without_css_module(&mut self, f: impl FnOnce(&mut Self) -> Result) -> Result; +} + +impl private::Sealed for Printer<'_, '_, W> { + fn targets(&self) -> &TargetsWithSupportsScope { + &self.state.targets + } + + fn targets_mut(&mut self) -> &mut TargetsWithSupportsScope { + &mut self.state.targets + } + + fn vendor_prefix(&self) -> VendorPrefix { + self.state.vendor_prefix + } + + fn set_vendor_prefix(&mut self, prefix: VendorPrefix) { + self.state.vendor_prefix = prefix; + } + + fn loc(&self) -> Location { + self.state.loc + } + + fn in_calc(&self) -> bool { + self.state.in_calc + } + + fn set_in_calc(&mut self, in_calc: bool) { + self.state.in_calc = in_calc; + } + + fn css_module_config(&self) -> Option<&crate::css_modules::Config> { + self.state.css_module.as_ref().map(|css_module| css_module.config) + } + + fn with_css_module_mut(&mut self, f: impl FnOnce(&mut CssModule<'_, '_>) -> T) -> Option { + self.state.css_module.as_mut().map(f) + } + + fn is_nested(&self) -> bool { + Printer::is_nested(self) + } + + fn has_dependencies(&self) -> bool { + self.state.dependencies.is_some() + } + + fn add_dependency(&mut self, dep: Dependency) { + if let Some(dependencies) = &mut self.state.dependencies { + dependencies.push(dep); + } + } + + fn remove_imports(&self) -> bool { + self.state.remove_imports + } + + fn has_context(&self) -> bool { + self.state.context.is_some() + } + + fn with_context(&mut self, _: ContextAccess, selectors: &SelectorList, f: impl FnOnce(&mut Self) -> T) -> T { + Printer::with_context(self, selectors, f) + } + + fn with_cleared_context(&mut self, _: ContextAccess, f: impl FnOnce(&mut Self) -> T) -> T { + Printer::with_cleared_context(self, f) + } + + fn with_parent_context(&mut self, _: ContextAccess, f: impl FnOnce(&mut Self) -> T) -> T { + Printer::with_parent_context(self, f) + } + + fn with_current_context( + &mut self, + _: ContextAccess, + f: impl FnOnce(&mut Self, Option<&StyleContext<'_, '_>>) -> T, + ) -> T { + let context = self.state.context; + f(self, context) + } + + fn with_pseudo_class( + &mut self, + get: impl for<'p> FnOnce(&PseudoClasses<'p>) -> Option<&'p str>, + f: impl FnOnce(&mut Self, Option<&str>) -> T, + ) -> T { + let class = self.options.pseudo_classes.as_ref().and_then(get); + f(self, class) + } +} + +impl<'a, 'c, W: std::fmt::Write + Sized> PrinterTrait for Printer<'a, 'c, W> { + fn options(&self) -> &PrinterOptions<'_> { + &self.options + } + + fn filename(&self) -> &str { + Printer::filename(self) + } + + fn whitespace(&mut self) -> Result<(), PrinterError> { + Printer::whitespace(self) + } + + fn delim(&mut self, c: char, ws_before: bool) -> Result<(), PrinterError> { + Printer::delim(self, c, ws_before) + } + + fn newline(&mut self) -> Result<(), PrinterError> { + Printer::newline(self) + } + + #[cfg(feature = "sourcemap")] + fn add_mapping(&mut self, loc: Location) { + Printer::add_mapping(self, loc) + } + + fn indent(&mut self) { + Printer::indent(self) + } + + fn dedent(&mut self) { + Printer::dedent(self) + } + + fn indent_by(&mut self, amt: u8) { + Printer::indent_by(self, amt) + } + + fn dedent_by(&mut self, amt: u8) { + Printer::dedent_by(self, amt) + } + + fn write_ident(&mut self, ident: &str, handle_css_module: bool) -> Result<(), PrinterError> { + Printer::write_ident(self, ident, handle_css_module) + } + + fn write_dashed_ident(&mut self, ident: &str, is_declaration: bool) -> Result<(), PrinterError> { + Printer::write_dashed_ident(self, ident, is_declaration) + } + + fn without_css_module(&mut self, f: impl FnOnce(&mut Self) -> Result) -> Result { + let css_module = self.state.css_module.take(); + let res = f(self)?; + self.state.css_module = css_module; + Ok(res) + } +} + #[cfg(test)] mod tests { use super::{Printer, PrinterOptions}; @@ -427,7 +655,7 @@ mod tests { printer.write_char('\n').unwrap(); printer.write_str("d").unwrap(); - assert_eq!((printer.line, printer.col), (2, 1)); + assert_eq!((printer.state.generated_line, printer.state.generated_col), (2, 1)); drop(printer); assert_eq!(output, "a\nbc\nd"); } diff --git a/src/properties/align.rs b/src/properties/align.rs index c4ec2969..2e436725 100644 --- a/src/properties/align.rs +++ b/src/properties/align.rs @@ -8,7 +8,6 @@ use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::macros::*; use crate::prefixes::{is_flex_2009, Feature}; -use crate::printer::Printer; use crate::traits::{FromStandard, Parse, PropertyHandler, Shorthand, ToCss}; use crate::values::length::LengthPercentage; use crate::values::number::NonNegative; @@ -16,7 +15,6 @@ use crate::vendor_prefix::VendorPrefix; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; #[cfg(feature = "serde")] use crate::serialization::ValueWrapper; @@ -60,10 +58,7 @@ impl<'i> Parse<'i> for BaselinePosition { } impl ToCss for BaselinePosition { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { BaselinePosition::First => dest.write_str("baseline")?, BaselinePosition::Last => dest.write_str("last baseline")?, @@ -208,10 +203,7 @@ impl<'i> Parse<'i> for JustifyContent { } impl ToCss for JustifyContent { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { JustifyContent::Normal => dest.write_str("normal")?, JustifyContent::ContentDistribution(value) => value.to_css(dest)?, @@ -283,10 +275,7 @@ impl<'i> Parse<'i> for PlaceContent { } impl ToCss for PlaceContent { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.align.to_css(dest)?; let is_equal = match self.justify { JustifyContent::Normal if self.align == AlignContent::Normal => true, @@ -432,10 +421,7 @@ impl<'i> Parse<'i> for JustifySelf { } impl ToCss for JustifySelf { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { JustifySelf::Auto => dest.write_str("auto")?, JustifySelf::Normal => dest.write_str("normal")?, @@ -505,10 +491,7 @@ impl<'i> Parse<'i> for PlaceSelf { } impl ToCss for PlaceSelf { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.align.to_css(dest)?; let is_equal = match &self.justify { JustifySelf::Auto => true, @@ -614,10 +597,7 @@ impl<'i> Parse<'i> for LegacyJustify { } impl ToCss for LegacyJustify { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { dest.write_str("legacy ")?; match self { LegacyJustify::Left => dest.write_str("left")?, @@ -704,10 +684,7 @@ impl<'i> Parse<'i> for JustifyItems { } impl ToCss for JustifyItems { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { JustifyItems::Normal => dest.write_str("normal")?, JustifyItems::Stretch => dest.write_str("stretch")?, @@ -776,10 +753,7 @@ impl<'i> Parse<'i> for PlaceItems { } impl ToCss for PlaceItems { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.align.to_css(dest)?; let is_equal = match &self.justify { JustifyItems::Normal => self.align == AlignItems::Normal, @@ -839,10 +813,7 @@ impl<'i> Parse<'i> for Gap { } impl ToCss for Gap { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.row.to_css(dest)?; if self.column != self.row { dest.write_str(" ")?; diff --git a/src/properties/animation.rs b/src/properties/animation.rs index 5e6b6541..46e0a39f 100644 --- a/src/properties/animation.rs +++ b/src/properties/animation.rs @@ -1,14 +1,12 @@ //! CSS properties related to keyframe animations. use std::borrow::Cow; -use std::fmt::Write; use crate::context::PropertyHandlerContext; use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::macros::*; use crate::prefixes::Feature; -use crate::printer::Printer; use crate::properties::{Property, PropertyId, TokenOrValue, VendorPrefix}; use crate::traits::{Parse, PropertyHandler, Shorthand, ToCss, Zero}; use crate::values::ident::DashedIdent; @@ -47,12 +45,9 @@ pub enum AnimationName<'i> { } impl<'i> ToCss for AnimationName<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { - let css_module_animation_enabled = - dest.css_module.as_ref().map_or(false, |css_module| css_module.config.animation); + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { + let css_module_animation_enabled = dest.css_module_config().is_some_and(|config| config.animation); + let source_index = dest.loc().source_index; match self { AnimationName::None => { @@ -61,17 +56,13 @@ impl<'i> ToCss for AnimationName<'i> { } AnimationName::Ident(s) => { if css_module_animation_enabled { - if let Some(css_module) = &mut dest.css_module { - css_module.reference(&s.0, dest.loc.source_index) - } + dest.with_css_module_mut(|css_module| css_module.reference(&s.0, source_index)); } s.to_css_with_options(dest, css_module_animation_enabled) } AnimationName::String(s) => { if css_module_animation_enabled { - if let Some(css_module) = &mut dest.css_module { - css_module.reference(&s, dest.loc.source_index) - } + dest.with_css_module_mut(|css_module| css_module.reference(&s, source_index)); } // CSS-wide keywords and `none` cannot remove quotes. @@ -255,10 +246,7 @@ impl<'i> Parse<'i> for ScrollTimeline { } impl ToCss for ScrollTimeline { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { dest.write_str("scroll(")?; let mut needs_space = false; @@ -360,10 +348,7 @@ impl<'i> Parse<'i> for ViewTimeline { } impl ToCss for ViewTimeline { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { dest.write_str("view(")?; let mut needs_space = false; if self.axis != ScrollAxis::default() { @@ -454,10 +439,11 @@ impl<'i> AnimationAttachmentRange { Ok(AnimationAttachmentRange::TimelineRange { name, offset }) } - fn to_css(&self, dest: &mut Printer, default: f32) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css( + &self, + dest: &mut PrinterT, + default: f32, + ) -> Result<(), PrinterError> { match self { Self::Normal => { dest.write_str("normal")?; @@ -498,10 +484,7 @@ impl<'i> Parse<'i> for AnimationRangeStart { } impl ToCss for AnimationRangeStart { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.0.to_css(dest, 0.0) } } @@ -522,10 +505,7 @@ impl<'i> Parse<'i> for AnimationRangeEnd { } impl ToCss for AnimationRangeEnd { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.0.to_css(dest, 1.0) } } @@ -567,10 +547,7 @@ impl<'i> Parse<'i> for AnimationRange { } impl ToCss for AnimationRange { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.start.to_css(dest)?; let omit_end = match (&self.start.0, &self.end.0) { @@ -671,10 +648,7 @@ impl<'i> Parse<'i> for Animation<'i> { } impl<'i> ToCss for Animation<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match &self.name { AnimationName::None => {} AnimationName::Ident(CustomIdent(name)) | AnimationName::String(CSSString(name)) => { diff --git a/src/properties/background.rs b/src/properties/background.rs index 1864e7e7..91e9c46d 100644 --- a/src/properties/background.rs +++ b/src/properties/background.rs @@ -5,7 +5,6 @@ use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::macros::*; use crate::prefixes::Feature; -use crate::printer::Printer; use crate::properties::{Property, PropertyId, VendorPrefix}; use crate::targets::{Browsers, Targets}; use crate::traits::{FallbackValues, IsCompatible, Parse, PropertyHandler, Shorthand, ToCss}; @@ -18,7 +17,6 @@ use crate::visitor::Visit; use cssparser::*; use itertools::izip; use smallvec::SmallVec; -use std::fmt::Write; /// A value for the [background-size](https://www.w3.org/TR/css-backgrounds-3/#background-size) property. #[derive(Debug, Clone, PartialEq)] @@ -75,10 +73,7 @@ impl<'i> Parse<'i> for BackgroundSize { } impl ToCss for BackgroundSize { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { use BackgroundSize::*; match &self { @@ -174,10 +169,7 @@ impl<'i> Parse<'i> for BackgroundRepeat { } impl ToCss for BackgroundRepeat { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { use BackgroundRepeatKeyword::*; match (&self.x, &self.y) { (Repeat, NoRepeat) => { @@ -327,10 +319,7 @@ impl<'i> Parse<'i> for BackgroundPosition { } impl ToCss for BackgroundPosition { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let pos: Position = self.into(); pos.to_css(dest) } @@ -455,10 +444,7 @@ impl<'i> Parse<'i> for Background<'i> { } impl<'i> ToCss for Background<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let mut has_output = false; if self.color != CssColor::default() { @@ -529,7 +515,7 @@ impl<'i> ToCss for Background<'i> { // If nothing was output, then this is the initial value, e.g. background: transparent if !has_output { - if dest.minify { + if dest.options().minify { // `0 0` is the shortest valid background value self.position.to_css(dest)?; } else { diff --git a/src/properties/border.rs b/src/properties/border.rs index 2825276e..a3e948dc 100644 --- a/src/properties/border.rs +++ b/src/properties/border.rs @@ -8,7 +8,6 @@ use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::logical::PropertyCategory; use crate::macros::*; -use crate::printer::Printer; use crate::properties::custom::UnparsedProperty; use crate::properties::{Property, PropertyId}; use crate::targets::Browsers; @@ -22,7 +21,6 @@ use crate::values::size::Size2D; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; /// A value for the [border-width](https://www.w3.org/TR/css-backgrounds-3/#border-width) property. #[derive(Debug, Clone, PartialEq, Parse, ToCss)] @@ -180,10 +178,7 @@ impl<'i, S: Parse<'i> + Default, const P: u8> Parse<'i> for GenericBorder } impl ToCss for GenericBorder { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if *self == Self::default() { self.style.to_css(dest)?; return Ok(()); diff --git a/src/properties/border_image.rs b/src/properties/border_image.rs index f38c7b7e..abb96bd3 100644 --- a/src/properties/border_image.rs +++ b/src/properties/border_image.rs @@ -4,7 +4,6 @@ use crate::context::PropertyHandlerContext; use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::prefixes::Feature; -use crate::printer::Printer; use crate::properties::{Property, PropertyId, VendorPrefix}; use crate::targets::{Browsers, Targets}; use crate::traits::{IsCompatible, Parse, PropertyHandler, Shorthand, ToCss}; @@ -23,7 +22,6 @@ use crate::{ }, }; use cssparser::*; -use std::fmt::Write; enum_property! { /// A single [border-image-repeat](https://www.w3.org/TR/css-backgrounds-3/#border-image-repeat) keyword. @@ -84,10 +82,7 @@ impl<'i> Parse<'i> for BorderImageRepeat { } impl ToCss for BorderImageRepeat { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.horizontal.to_css(dest)?; if self.horizontal != self.vertical { dest.write_str(" ")?; @@ -171,10 +166,7 @@ impl<'i> Parse<'i> for BorderImageSlice { } impl ToCss for BorderImageSlice { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.offsets.to_css(dest)?; if self.fill { dest.write_str(" fill")?; @@ -293,17 +285,14 @@ impl<'i> BorderImage<'i> { } } - pub(crate) fn to_css_internal( + pub(crate) fn to_css_internal( source: &Image<'i>, slice: &BorderImageSlice, width: &Rect, outset: &Rect>, repeat: &BorderImageRepeat, - dest: &mut Printer, - ) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + dest: &mut PrinterT, + ) -> Result<(), PrinterError> { let has_source = *source != Image::default(); let has_slice = *slice != BorderImageSlice::default(); let has_width = *width != Rect::all(BorderImageSideWidth::default()); @@ -345,10 +334,7 @@ impl<'i> BorderImage<'i> { } impl<'i> ToCss for BorderImage<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { BorderImage::to_css_internal(&self.source, &self.slice, &self.width, &self.outset, &self.repeat, dest) } } diff --git a/src/properties/border_radius.rs b/src/properties/border_radius.rs index 38097de0..bb870b3d 100644 --- a/src/properties/border_radius.rs +++ b/src/properties/border_radius.rs @@ -7,7 +7,6 @@ use crate::error::{ParserError, PrinterError}; use crate::logical::PropertyCategory; use crate::macros::define_shorthand; use crate::prefixes::Feature; -use crate::printer::Printer; use crate::properties::{Property, PropertyId, VendorPrefix}; use crate::traits::{IsCompatible, Parse, PropertyHandler, Shorthand, ToCss, Zero}; use crate::values::length::*; @@ -66,10 +65,7 @@ impl<'i> Parse<'i> for BorderRadius { } impl ToCss for BorderRadius { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let widths = Rect::new( &self.top_left.0, &self.top_right.0, diff --git a/src/properties/box_shadow.rs b/src/properties/box_shadow.rs index bab3bfb5..1552de41 100644 --- a/src/properties/box_shadow.rs +++ b/src/properties/box_shadow.rs @@ -5,7 +5,6 @@ use crate::context::PropertyHandlerContext; use crate::declaration::DeclarationList; use crate::error::{ParserError, PrinterError}; use crate::prefixes::Feature; -use crate::printer::Printer; use crate::properties::Property; use crate::targets::Browsers; use crate::traits::{IsCompatible, Parse, PropertyHandler, ToCss, Zero}; @@ -17,7 +16,6 @@ use crate::vendor_prefix::VendorPrefix; use crate::visitor::Visit; use cssparser::*; use smallvec::SmallVec; -use std::fmt::Write; /// A value for the [box-shadow](https://drafts.csswg.org/css-backgrounds/#box-shadow) property. #[derive(Debug, Clone, PartialEq)] @@ -101,10 +99,7 @@ impl<'i> Parse<'i> for BoxShadow { } impl ToCss for BoxShadow { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if self.inset { dest.write_str("inset ")?; } diff --git a/src/properties/contain.rs b/src/properties/contain.rs index 134b2222..1fb1dbfe 100644 --- a/src/properties/contain.rs +++ b/src/properties/contain.rs @@ -2,8 +2,6 @@ #![allow(non_upper_case_globals)] -use std::fmt::Write; - use cssparser::*; use smallvec::SmallVec; @@ -14,7 +12,6 @@ use crate::{ declaration::{DeclarationBlock, DeclarationList}, error::{ParserError, PrinterError}, macros::{define_shorthand, enum_property, shorthand_handler}, - printer::Printer, properties::{Property, PropertyId}, rules::container::ContainerName as ContainerIdent, targets::Browsers, @@ -93,10 +90,7 @@ impl<'i> Parse<'i> for ContainerNameList<'i> { } impl<'i> ToCss for ContainerNameList<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { ContainerNameList::None => { dest.write_str("none")?; @@ -148,10 +142,7 @@ impl<'i> Parse<'i> for Container<'i> { } impl<'i> ToCss for Container<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.name.to_css(dest)?; if self.container_type != ContainerType::default() { dest.delim('/', true)?; diff --git a/src/properties/css_modules.rs b/src/properties/css_modules.rs index f699bbe3..1a297706 100644 --- a/src/properties/css_modules.rs +++ b/src/properties/css_modules.rs @@ -2,7 +2,6 @@ use crate::dependencies::Location; use crate::error::{ParserError, PrinterError}; -use crate::printer::Printer; use crate::traits::{Parse, ToCss}; use crate::values::ident::{CustomIdent, CustomIdentList}; use crate::values::string::CowArcStr; @@ -10,7 +9,6 @@ use crate::values::string::CowArcStr; use crate::visitor::Visit; use cssparser::*; use smallvec::SmallVec; -use std::fmt::Write; /// A value for the [composes](https://github.com/css-modules/css-modules/#dependencies) property from CSS modules. #[derive(Debug, Clone, PartialEq)] @@ -88,10 +86,7 @@ fn parse_one_ident<'i, 't>( } impl ToCss for Composes<'_> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let mut first = true; for name in &self.names { if first { @@ -123,10 +118,7 @@ impl<'i> Parse<'i> for Specifier<'i> { } impl<'i> ToCss for Specifier<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { Specifier::Global => dest.write_str("global")?, Specifier::File(file) => serialize_string(&file, dest)?, diff --git a/src/properties/custom.rs b/src/properties/custom.rs index f77fff28..d5a8e53c 100644 --- a/src/properties/custom.rs +++ b/src/properties/custom.rs @@ -3,6 +3,7 @@ use crate::error::{ParserError, PrinterError, PrinterErrorKind}; use crate::macros::enum_property; use crate::prefixes::Feature; +#[cfg(feature = "substitute_variables")] use crate::printer::Printer; use crate::properties::PropertyId; use crate::rules::supports::SupportsCondition; @@ -26,7 +27,6 @@ use crate::values::url::Url; use crate::visitor::Visit; use cssparser::color::parse_hash_color; use cssparser::*; -use std::fmt::Write; use super::AnimationName; #[cfg(feature = "serde")] @@ -101,10 +101,7 @@ impl<'i> AsRef for CustomPropertyName<'i> { } impl<'i> ToCss for CustomPropertyName<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { CustomPropertyName::Custom(c) => c.to_css(dest), CustomPropertyName::Unknown(u) => u.to_css(dest), @@ -486,10 +483,11 @@ fn try_parse_color_token<'i, 't>( } impl<'i> TokenList<'i> { - pub(crate) fn to_css(&self, dest: &mut Printer, is_custom_property: bool) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + pub(crate) fn to_css( + &self, + dest: &mut PrinterT, + is_custom_property: bool, + ) -> Result<(), PrinterError> { for token_or_value in self.0.iter() { match token_or_value { TokenOrValue::Color(color) => { @@ -499,7 +497,7 @@ impl<'i> TokenList<'i> { color.to_css(dest, is_custom_property)?; } TokenOrValue::Url(url) => { - if dest.dependencies.is_some() && is_custom_property && !url.is_absolute() { + if dest.has_dependencies() && is_custom_property && !url.is_absolute() { return Err(dest.error( PrinterErrorKind::AmbiguousUrlInCustomProperty { url: url.url.as_ref().to_owned(), @@ -555,10 +553,10 @@ impl<'i> TokenList<'i> { Ok(()) } - pub(crate) fn to_css_raw(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + pub(crate) fn to_css_raw( + &self, + dest: &mut PrinterT, + ) -> Result<(), PrinterError> { for token_or_value in &self.0 { match token_or_value { TokenOrValue::Token(token) => { @@ -841,10 +839,7 @@ impl<'a> From<&cssparser::Token<'a>> for Token<'a> { impl<'a> ToCss for Token<'a> { #[inline] - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { use cssparser::ToCss; match self { Token::Ident(x) => cssparser::Token::Ident(x.as_ref().into()).to_css(dest)?, @@ -890,14 +885,14 @@ impl<'a> ToCss for Token<'a> { } .to_css(dest)?, Token::WhiteSpace(w) => { - if dest.minify { + if dest.options().minify { dest.write_char(' ')?; } else { dest.write_str(&w)?; } } Token::Comment(c) => { - if !dest.minify { + if !dest.options().minify { cssparser::Token::Comment(c).to_css(dest)?; } } @@ -1209,10 +1204,11 @@ impl<'i> Variable<'i> { Ok(Variable { name, fallback }) } - fn to_css(&self, dest: &mut Printer, is_custom_property: bool) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css( + &self, + dest: &mut PrinterT, + is_custom_property: bool, + ) -> Result<(), PrinterError> { dest.write_str("var(")?; self.name.to_css(dest)?; if let Some(fallback) = &self.fallback { @@ -1335,10 +1331,7 @@ impl<'i> Parse<'i> for EnvironmentVariableName<'i> { } impl<'i> ToCss for EnvironmentVariableName<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { EnvironmentVariableName::UA(ua) => ua.to_css(dest), EnvironmentVariableName::Custom(custom) => custom.to_css(dest), @@ -1381,10 +1374,11 @@ impl<'i> EnvironmentVariable<'i> { }) } - pub(crate) fn to_css(&self, dest: &mut Printer, is_custom_property: bool) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + pub(crate) fn to_css( + &self, + dest: &mut PrinterT, + is_custom_property: bool, + ) -> Result<(), PrinterError> { dest.write_str("env(")?; self.name.to_css(dest)?; @@ -1429,10 +1423,11 @@ pub struct Function<'i> { } impl<'i> Function<'i> { - fn to_css(&self, dest: &mut Printer, is_custom_property: bool) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css( + &self, + dest: &mut PrinterT, + is_custom_property: bool, + ) -> Result<(), PrinterError> { self.name.to_css(dest)?; dest.write_char('(')?; self.arguments.to_css(dest, is_custom_property)?; @@ -1554,13 +1549,14 @@ impl<'i> UnresolvedColor<'i> { } } - fn to_css(&self, dest: &mut Printer, is_custom_property: bool) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css( + &self, + dest: &mut PrinterT, + is_custom_property: bool, + ) -> Result<(), PrinterError> { match self { UnresolvedColor::RGB { r, g, b, alpha } => { - if should_compile!(dest.targets.current, SpaceSeparatedColorNotation) { + if should_compile!(dest.targets().current, SpaceSeparatedColorNotation) { dest.write_str("rgba(")?; r.to_css(dest)?; dest.delim(',', false)?; @@ -1585,7 +1581,7 @@ impl<'i> UnresolvedColor<'i> { Ok(()) } UnresolvedColor::HSL { h, s, l, alpha } => { - if should_compile!(dest.targets.current, SpaceSeparatedColorNotation) { + if should_compile!(dest.targets().current, SpaceSeparatedColorNotation) { dest.write_str("hsla(")?; h.to_css(dest)?; dest.delim(',', false)?; @@ -1610,7 +1606,7 @@ impl<'i> UnresolvedColor<'i> { Ok(()) } UnresolvedColor::LightDark { light, dark } => { - if should_compile!(dest.targets.current, LightDark) { + if should_compile!(dest.targets().current, LightDark) { dest.write_str("var(--lightningcss-light")?; dest.delim(',', false)?; light.to_css(dest, is_custom_property)?; diff --git a/src/properties/display.rs b/src/properties/display.rs index a82e30ab..e1b06930 100644 --- a/src/properties/display.rs +++ b/src/properties/display.rs @@ -7,13 +7,11 @@ use crate::declaration::DeclarationList; use crate::error::{ParserError, PrinterError}; use crate::macros::enum_property; use crate::prefixes::{is_flex_2009, Feature}; -use crate::printer::Printer; use crate::traits::{Parse, PropertyHandler, ToCss}; use crate::vendor_prefix::VendorPrefix; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; enum_property! { /// A [``](https://drafts.csswg.org/css-display-3/#typedef-display-outside) value. @@ -68,10 +66,7 @@ impl<'i> Parse<'i> for DisplayInside { } impl ToCss for DisplayInside { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { DisplayInside::Flow => dest.write_str("flow")?, DisplayInside::FlowRoot => dest.write_str("flow-root")?, @@ -228,10 +223,7 @@ impl<'i> Parse<'i> for DisplayPair { } impl ToCss for DisplayPair { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { DisplayPair { outside: DisplayOutside::Inline, diff --git a/src/properties/effects.rs b/src/properties/effects.rs index 0979cd73..85a157f8 100644 --- a/src/properties/effects.rs +++ b/src/properties/effects.rs @@ -2,7 +2,6 @@ use crate::error::{ParserError, PrinterError}; use crate::macros::enum_property; -use crate::printer::Printer; use crate::targets::{Browsers, Targets}; use crate::traits::{FallbackValues, IsCompatible, Parse, ToCss, Zero}; use crate::values::color::ColorFallbackKind; @@ -12,7 +11,6 @@ use crate::values::{angle::Angle, color::CssColor, length::Length, percentage::N use crate::visitor::Visit; use cssparser::*; use smallvec::SmallVec; -use std::fmt::Write; /// A [filter](https://drafts.fxtf.org/filter-effects-1/#filter-functions) function. #[derive(Debug, Clone, PartialEq)] @@ -118,10 +116,7 @@ impl<'i> Parse<'i> for Filter<'i> { } impl<'i> ToCss for Filter<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { Filter::Blur(val) => { dest.write_str("blur(")?; @@ -290,10 +285,7 @@ impl<'i> Parse<'i> for DropShadow { } impl ToCss for DropShadow { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.x_offset.to_css(dest)?; dest.write_char(' ')?; self.y_offset.to_css(dest)?; @@ -356,10 +348,7 @@ impl<'i> Parse<'i> for FilterList<'i> { } impl<'i> ToCss for FilterList<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { FilterList::None => { dest.write_str("none")?; diff --git a/src/properties/flex.rs b/src/properties/flex.rs index 2ec6f884..430006ae 100644 --- a/src/properties/flex.rs +++ b/src/properties/flex.rs @@ -9,7 +9,6 @@ use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::macros::*; use crate::prefixes::{is_flex_2009, Feature}; -use crate::printer::Printer; use crate::traits::{FromStandard, Parse, PropertyHandler, Shorthand, ToCss, Zero}; use crate::values::number::{CSSInteger, CSSNumber, NonNegative}; use crate::values::{ @@ -20,7 +19,6 @@ use crate::vendor_prefix::VendorPrefix; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; enum_property! { /// A value for the [flex-direction](https://www.w3.org/TR/2018/CR-css-flexbox-1-20181119/#propdef-flex-direction) property. @@ -104,10 +102,7 @@ impl<'i> Parse<'i> for FlexFlow { } impl ToCss for FlexFlow { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let mut needs_space = false; if self.direction != FlexDirection::default() || self.wrap == FlexWrap::default() { self.direction.to_css(dest)?; @@ -181,10 +176,7 @@ impl<'i> Parse<'i> for Flex { } impl ToCss for Flex { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if self.grow.0 == 0.0 && self.shrink.0 == 0.0 && self.basis.0 == LengthPercentageOrAuto::Auto { dest.write_str("none")?; return Ok(()); diff --git a/src/properties/font.rs b/src/properties/font.rs index f59b9b45..df6a3010 100644 --- a/src/properties/font.rs +++ b/src/properties/font.rs @@ -1,7 +1,6 @@ //! CSS properties related to fonts. use std::collections::HashSet; -use std::fmt::Write; use super::{Property, PropertyId}; use crate::compat::Feature; @@ -9,7 +8,6 @@ use crate::context::PropertyHandlerContext; use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::macros::*; -use crate::printer::Printer; use crate::targets::should_compile; use crate::traits::{IsCompatible, Parse, PropertyHandler, Shorthand, ToCss}; use crate::values::length::LengthValue; @@ -82,15 +80,12 @@ impl Default for AbsoluteFontWeight { } impl ToCss for AbsoluteFontWeight { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { use AbsoluteFontWeight::*; match self { Weight(val) => val.to_css(dest)?, - Normal => dest.write_str(if dest.minify { "400" } else { "normal" })?, - Bold => dest.write_str(if dest.minify { "700" } else { "bold" })?, + Normal => dest.write_str(if dest.options().minify { "400" } else { "normal" })?, + Bold => dest.write_str(if dest.options().minify { "700" } else { "bold" })?, }; Ok(()) } @@ -264,11 +259,8 @@ impl Into for &FontStretch { } impl ToCss for FontStretch { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { - if dest.minify { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { + if dest.options().minify { let percentage: Percentage = self.into(); return percentage.to_css(dest); } @@ -365,10 +357,7 @@ impl<'i> Parse<'i> for FontFamily<'i> { } impl<'i> ToCss for FontFamily<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { FontFamily::Generic(val) => val.to_css(dest), FontFamily::FamilyName(val) => val.to_css(dest), @@ -414,10 +403,7 @@ impl<'i> Parse<'i> for FamilyName<'i> { } impl<'i> ToCss for FamilyName<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { // Generic family names such as sans-serif must be quoted if parsed as a string. // CSS wide keywords, as well as "default", must also be quoted. // https://www.w3.org/TR/css-fonts-4/#family-name-syntax @@ -510,10 +496,7 @@ impl<'i> Parse<'i> for FontStyle { } impl ToCss for FontStyle { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { FontStyle::Normal => dest.write_str("normal")?, FontStyle::Italic => dest.write_str("italic")?, @@ -758,10 +741,7 @@ impl<'i> Parse<'i> for Font<'i> { } impl<'i> ToCss for Font<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if self.style != FontStyle::default() { self.style.to_css(dest)?; dest.write_char(' ')?; diff --git a/src/properties/grid.rs b/src/properties/grid.rs index b4a20bc9..79da1251 100644 --- a/src/properties/grid.rs +++ b/src/properties/grid.rs @@ -2,13 +2,10 @@ #![allow(non_upper_case_globals)] -use std::fmt::Write; - use crate::context::PropertyHandlerContext; use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{Error, ErrorLocation, ParserError, PrinterError, PrinterErrorKind}; use crate::macros::{define_shorthand, impl_shorthand}; -use crate::printer::Printer; use crate::properties::{Property, PropertyId}; use crate::traits::{Parse, PropertyHandler, Shorthand, ToCss}; use crate::values::ident::CustomIdent; @@ -222,10 +219,7 @@ impl<'i> Parse<'i> for TrackSize { } impl ToCss for TrackSize { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { TrackSize::TrackBreadth(breadth) => breadth.to_css(dest), TrackSize::MinMax { min, max } => { @@ -293,10 +287,7 @@ impl TrackBreadth { } impl ToCss for TrackBreadth { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { TrackBreadth::Auto => { dest.write_str("auto")?; @@ -348,10 +339,7 @@ impl<'i> Parse<'i> for TrackRepeat<'i> { } impl<'i> ToCss for TrackRepeat<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { dest.write_str("repeat(")?; self.count.to_css(dest)?; dest.delim(',', false)?; @@ -395,10 +383,10 @@ fn parse_line_names<'i, 't>( }) } -fn serialize_line_names(names: &[CustomIdent], dest: &mut Printer) -> Result<(), PrinterError> -where - W: std::fmt::Write, -{ +fn serialize_line_names( + names: &[CustomIdent], + dest: &mut PrinterT, +) -> Result<(), PrinterError> { dest.write_char('[')?; let mut first = true; for name in names { @@ -413,28 +401,26 @@ where Ok(()) } -fn write_ident(name: &str, dest: &mut Printer) -> Result<(), PrinterError> -where - W: std::fmt::Write, -{ - let css_module_grid_enabled = dest.css_module.as_ref().map_or(false, |css_module| css_module.config.grid); - if css_module_grid_enabled { - if let Some(css_module) = &mut dest.css_module { - if let Some(last) = css_module.config.pattern.segments.last() { - if !matches!(last, crate::css_modules::Segment::Local) { - return Err(Error { - kind: PrinterErrorKind::InvalidCssModulesPatternInGrid, - loc: Some(ErrorLocation { - filename: dest.filename().into(), - line: dest.loc.line, - column: dest.loc.column, - }), - }); - } +fn write_ident( + name: &str, + dest: &mut PrinterT, +) -> Result<(), PrinterError> { + let config = dest.css_module_config().filter(|config| config.grid); + if let Some(config) = config { + if let Some(last) = config.pattern.segments.last() { + if !matches!(last, crate::css_modules::Segment::Local) { + return Err(Error { + kind: PrinterErrorKind::InvalidCssModulesPatternInGrid, + loc: Some(ErrorLocation { + filename: dest.filename().into(), + line: dest.loc().line, + column: dest.loc().column, + }), + }); } } } - dest.write_ident(name, css_module_grid_enabled)?; + dest.write_ident(name, config.is_some())?; Ok(()) } @@ -467,10 +453,7 @@ impl<'i> Parse<'i> for TrackList<'i> { } impl<'i> ToCss for TrackList<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let mut items_iter = self.items.iter(); let line_names_iter = self.line_names.iter(); let mut first = true; @@ -529,10 +512,7 @@ impl<'i> Parse<'i> for TrackSizeList { } impl ToCss for TrackSizeList { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if self.0.len() == 0 { dest.write_str("auto")?; return Ok(()); @@ -644,10 +624,7 @@ fn is_name_code_point(c: char) -> bool { } impl ToCss for GridTemplateAreas { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { GridTemplateAreas::None => { dest.write_str("none")?; @@ -658,7 +635,7 @@ impl ToCss for GridTemplateAreas { let mut next = iter.next(); let mut first = true; while next.is_some() { - if !first && !dest.minify { + if !first && !dest.options().minify { dest.newline()?; } @@ -666,14 +643,14 @@ impl ToCss for GridTemplateAreas { if first { first = false; - if !dest.minify { + if !dest.options().minify { // Indent by the width of "grid-template-areas: ", so the rows line up. dest.indent_by(21); } } } - if !dest.minify { + if !dest.options().minify { dest.dedent_by(21); } @@ -684,15 +661,12 @@ impl ToCss for GridTemplateAreas { } impl GridTemplateAreas { - fn write_string<'a, W>( + fn write_string<'a, PrinterT: crate::printer::PrinterTrait>( &self, - dest: &mut Printer, + dest: &mut PrinterT, iter: &mut std::slice::Iter<'a, Option>, next: &mut Option<&'a Option>, - ) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + ) -> Result<(), PrinterError> { let columns = match self { GridTemplateAreas::Areas { columns, .. } => *columns, _ => unreachable!(), @@ -704,13 +678,13 @@ impl GridTemplateAreas { for i in 0..columns { if let Some(token) = next { if let Some(string) = token { - if i > 0 && (!last_was_null || !dest.minify) { + if i > 0 && (!last_was_null || !dest.options().minify) { dest.write_char(' ')?; } write_ident(string, dest)?; last_was_null = false; } else { - if i > 0 && (last_was_null || !dest.minify) { + if i > 0 && (last_was_null || !dest.options().minify) { dest.write_char(' ')?; } dest.write_char('.')?; @@ -828,19 +802,17 @@ impl<'i> Parse<'i> for GridTemplate<'i> { } impl ToCss for GridTemplate<'_> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.to_css_with_indent(dest, 15) } } impl GridTemplate<'_> { - fn to_css_with_indent(&self, dest: &mut Printer, indent: u8) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css_with_indent( + &self, + dest: &mut PrinterT, + indent: u8, + ) -> Result<(), PrinterError> { match &self.areas { GridTemplateAreas::None => { if self.rows == TrackSizing::None && self.columns == TrackSizing::None { @@ -867,7 +839,7 @@ impl GridTemplate<'_> { while next.is_some() { macro_rules! newline { () => { - if !dest.minify { + if !dest.options().minify { if !indented { // Indent by the width of "grid-template: ", so the rows line up. dest.indent_by(indent); @@ -880,7 +852,7 @@ impl GridTemplate<'_> { if let Some(line_names) = line_names_iter.next() { if !line_names.is_empty() { - if !dest.minify && line_names.len() == 2 { + if !dest.options().minify && line_names.len() == 2 { dest.whitespace()?; serialize_line_names(&line_names[0..1], dest)?; newline!(); @@ -1104,16 +1076,13 @@ impl<'i> Parse<'i> for GridAutoFlow { } impl ToCss for GridAutoFlow { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let s = if *self == GridAutoFlow::Row { "row" } else if *self == GridAutoFlow::Column { "column" } else if *self == GridAutoFlow::Row | GridAutoFlow::Dense { - if dest.minify { + if dest.options().minify { "dense" } else { "row dense" @@ -1224,10 +1193,7 @@ fn parse_grid_auto_flow<'i, 't>( } impl ToCss for Grid<'_> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let is_auto_initial = self.auto_rows == TrackSizeList::default() && self.auto_columns == TrackSizeList::default() && self.auto_flow == GridAutoFlow::default(); @@ -1455,10 +1421,7 @@ impl<'i> Parse<'i> for GridLine<'i> { } impl ToCss for GridLine<'_> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { GridLine::Auto => { dest.write_str("auto")?; @@ -1527,10 +1490,7 @@ macro_rules! impl_grid_placement { } impl ToCss for $name<'_> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.start.to_css(dest)?; if !self.start.can_omit_end(&self.end) { @@ -1636,10 +1596,7 @@ impl<'i> Parse<'i> for GridArea<'i> { } impl ToCss for GridArea<'_> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.row_start.to_css(dest)?; let can_omit_column_end = self.column_start.can_omit_end(&self.column_end); diff --git a/src/properties/list.rs b/src/properties/list.rs index 84a04e9e..4ac43a57 100644 --- a/src/properties/list.rs +++ b/src/properties/list.rs @@ -5,7 +5,6 @@ use crate::context::PropertyHandlerContext; use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::macros::{define_shorthand, enum_property, shorthand_handler}; -use crate::printer::Printer; use crate::targets::{Browsers, Targets}; use crate::traits::{FallbackValues, IsCompatible, Parse, PropertyHandler, Shorthand, ToCss}; use crate::values::string::CSSString; @@ -13,7 +12,6 @@ use crate::values::{ident::CustomIdent, image::Image}; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; /// A value for the [list-style-type](https://www.w3.org/TR/2020/WD-css-lists-3-20201117/#text-markers) property. #[derive(Debug, Clone, PartialEq, Parse, ToCss)] @@ -214,16 +212,12 @@ impl<'i> Parse<'i> for CounterStyle<'i> { } impl ToCss for CounterStyle<'_> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { CounterStyle::Predefined(style) => style.to_css(dest), CounterStyle::Name(name) => { - if let Some(css_module) = &mut dest.css_module { - css_module.reference(&name.0, dest.loc.source_index) - } + let source_index = dest.loc().source_index; + dest.with_css_module_mut(|css_module| css_module.reference(&name.0, source_index)); name.to_css(dest) } CounterStyle::Symbols { system: t, symbols } => { @@ -414,10 +408,7 @@ impl<'i> Parse<'i> for ListStyle<'i> { } impl<'i> ToCss for ListStyle<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let mut needs_space = false; if self.position != ListStylePosition::default() { self.position.to_css(dest)?; diff --git a/src/properties/margin_padding.rs b/src/properties/margin_padding.rs index c467ed95..31f7feaf 100644 --- a/src/properties/margin_padding.rs +++ b/src/properties/margin_padding.rs @@ -4,7 +4,6 @@ use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::logical::PropertyCategory; use crate::macros::{define_shorthand, rect_shorthand, size_shorthand}; -use crate::printer::Printer; use crate::properties::{Property, PropertyId}; use crate::traits::{IsCompatible, Parse, PropertyHandler, Shorthand, ToCss}; use crate::values::number::NonNegative; diff --git a/src/properties/masking.rs b/src/properties/masking.rs index e9f89b36..0899dd4d 100644 --- a/src/properties/masking.rs +++ b/src/properties/masking.rs @@ -8,7 +8,6 @@ use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::macros::{define_list_shorthand, define_shorthand, enum_property, property_bitflags}; use crate::prefixes::Feature; -use crate::printer::Printer; use crate::properties::Property; use crate::targets::{Browsers, Targets}; use crate::traits::{FallbackValues, IsCompatible, Parse, PropertyHandler, Shorthand, ToCss}; @@ -23,7 +22,6 @@ use crate::visitor::Visit; use cssparser::*; use itertools::izip; use smallvec::SmallVec; -use std::fmt::Write; enum_property! { /// A value for the [mask-type](https://www.w3.org/TR/css-masking-1/#the-mask-type) property. @@ -312,10 +310,7 @@ impl<'i> Parse<'i> for Mask<'i> { } impl<'i> ToCss for Mask<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.image.to_css(dest)?; if self.position != Position::default() || self.size != BackgroundSize::default() { @@ -429,10 +424,7 @@ impl<'i> Parse<'i> for ClipPath<'i> { } impl<'i> ToCss for ClipPath<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { ClipPath::None => { dest.write_str("none")?; @@ -521,10 +513,7 @@ impl<'i> Parse<'i> for MaskBorder<'i> { } impl<'i> ToCss for MaskBorder<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { BorderImage::to_css_internal(&self.source, &self.slice, &self.width, &self.outset, &self.repeat, dest)?; if self.mode != MaskBorderMode::default() { dest.write_char(' ')?; diff --git a/src/properties/mod.rs b/src/properties/mod.rs index 1b5b6ead..bc1da477 100644 --- a/src/properties/mod.rs +++ b/src/properties/mod.rs @@ -90,8 +90,6 @@ #![deny(missing_docs)] -use std::fmt::Write; - pub mod align; pub mod animation; pub mod background; @@ -247,7 +245,7 @@ macro_rules! define_properties { } impl<'i> ToCss for PropertyId<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> where W: std::fmt::Write { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let mut first = true; macro_rules! delim { () => { @@ -774,7 +772,7 @@ macro_rules! define_properties { } /// Serializes the value of a CSS property without its name or `!important` flag. - pub fn value_to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> where W: std::fmt::Write { + pub fn value_to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { use Property::*; match self { @@ -803,7 +801,7 @@ macro_rules! define_properties { } /// Serializes the CSS property, with an optional `!important` flag. - pub fn to_css(&self, dest: &mut Printer, important: bool) -> Result<(), PrinterError> where W: std::fmt::Write { + pub fn to_css(&self, dest: &mut PrinterT, important: bool) -> Result<(), PrinterError> { use Property::*; let mut first = true; @@ -1644,10 +1642,7 @@ impl<'i, T: smallvec::Array, V: Parse<'i>> Parse<'i> for SmallVec { } impl, V: ToCss> ToCss for SmallVec { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let len = self.len(); for (idx, val) in self.iter().enumerate() { val.to_css(dest)?; @@ -1666,10 +1661,7 @@ impl<'i, T: Parse<'i>> Parse<'i> for Vec { } impl ToCss for Vec { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let len = self.len(); for (idx, val) in self.iter().enumerate() { val.to_css(dest)?; diff --git a/src/properties/outline.rs b/src/properties/outline.rs index 839147c7..87c30347 100644 --- a/src/properties/outline.rs +++ b/src/properties/outline.rs @@ -6,14 +6,12 @@ use crate::context::PropertyHandlerContext; use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::macros::{impl_shorthand, shorthand_handler}; -use crate::printer::Printer; use crate::targets::Browsers; use crate::traits::{FallbackValues, IsCompatible, Parse, PropertyHandler, Shorthand, ToCss}; use crate::values::color::CssColor; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; /// A value for the [outline-style](https://drafts.csswg.org/css-ui/#outline-style) property. #[derive(Debug, Clone, PartialEq, Parse, ToCss)] diff --git a/src/properties/overflow.rs b/src/properties/overflow.rs index 3c6b9e51..6ccfb720 100644 --- a/src/properties/overflow.rs +++ b/src/properties/overflow.rs @@ -6,12 +6,10 @@ use crate::context::PropertyHandlerContext; use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::macros::{define_shorthand, enum_property}; -use crate::printer::Printer; use crate::traits::{Parse, PropertyHandler, Shorthand, ToCss}; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; enum_property! { /// An [overflow](https://www.w3.org/TR/css-overflow-3/#overflow-properties) keyword @@ -49,10 +47,7 @@ impl<'i> Parse<'i> for Overflow { } impl ToCss for Overflow { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.x.to_css(dest)?; if self.y != self.x { dest.write_char(' ')?; diff --git a/src/properties/position.rs b/src/properties/position.rs index 3bd40b56..85617632 100644 --- a/src/properties/position.rs +++ b/src/properties/position.rs @@ -5,14 +5,12 @@ use crate::context::PropertyHandlerContext; use crate::declaration::DeclarationList; use crate::error::{ParserError, PrinterError}; use crate::prefixes::Feature; -use crate::printer::Printer; use crate::traits::{Parse, PropertyHandler, ToCss}; use crate::values::number::CSSInteger; use crate::vendor_prefix::VendorPrefix; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; /// A value for the [position](https://www.w3.org/TR/css-position-3/#position-property) property. #[derive(Debug, Clone, PartialEq)] @@ -56,10 +54,7 @@ impl<'i> Parse<'i> for Position { } impl ToCss for Position { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { Position::Static => { dest.write_str("static")?; diff --git a/src/properties/size.rs b/src/properties/size.rs index 1ca771ee..c252c672 100644 --- a/src/properties/size.rs +++ b/src/properties/size.rs @@ -6,7 +6,6 @@ use crate::declaration::DeclarationList; use crate::error::{ParserError, PrinterError}; use crate::logical::PropertyCategory; use crate::macros::{enum_property, property_bitflags}; -use crate::printer::Printer; use crate::properties::{Property, PropertyId}; use crate::targets::Targets; use crate::traits::{IsCompatible, Parse, PropertyHandler, ToCss}; @@ -17,7 +16,6 @@ use crate::vendor_prefix::VendorPrefix; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; #[cfg(feature = "serde")] use crate::serialization::*; @@ -98,10 +96,7 @@ impl<'i> Parse<'i> for Size { } impl ToCss for Size { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { use Size::*; match self { Auto => { @@ -250,10 +245,7 @@ impl<'i> Parse<'i> for MaxSize { } impl ToCss for MaxSize { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { use MaxSize::*; match self { None => { @@ -448,10 +440,7 @@ impl<'i> Parse<'i> for AspectRatio { } impl ToCss for AspectRatio { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if self.auto { dest.write_str("auto")?; } diff --git a/src/properties/svg.rs b/src/properties/svg.rs index ea9657cd..7bd9186a 100644 --- a/src/properties/svg.rs +++ b/src/properties/svg.rs @@ -2,7 +2,6 @@ use crate::error::{ParserError, PrinterError}; use crate::macros::enum_property; -use crate::printer::Printer; use crate::targets::{Browsers, Targets}; use crate::traits::{FallbackValues, IsCompatible, Parse, ToCss}; use crate::values::length::LengthPercentage; @@ -11,7 +10,6 @@ use crate::values::{color::CssColor, url::Url}; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; /// An SVG [``](https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint) value /// used in the `fill` and `stroke` properties. @@ -171,10 +169,7 @@ impl<'i> Parse<'i> for StrokeDasharray { } impl ToCss for StrokeDasharray { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { StrokeDasharray::None => { dest.write_str("none")?; diff --git a/src/properties/text.rs b/src/properties/text.rs index 5d4f3c90..5af04bb9 100644 --- a/src/properties/text.rs +++ b/src/properties/text.rs @@ -2,8 +2,6 @@ #![allow(non_upper_case_globals)] -use std::fmt::Write; - use super::{Property, PropertyId}; use crate::compat; use crate::context::PropertyHandlerContext; @@ -11,7 +9,6 @@ use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::macros::{define_shorthand, enum_property}; use crate::prefixes::Feature; -use crate::printer::Printer; use crate::targets::{should_compile, Browsers, Targets}; use crate::traits::{FallbackValues, IsCompatible, Parse, PropertyHandler, Shorthand, ToCss, Zero}; use crate::values::calc::{Calc, MathFunction}; @@ -79,10 +76,7 @@ impl<'i> Parse<'i> for TextTransformOther { } impl ToCss for TextTransformOther { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let mut needs_space = false; if self.contains(TextTransformOther::FullWidth) { dest.write_str("full-width")?; @@ -199,10 +193,7 @@ impl<'i> Parse<'i> for TextTransform { } impl ToCss for TextTransform { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let mut needs_space = false; if self.case != TextTransformCase::None || self.other.is_empty() { self.case.to_css(dest)?; @@ -430,10 +421,7 @@ impl<'i> Parse<'i> for TextIndent { } impl ToCss for TextIndent { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.value.to_css(dest)?; if self.hanging { dest.write_str(" hanging")?; @@ -534,10 +522,7 @@ impl<'i> Parse<'i> for TextDecorationLine { } impl ToCss for TextDecorationLine { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if self.is_empty() { dest.write_str("none")?; return Ok(()); @@ -778,10 +763,7 @@ impl<'i> Parse<'i> for TextDecoration { } impl ToCss for TextDecoration { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.line.to_css(dest)?; if self.line.is_empty() { return Ok(()); @@ -926,10 +908,7 @@ impl<'i> Parse<'i> for TextEmphasisStyle<'i> { } impl<'i> ToCss for TextEmphasisStyle<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { TextEmphasisStyle::None => { dest.write_str("none")?; @@ -997,10 +976,7 @@ impl<'i> Parse<'i> for TextEmphasis<'i> { } impl<'i> ToCss for TextEmphasis<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.style.to_css(dest)?; if self.style != TextEmphasisStyle::None && self.color != CssColor::current_color() { @@ -1092,10 +1068,7 @@ impl Default for BoxDecorationBreak { } impl ToCss for TextEmphasisPosition { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.vertical.to_css(dest)?; if self.horizontal != TextEmphasisPositionHorizontal::Right { dest.write_char(' ')?; @@ -1448,10 +1421,7 @@ impl<'i> Parse<'i> for TextShadow { } impl ToCss for TextShadow { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.x_offset.to_css(dest)?; dest.write_char(' ')?; self.y_offset.to_css(dest)?; diff --git a/src/properties/transform.rs b/src/properties/transform.rs index a6e90631..40576983 100644 --- a/src/properties/transform.rs +++ b/src/properties/transform.rs @@ -6,7 +6,6 @@ use crate::declaration::DeclarationList; use crate::error::{ParserError, PrinterError}; use crate::macros::enum_property; use crate::prefixes::Feature; -use crate::printer::Printer; use crate::traits::{Parse, PropertyHandler, ToCss, Zero}; use crate::values::number::NonNegative; use crate::values::{ @@ -19,7 +18,6 @@ use crate::vendor_prefix::VendorPrefix; use crate::visitor::Visit; use cssparser::*; use std::f32::consts::PI; -use std::fmt::Write; /// A value for the [transform](https://www.w3.org/TR/2019/CR-css-transforms-1-20190214/#propdef-transform) property. #[derive(Debug, Clone, PartialEq, Default)] @@ -49,10 +47,7 @@ impl<'i> Parse<'i> for TransformList { } impl ToCss for TransformList { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if self.0.is_empty() { dest.write_str("none")?; return Ok(()); @@ -60,7 +55,7 @@ impl ToCss for TransformList { // TODO: Re-enable with a better solution // See: https://github.com/parcel-bundler/lightningcss/issues/288 - // if dest.minify { + // if dest.options().minify { // // Combine transforms into a single matrix. // if let Some(matrix) = self.to_matrix() { // // Generate based on the original transforms. @@ -124,10 +119,7 @@ impl ToCss for TransformList { } impl TransformList { - fn to_css_base(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css_base(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let mut first = true; for item in &self.0 { if first { @@ -1024,14 +1016,11 @@ impl<'i> Parse<'i> for Transform { } impl ToCss for Transform { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { use Transform::*; match self { Translate(x, y) => { - if dest.minify && x.is_zero() && !y.is_zero() { + if dest.options().minify && x.is_zero() && !y.is_zero() { dest.write_str("translateY(")?; y.to_css(dest)? } else { @@ -1046,7 +1035,11 @@ impl ToCss for Transform { Ok(()) } TranslateX(x) => { - dest.write_str(if dest.minify { "translate(" } else { "translateX(" })?; + dest.write_str(if dest.options().minify { + "translate(" + } else { + "translateX(" + })?; x.to_css(dest)?; dest.write_char(')')?; Ok(()) @@ -1064,16 +1057,16 @@ impl ToCss for Transform { Ok(()) } Translate3d(x, y, z) => { - if dest.minify && y.is_zero() && z.is_zero() { + if dest.options().minify && y.is_zero() && z.is_zero() { dest.write_str("translate(")?; x.to_css(dest)?; - } else if dest.minify && x.is_zero() && !y.is_zero() && z.is_zero() { + } else if dest.options().minify && x.is_zero() && !y.is_zero() && z.is_zero() { dest.write_str("translateY(")?; y.to_css(dest)?; - } else if dest.minify && x.is_zero() && y.is_zero() && !z.is_zero() { + } else if dest.options().minify && x.is_zero() && y.is_zero() && !z.is_zero() { dest.write_str("translateZ(")?; z.to_css(dest)?; - } else if dest.minify && z.is_zero() { + } else if dest.options().minify && z.is_zero() { dest.write_str("translate(")?; x.to_css(dest)?; dest.delim(',', false)?; @@ -1092,10 +1085,10 @@ impl ToCss for Transform { Scale(x, y) => { let x: f32 = x.into(); let y: f32 = y.into(); - if dest.minify && x == 1.0 && y != 1.0 { + if dest.options().minify && x == 1.0 && y != 1.0 { dest.write_str("scaleY(")?; y.to_css(dest)?; - } else if dest.minify && x != 1.0 && y == 1.0 { + } else if dest.options().minify && x != 1.0 && y == 1.0 { dest.write_str("scaleX(")?; x.to_css(dest)?; } else { @@ -1134,23 +1127,23 @@ impl ToCss for Transform { let x: f32 = x.into(); let y: f32 = y.into(); let z: f32 = z.into(); - if dest.minify && z == 1.0 && x == y { + if dest.options().minify && z == 1.0 && x == y { // scale3d(x, x, 1) => scale(x) dest.write_str("scale(")?; x.to_css(dest)?; - } else if dest.minify && x != 1.0 && y == 1.0 && z == 1.0 { + } else if dest.options().minify && x != 1.0 && y == 1.0 && z == 1.0 { // scale3d(x, 1, 1) => scaleX(x) dest.write_str("scaleX(")?; x.to_css(dest)?; - } else if dest.minify && x == 1.0 && y != 1.0 && z == 1.0 { + } else if dest.options().minify && x == 1.0 && y != 1.0 && z == 1.0 { // scale3d(1, y, 1) => scaleY(y) dest.write_str("scaleY(")?; y.to_css(dest)?; - } else if dest.minify && x == 1.0 && y == 1.0 && z != 1.0 { + } else if dest.options().minify && x == 1.0 && y == 1.0 && z != 1.0 { // scale3d(1, 1, z) => scaleZ(z) dest.write_str("scaleZ(")?; z.to_css(dest)?; - } else if dest.minify && z == 1.0 { + } else if dest.options().minify && z == 1.0 { // scale3d(x, y, 1) => scale(x, y) dest.write_str("scale(")?; x.to_css(dest)?; @@ -1186,21 +1179,21 @@ impl ToCss for Transform { Ok(()) } RotateZ(angle) => { - dest.write_str(if dest.minify { "rotate(" } else { "rotateZ(" })?; + dest.write_str(if dest.options().minify { "rotate(" } else { "rotateZ(" })?; angle.to_css_with_unitless_zero(dest)?; dest.write_char(')')?; Ok(()) } Rotate3d(x, y, z, angle) => { - if dest.minify && *x == 1.0 && *y == 0.0 && *z == 0.0 { + if dest.options().minify && *x == 1.0 && *y == 0.0 && *z == 0.0 { // rotate3d(1, 0, 0, a) => rotateX(a) dest.write_str("rotateX(")?; angle.to_css_with_unitless_zero(dest)?; - } else if dest.minify && *x == 0.0 && *y == 1.0 && *z == 0.0 { + } else if dest.options().minify && *x == 0.0 && *y == 1.0 && *z == 0.0 { // rotate3d(0, 1, 0, a) => rotateY(a) dest.write_str("rotateY(")?; angle.to_css_with_unitless_zero(dest)?; - } else if dest.minify && *x == 0.0 && *y == 0.0 && *z == 1.0 { + } else if dest.options().minify && *x == 0.0 && *y == 0.0 && *z == 1.0 { // rotate3d(0, 0, 1, a) => rotate(a) dest.write_str("rotate(")?; angle.to_css_with_unitless_zero(dest)?; @@ -1218,7 +1211,7 @@ impl ToCss for Transform { Ok(()) } Skew(x, y) => { - if dest.minify && x.is_zero() && !y.is_zero() { + if dest.options().minify && x.is_zero() && !y.is_zero() { dest.write_str("skewY(")?; y.to_css_with_unitless_zero(dest)? } else { @@ -1233,7 +1226,7 @@ impl ToCss for Transform { Ok(()) } SkewX(angle) => { - dest.write_str(if dest.minify { "skew(" } else { "skewX(" })?; + dest.write_str(if dest.options().minify { "skew(" } else { "skewX(" })?; angle.to_css_with_unitless_zero(dest)?; dest.write_char(')')?; Ok(()) @@ -1495,10 +1488,7 @@ impl<'i> Parse<'i> for Translate { } impl ToCss for Translate { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { Translate::None => { dest.write_str("none")?; @@ -1596,10 +1586,7 @@ impl<'i> Parse<'i> for Rotate { } impl ToCss for Rotate { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { Rotate::None => { dest.write_str("none")?; @@ -1704,10 +1691,7 @@ impl<'i> Parse<'i> for Scale { } impl ToCss for Scale { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { Scale::None => { dest.write_str("none")?; diff --git a/src/properties/transition.rs b/src/properties/transition.rs index 892281db..3fa67240 100644 --- a/src/properties/transition.rs +++ b/src/properties/transition.rs @@ -7,7 +7,6 @@ use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::macros::define_list_shorthand; use crate::prefixes::Feature; -use crate::printer::Printer; use crate::properties::masking::get_webkit_mask_property; use crate::traits::{Parse, PropertyHandler, Shorthand, ToCss, Zero}; use crate::values::ident::CustomIdent; @@ -19,7 +18,6 @@ use crate::visitor::Visit; use cssparser::*; use itertools::izip; use smallvec::SmallVec; -use std::fmt::Write; define_list_shorthand! { /// A value for the [transition](https://www.w3.org/TR/2018/WD-css-transitions-1-20181011/#transition-shorthand-property) property. @@ -86,10 +84,7 @@ impl<'i> Parse<'i> for Transition<'i> { } impl<'i> ToCss for Transition<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.property.to_css(dest)?; if !self.duration.is_zero() || !self.delay.is_zero() { dest.write_char(' ')?; diff --git a/src/properties/ui.rs b/src/properties/ui.rs index a6fa1789..887ec1b0 100644 --- a/src/properties/ui.rs +++ b/src/properties/ui.rs @@ -4,7 +4,6 @@ use crate::context::PropertyHandlerContext; use crate::declaration::{DeclarationBlock, DeclarationList}; use crate::error::{ParserError, PrinterError}; use crate::macros::{define_shorthand, enum_property, shorthand_property}; -use crate::printer::Printer; use crate::properties::{Property, PropertyId}; use crate::targets::{should_compile, Browsers, Targets}; use crate::traits::{FallbackValues, IsCompatible, Parse, PropertyHandler, Shorthand, ToCss}; @@ -17,7 +16,6 @@ use crate::visitor::Visit; use bitflags::bitflags; use cssparser::*; use smallvec::SmallVec; -use std::fmt::Write; use super::custom::Token; use super::{CustomProperty, CustomPropertyName, TokenList, TokenOrValue}; @@ -71,10 +69,7 @@ impl<'i> Parse<'i> for CursorImage<'i> { } impl<'i> ToCss for CursorImage<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.url.to_css(dest)?; if let Some((x, y)) = self.hotspot { @@ -166,10 +161,7 @@ impl<'i> Parse<'i> for Cursor<'i> { } impl<'i> ToCss for Cursor<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { for image in &self.images { image.to_css(dest)?; dest.delim(',', false)?; @@ -368,10 +360,7 @@ impl<'i> Parse<'i> for Appearance<'i> { } impl<'i> ToCss for Appearance<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { dest.write_str(self.to_str())?; Ok(()) } @@ -477,10 +466,7 @@ impl<'i> Parse<'i> for ColorScheme { } impl ToCss for ColorScheme { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if self.is_empty() { dest.write_str("normal")?; return Ok(()); diff --git a/src/rules/container.rs b/src/rules/container.rs index 0b8c341a..03823eaa 100644 --- a/src/rules/container.rs +++ b/src/rules/container.rs @@ -1,7 +1,6 @@ //! The `@container` rule. use cssparser::*; -use std::fmt::Write; use super::Location; use super::{CssRuleList, MinifyContext}; @@ -11,7 +10,6 @@ use crate::media_query::{ MediaFeatureType, Operator, QueryCondition, QueryConditionFlags, QueryFeature, ValueType, }; use crate::parser::{DefaultAtRule, ParserOptions}; -use crate::printer::Printer; use crate::properties::custom::TokenList; use crate::properties::{Property, PropertyId}; #[cfg(feature = "serde")] @@ -100,10 +98,11 @@ define_query_features! { } impl FeatureToCss for ContainerSizeFeatureId { - fn to_css_with_prefix(&self, prefix: &str, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css_with_prefix( + &self, + prefix: &str, + dest: &mut PrinterT, + ) -> Result<(), PrinterError> { dest.write_str(prefix)?; self.to_css(dest) } @@ -187,10 +186,11 @@ define_query_features! { } impl FeatureToCss for ScrollStateFeatureId { - fn to_css_with_prefix(&self, prefix: &str, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css_with_prefix( + &self, + prefix: &str, + dest: &mut PrinterT, + ) -> Result<(), PrinterError> { dest.write_str(prefix)?; self.to_css(dest) } @@ -350,15 +350,12 @@ impl<'i> ParseWithOptions<'i> for ContainerCondition<'i> { } impl<'i> ToCss for ContainerCondition<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match *self { ContainerCondition::Feature(ref f) => f.to_css(dest), ContainerCondition::Not(ref c) => { dest.write_str("not ")?; - to_css_with_parens_if_needed(&**c, dest, c.needs_parens(None, &dest.targets.current)) + to_css_with_parens_if_needed(&**c, dest, c.needs_parens(None, &dest.targets().current)) } ContainerCondition::Operation { ref conditions, @@ -388,16 +385,13 @@ impl<'i> ToCss for ContainerCondition<'i> { } impl<'i> ToCss for StyleQuery<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match *self { StyleQuery::Declaration(ref f) => f.to_css(dest, false), StyleQuery::Property(ref f) => f.to_css(dest), StyleQuery::Not(ref c) => { dest.write_str("not ")?; - to_css_with_parens_if_needed(&**c, dest, c.needs_parens(None, &dest.targets.current)) + to_css_with_parens_if_needed(&**c, dest, c.needs_parens(None, &dest.targets().current)) } StyleQuery::Operation { ref conditions, @@ -408,15 +402,12 @@ impl<'i> ToCss for StyleQuery<'i> { } impl<'i> ToCss for ScrollStateQuery<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match *self { ScrollStateQuery::Feature(ref f) => f.to_css(dest), ScrollStateQuery::Not(ref c) => { dest.write_str("not ")?; - to_css_with_parens_if_needed(&**c, dest, c.needs_parens(None, &dest.targets.current)) + to_css_with_parens_if_needed(&**c, dest, c.needs_parens(None, &dest.targets().current)) } ScrollStateQuery::Operation { ref conditions, @@ -445,19 +436,12 @@ impl<'i> Parse<'i> for ContainerName<'i> { } impl<'i> ToCss for ContainerName<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { // Container name should not be hashed // https://github.com/vercel/next.js/issues/71233 - self.0.to_css_with_options( - dest, - match &dest.css_module { - Some(css_module) => css_module.config.container, - None => false, - }, - ) + self + .0 + .to_css_with_options(dest, dest.css_module_config().is_some_and(|config| config.container)) } } @@ -473,10 +457,7 @@ impl<'i, T: Clone> ContainerRule<'i, T> { } impl<'a, 'i, T: ToCss> ToCss for ContainerRule<'i, T> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@container ")?; @@ -491,10 +472,10 @@ impl<'a, 'i, T: ToCss> ToCss for ContainerRule<'i, T> { if let Some(condition) = &self.condition { // Don't downlevel range syntax in container queries. - let exclude = dest.targets.current.exclude; - dest.targets.current.exclude.insert(Features::MediaQueries); + let exclude = dest.targets().current.exclude; + dest.targets_mut().current.exclude.insert(Features::MediaQueries); condition.to_css(dest)?; - dest.targets.current.exclude = exclude; + dest.targets_mut().current.exclude = exclude; } dest.whitespace()?; diff --git a/src/rules/counter_style.rs b/src/rules/counter_style.rs index 1550cbe9..d0501274 100644 --- a/src/rules/counter_style.rs +++ b/src/rules/counter_style.rs @@ -3,12 +3,10 @@ use super::Location; use crate::declaration::DeclarationBlock; use crate::error::PrinterError; -use crate::printer::Printer; use crate::traits::ToCss; use crate::values::ident::CustomIdent; #[cfg(feature = "visitor")] use crate::visitor::Visit; -use std::fmt::Write; /// A [@counter-style](https://drafts.csswg.org/css-counter-styles/#the-counter-style-rule) rule. #[derive(Debug, PartialEq, Clone)] @@ -29,10 +27,7 @@ pub struct CounterStyleRule<'i> { } impl<'i> ToCss for CounterStyleRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@counter-style ")?; diff --git a/src/rules/custom_media.rs b/src/rules/custom_media.rs index 9c3b7453..6f392e25 100644 --- a/src/rules/custom_media.rs +++ b/src/rules/custom_media.rs @@ -3,12 +3,10 @@ use super::Location; use crate::error::PrinterError; use crate::media_query::MediaList; -use crate::printer::Printer; use crate::traits::ToCss; use crate::values::ident::DashedIdent; #[cfg(feature = "visitor")] use crate::visitor::Visit; -use std::fmt::Write; /// A [@custom-media](https://drafts.csswg.org/mediaqueries-5/#custom-mq) rule. #[derive(Debug, PartialEq, Clone)] @@ -28,10 +26,7 @@ pub struct CustomMediaRule<'i> { } impl<'i> ToCss for CustomMediaRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@custom-media ")?; diff --git a/src/rules/document.rs b/src/rules/document.rs index 4f99c816..3d4265a9 100644 --- a/src/rules/document.rs +++ b/src/rules/document.rs @@ -4,11 +4,9 @@ use super::Location; use super::{CssRuleList, MinifyContext}; use crate::error::{MinifyError, PrinterError}; use crate::parser::DefaultAtRule; -use crate::printer::Printer; use crate::traits::ToCss; #[cfg(feature = "visitor")] use crate::visitor::Visit; -use std::fmt::Write; /// A [@-moz-document](https://www.w3.org/TR/2012/WD-css3-conditional-20120911/#at-document) rule. /// @@ -35,10 +33,7 @@ impl<'i, T: Clone> MozDocumentRule<'i, T> { } impl<'i, T: ToCss> ToCss for MozDocumentRule<'i, T> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@-moz-document url-prefix()")?; diff --git a/src/rules/font_face.rs b/src/rules/font_face.rs index 15f2e269..4e61be4f 100644 --- a/src/rules/font_face.rs +++ b/src/rules/font_face.rs @@ -3,7 +3,6 @@ use super::Location; use crate::error::{ParserError, PrinterError}; use crate::macros::enum_property; -use crate::printer::Printer; use crate::properties::custom::CustomProperty; use crate::properties::font::{FontFamily, FontStretch, FontStyle as FontStyleProperty, FontWeight}; use crate::stylesheet::ParserOptions; @@ -15,7 +14,6 @@ use crate::values::url::Url; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; /// A [@font-face](https://drafts.csswg.org/css-fonts/#font-face-rule) rule. #[derive(Debug, PartialEq, Clone)] @@ -101,10 +99,7 @@ impl<'i> Parse<'i> for Source<'i> { } impl<'i> ToCss for Source<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { Source::Url(url) => url.to_css(dest), Source::Local(local) => { @@ -155,10 +150,7 @@ impl<'i> Parse<'i> for UrlSource<'i> { } impl<'i> ToCss for UrlSource<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { self.url.to_css(dest)?; if let Some(format) = &self.format { dest.whitespace()?; @@ -228,10 +220,7 @@ impl<'i> Parse<'i> for FontFormat<'i> { } impl<'i> ToCss for FontFormat<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { use FontFormat::*; let s = match self { WOFF => "woff", @@ -320,10 +309,7 @@ impl<'i> Parse<'i> for UnicodeRange { } impl ToCss for UnicodeRange { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { // Attempt to optimize the range to use question mark syntax. if self.start != self.end { // Find the first hex digit that differs between the start and end values. @@ -421,10 +407,7 @@ impl<'i> Parse<'i> for FontStyle { } impl ToCss for FontStyle { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { FontStyle::Normal => { dest.write_str("normal")?; @@ -517,10 +500,7 @@ impl<'i> RuleBodyItemParser<'i, FontFaceProperty<'i>, ParserError<'i>> for FontF } impl<'i> ToCss for FontFaceRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@font-face")?; @@ -531,7 +511,7 @@ impl<'i> ToCss for FontFaceRule<'i> { for (i, prop) in self.properties.iter().enumerate() { dest.newline()?; prop.to_css(dest)?; - if i != len - 1 || !dest.minify { + if i != len - 1 || !dest.options().minify { dest.write_char(';')?; } } @@ -543,10 +523,7 @@ impl<'i> ToCss for FontFaceRule<'i> { } impl<'i> ToCss for FontFaceProperty<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { use FontFaceProperty::*; macro_rules! property { ($prop: literal, $value: expr) => {{ diff --git a/src/rules/font_feature_values.rs b/src/rules/font_feature_values.rs index d8ff73d9..e2ddd575 100644 --- a/src/rules/font_feature_values.rs +++ b/src/rules/font_feature_values.rs @@ -3,7 +3,6 @@ use super::Location; use crate::error::{ParserError, PrinterError}; use crate::parser::ParserOptions; -use crate::printer::Printer; use crate::properties::font::FamilyName; use crate::traits::{Parse, ToCss}; use crate::values::ident::Ident; @@ -13,7 +12,6 @@ use crate::visitor::Visit; use cssparser::*; use indexmap::IndexMap; use smallvec::SmallVec; -use std::fmt::Write; /// A [@font-feature-values](https://drafts.csswg.org/css-fonts/#font-feature-values) rule. #[derive(Debug, PartialEq, Clone)] @@ -152,10 +150,7 @@ impl<'a, 'i> RuleBodyItemParser<'i, (), ParserError<'i>> for FontFeatureValuesRu } impl<'i> ToCss for FontFeatureValuesRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@font-feature-values ")?; @@ -241,10 +236,7 @@ pub struct FontFeatureSubrule<'i> { } impl<'i> ToCss for FontFeatureSubrule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_char('@')?; @@ -267,7 +259,7 @@ impl<'i> ToCss for FontFeatureSubrule<'i> { index.to_css(dest)?; } - if i != len - 1 || !dest.minify { + if i != len - 1 || !dest.options().minify { dest.write_char(';')?; } } diff --git a/src/rules/font_palette_values.rs b/src/rules/font_palette_values.rs index cb5a3d7e..8e6f1834 100644 --- a/src/rules/font_palette_values.rs +++ b/src/rules/font_palette_values.rs @@ -3,7 +3,6 @@ use super::supports::SupportsRule; use super::{CssRule, CssRuleList, Location, MinifyContext}; use crate::error::{ParserError, PrinterError}; -use crate::printer::Printer; use crate::properties::custom::CustomProperty; use crate::properties::font::FontFamily; use crate::stylesheet::ParserOptions; @@ -15,7 +14,6 @@ use crate::values::number::CSSInteger; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; /// A [@font-palette-values](https://drafts.csswg.org/css-fonts-4/#font-palette-values) rule. #[derive(Debug, PartialEq, Clone)] @@ -203,10 +201,7 @@ impl<'i> Parse<'i> for BasePalette { } impl ToCss for BasePalette { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { BasePalette::Light => { dest.write_str("light")?; @@ -241,10 +236,7 @@ impl<'i> Parse<'i> for OverrideColors { } impl ToCss for OverrideColors { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { (self.index as CSSInteger).to_css(dest)?; dest.write_char(' ')?; self.color.to_css(dest) @@ -365,10 +357,7 @@ impl<'i> FontPaletteValuesRule<'i> { } impl<'i> ToCss for FontPaletteValuesRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@font-palette-values ")?; @@ -380,7 +369,7 @@ impl<'i> ToCss for FontPaletteValuesRule<'i> { for (i, prop) in self.properties.iter().enumerate() { dest.newline()?; prop.to_css(dest)?; - if i != len - 1 || !dest.minify { + if i != len - 1 || !dest.options().minify { dest.write_char(';')?; } } @@ -392,10 +381,7 @@ impl<'i> ToCss for FontPaletteValuesRule<'i> { } impl<'i> ToCss for FontPaletteValuesProperty<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { macro_rules! property { ($prop: literal, $value: expr) => {{ dest.write_str($prop)?; diff --git a/src/rules/import.rs b/src/rules/import.rs index 0dff48c2..920546cd 100644 --- a/src/rules/import.rs +++ b/src/rules/import.rs @@ -6,13 +6,11 @@ use super::Location; use crate::dependencies::{Dependency, ImportDependency}; use crate::error::PrinterError; use crate::media_query::MediaList; -use crate::printer::Printer; use crate::traits::ToCss; use crate::values::string::CowArcStr; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; /// A [@import](https://drafts.csswg.org/css-cascade/#at-import) rule. #[derive(Debug, PartialEq, Clone)] @@ -39,25 +37,19 @@ pub struct ImportRule<'i> { } impl<'i> ToCss for ImportRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { - let dep = if dest.dependencies.is_some() { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { + let dep = if dest.has_dependencies() { Some(ImportDependency::new(self, dest.filename())) } else { None }; - #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@import ")?; if let Some(dep) = dep { serialize_string(&dep.placeholder, dest)?; - if let Some(dependencies) = &mut dest.dependencies { - dependencies.push(Dependency::Import(dep)) - } + dest.add_dependency(Dependency::Import(dep)); } else { serialize_string(&self.url, dest)?; } diff --git a/src/rules/keyframes.rs b/src/rules/keyframes.rs index 2ec19af9..0ef43704 100644 --- a/src/rules/keyframes.rs +++ b/src/rules/keyframes.rs @@ -7,7 +7,6 @@ use crate::context::DeclarationContext; use crate::declaration::DeclarationBlock; use crate::error::{ParserError, PrinterError}; use crate::parser::ParserOptions; -use crate::printer::Printer; use crate::properties::animation::TimelineRangeName; use crate::properties::custom::{CustomProperty, UnparsedProperty}; use crate::properties::Property; @@ -21,7 +20,6 @@ use crate::vendor_prefix::VendorPrefix; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; /// A [@keyframes](https://drafts.csswg.org/css-animations/#keyframes) rule. #[derive(Debug, PartialEq, Clone)] @@ -90,12 +88,8 @@ impl<'i> Parse<'i> for KeyframesName<'i> { } impl<'i> ToCss for KeyframesName<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { - let css_module_animation_enabled = - dest.css_module.as_ref().map_or(false, |css_module| css_module.config.animation); + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { + let css_module_animation_enabled = dest.css_module_config().is_some_and(|config| config.animation); match self { KeyframesName::Ident(ident) => { @@ -216,10 +210,7 @@ impl<'i> KeyframesRule<'i> { } impl<'i> ToCss for KeyframesRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); let mut first_rule = true; @@ -230,7 +221,7 @@ impl<'i> ToCss for KeyframesRule<'i> { if first_rule { first_rule = false; } else { - if !dest.minify { + if !dest.options().minify { dest.write_char('\n')?; // no indent } dest.newline()?; @@ -246,7 +237,7 @@ impl<'i> ToCss for KeyframesRule<'i> { for keyframe in &self.keyframes { if first { first = false; - } else if !dest.minify { + } else if !dest.options().minify { dest.write_char('\n')?; // no indent } dest.newline()?; @@ -315,13 +306,10 @@ pub enum KeyframeSelector { } impl ToCss for KeyframeSelector { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { KeyframeSelector::Percentage(p) => { - if dest.minify && *p == Percentage(1.0) { + if dest.options().minify && *p == Percentage(1.0) { dest.write_str("to")?; Ok(()) } else { @@ -329,7 +317,7 @@ impl ToCss for KeyframeSelector { } } KeyframeSelector::From => { - if dest.minify { + if dest.options().minify { dest.write_str("0%")?; Ok(()) } else { @@ -370,10 +358,7 @@ pub struct Keyframe<'i> { } impl<'i> ToCss for Keyframe<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let mut first = true; for selector in &self.selectors { if !first { diff --git a/src/rules/layer.rs b/src/rules/layer.rs index d20d608c..e8396d75 100644 --- a/src/rules/layer.rs +++ b/src/rules/layer.rs @@ -3,14 +3,12 @@ use super::{CssRuleList, Location, MinifyContext}; use crate::error::{MinifyError, ParserError, PrinterError}; use crate::parser::DefaultAtRule; -use crate::printer::Printer; use crate::traits::{Parse, ToCss}; use crate::values::string::CowArcStr; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; use smallvec::SmallVec; -use std::fmt::Write; /// A [``](https://drafts.csswg.org/css-cascade-5/#typedef-layer-name) within /// a `@layer` or `@import` rule. @@ -62,10 +60,7 @@ impl<'i> Parse<'i> for LayerName<'i> { } impl<'i> ToCss for LayerName<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let mut first = true; for name in &self.0 { if first { @@ -100,10 +95,7 @@ pub struct LayerStatementRule<'i> { } impl<'i> ToCss for LayerStatementRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@layer ")?; @@ -144,10 +136,7 @@ impl<'i, T: Clone> LayerBlockRule<'i, T> { } impl<'a, 'i, T: ToCss> ToCss for LayerBlockRule<'i, T> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@layer")?; diff --git a/src/rules/media.rs b/src/rules/media.rs index 5913f25d..9504fc3a 100644 --- a/src/rules/media.rs +++ b/src/rules/media.rs @@ -5,11 +5,9 @@ use super::{CssRuleList, MinifyContext}; use crate::error::{MinifyError, PrinterError}; use crate::media_query::MediaList; use crate::parser::DefaultAtRule; -use crate::printer::Printer; use crate::traits::ToCss; #[cfg(feature = "visitor")] use crate::visitor::Visit; -use std::fmt::Write; /// A [@media](https://drafts.csswg.org/css-conditional-3/#at-media) rule. #[derive(Debug, PartialEq, Clone)] @@ -46,16 +44,12 @@ impl<'i, T: Clone> MediaRule<'i, T> { } impl<'a, 'i, T: ToCss> ToCss for MediaRule<'i, T> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { // If the media query always matches, we can just output the nested rules. - if dest.minify && self.query.always_matches() { + if dest.options().minify && self.query.always_matches() { self.rules.to_css(dest)?; return Ok(()); } - #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@media ")?; diff --git a/src/rules/mod.rs b/src/rules/mod.rs index 71941c63..65e24df4 100644 --- a/src/rules/mod.rs +++ b/src/rules/mod.rs @@ -36,8 +36,6 @@ #![deny(missing_docs)] -use std::fmt::Write; - pub mod container; pub mod counter_style; pub mod custom_media; @@ -102,6 +100,7 @@ use scope::ScopeRule; use smallvec::{smallvec, SmallVec}; use starting_style::StartingStyleRule; use std::collections::{HashMap, HashSet}; +use std::fmt::Write; use std::hash::{BuildHasherDefault, Hasher}; use style::StyleRule; use supports::SupportsRule; @@ -382,10 +381,7 @@ impl<'i, 'de: 'i, R: serde::Deserialize<'de>> serde::Deserialize<'de> for CssRul } impl<'a, 'i, T: ToCss> ToCss for CssRule<'i, T> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { CssRule::Media(media) => media.to_css(dest), CssRule::Import(import) => import.to_css(dest), @@ -1322,10 +1318,7 @@ fn merge_style_rules<'i, T>( } impl<'a, 'i, T: ToCss> ToCss for CssRuleList<'i, T> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { let mut first = true; let mut last_without_block = false; @@ -1336,15 +1329,10 @@ impl<'a, 'i, T: ToCss> ToCss for CssRuleList<'i, T> { // Skip @import rules if collecting dependencies. if let CssRule::Import(rule) = &rule { - if dest.remove_imports { - let dep = if dest.dependencies.is_some() { - Some(Dependency::Import(ImportDependency::new(&rule, dest.filename()))) - } else { - None - }; - - if let Some(dependencies) = &mut dest.dependencies { - dependencies.push(dep.unwrap()); + if dest.remove_imports() { + if dest.has_dependencies() { + let dep = ImportDependency::new(&rule, dest.filename()); + dest.add_dependency(Dependency::Import(dep)); continue; } } @@ -1353,7 +1341,7 @@ impl<'a, 'i, T: ToCss> ToCss for CssRuleList<'i, T> { if first { first = false; } else { - if !dest.minify + if !dest.options().minify && !(last_without_block && matches!( rule, @@ -1367,8 +1355,8 @@ impl<'a, 'i, T: ToCss> ToCss for CssRuleList<'i, T> { rule.to_css(dest)?; // If this is an invisible nested declarations rule, and not the last rule in the block, add a semicolon. - if dest.minify - && !should_compile!(dest.targets.current, Nesting) + if dest.options().minify + && !should_compile!(dest.targets().current, Nesting) && matches!(rule, CssRule::NestedDeclarations(_)) && i != self.0.len() - 1 { diff --git a/src/rules/namespace.rs b/src/rules/namespace.rs index bd4ff475..56635a33 100644 --- a/src/rules/namespace.rs +++ b/src/rules/namespace.rs @@ -2,13 +2,11 @@ use super::Location; use crate::error::PrinterError; -use crate::printer::Printer; use crate::traits::ToCss; use crate::values::ident::Ident; use crate::values::string::CSSString; #[cfg(feature = "visitor")] use crate::visitor::Visit; -use std::fmt::Write; /// A [@namespace](https://drafts.csswg.org/css-namespaces/#declaration) rule. #[derive(Debug, PartialEq, Clone)] @@ -31,10 +29,7 @@ pub struct NamespaceRule<'i> { } impl<'i> ToCss for NamespaceRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@namespace ")?; diff --git a/src/rules/nesting.rs b/src/rules/nesting.rs index 9c824f9c..aae557c6 100644 --- a/src/rules/nesting.rs +++ b/src/rules/nesting.rs @@ -1,7 +1,6 @@ //! The `@nest` rule. use smallvec::SmallVec; -use std::fmt::Write; use super::style::StyleRule; use super::Location; @@ -10,7 +9,7 @@ use crate::context::DeclarationContext; use crate::declaration::DeclarationBlock; use crate::error::{MinifyError, PrinterError}; use crate::parser::DefaultAtRule; -use crate::printer::Printer; +use crate::printer::ContextAccess; use crate::targets::should_compile; use crate::traits::ToCss; #[cfg(feature = "visitor")] @@ -42,13 +41,10 @@ impl<'i, T: Clone> NestingRule<'i, T> { } impl<'a, 'i, T: ToCss> ToCss for NestingRule<'i, T> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); - if dest.context().is_none() { + if !dest.has_context() { dest.write_str("@nest ")?; } self.style.to_css(dest) @@ -86,18 +82,15 @@ impl<'i> NestedDeclarationsRule<'i> { } impl<'i> ToCss for NestedDeclarationsRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); - if should_compile!(dest.targets.current, Nesting) { - if let Some(context) = dest.context() { + dest.with_current_context(ContextAccess, |dest, context| { + if let Some(context) = context.filter(|_| should_compile!(dest.targets().current, Nesting)) { let has_printable_declarations = self.declarations.has_printable_declarations(); if has_printable_declarations { - dest.with_parent_context(|dest| context.selectors.to_css(dest))?; + dest.with_parent_context(ContextAccess, |dest| context.selectors.to_css(dest))?; dest.whitespace()?; dest.write_char('{')?; dest.indent(); @@ -115,13 +108,12 @@ impl<'i> ToCss for NestedDeclarationsRule<'i> { } return Ok(()); } - } - - self.declarations.to_css_declarations( - dest, - false, - &rspack_lightningcss_selectors::SelectorList(SmallVec::new()), - 0, - ) + self.declarations.to_css_declarations( + dest, + false, + &rspack_lightningcss_selectors::SelectorList(SmallVec::new()), + 0, + ) + }) } } diff --git a/src/rules/page.rs b/src/rules/page.rs index 7f16fc8f..7b60afcf 100644 --- a/src/rules/page.rs +++ b/src/rules/page.rs @@ -4,14 +4,12 @@ use super::Location; use crate::declaration::{parse_declaration, DeclarationBlock}; use crate::error::{ParserError, PrinterError}; use crate::macros::enum_property; -use crate::printer::Printer; use crate::stylesheet::ParserOptions; use crate::traits::{Parse, ToCss}; use crate::values::string::CowArcStr; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; /// A [page selector](https://www.w3.org/TR/css-page-3/#typedef-page-selector) /// within a `@page` rule. @@ -142,10 +140,7 @@ pub struct PageMarginRule<'i> { } impl<'i> ToCss for PageMarginRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_char('@')?; @@ -210,16 +205,13 @@ impl<'i> PageRule<'i> { } impl<'i> ToCss for PageRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@page")?; if let Some(first) = self.selectors.first() { // Space is only required if the first selector has a name. - if !dest.minify || first.name.is_some() { + if !dest.options().minify || first.name.is_some() { dest.write_char(' ')?; } let mut first = true; @@ -245,7 +237,7 @@ impl<'i> ToCss for PageRule<'i> { for decl in &$decls { dest.newline()?; decl.to_css(dest, $important)?; - if i != len - 1 || !dest.minify { + if i != len - 1 || !dest.options().minify { dest.write_char(';')?; } i += 1; @@ -257,7 +249,7 @@ impl<'i> ToCss for PageRule<'i> { write!(self.declarations.important_declarations, true); if !self.rules.is_empty() { - if !dest.minify && self.declarations.len() > 0 { + if !dest.options().minify && self.declarations.len() > 0 { dest.write_char('\n')?; } dest.newline()?; @@ -267,7 +259,7 @@ impl<'i> ToCss for PageRule<'i> { if first { first = false; } else { - if !dest.minify { + if !dest.options().minify { dest.write_char('\n')?; } dest.newline()?; @@ -284,10 +276,7 @@ impl<'i> ToCss for PageRule<'i> { } impl<'i> ToCss for PageSelector<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if let Some(name) = &self.name { dest.write_str(&name)?; } diff --git a/src/rules/position_try.rs b/src/rules/position_try.rs index dfa8fd2e..e63e6ec7 100644 --- a/src/rules/position_try.rs +++ b/src/rules/position_try.rs @@ -3,12 +3,10 @@ use super::Location; use crate::declaration::DeclarationBlock; use crate::error::PrinterError; -use crate::printer::Printer; use crate::traits::ToCss; use crate::values::ident::DashedIdent; #[cfg(feature = "visitor")] use crate::visitor::Visit; -use std::fmt::Write; /// A [@position-try](https://drafts.csswg.org/css-anchor-position-1/#position-try) rule. #[derive(Debug, PartialEq, Clone)] @@ -28,10 +26,7 @@ pub struct PositionTryRule<'i> { } impl<'i> ToCss for PositionTryRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@position-try ")?; diff --git a/src/rules/property.rs b/src/rules/property.rs index 49a4876b..89c58ed8 100644 --- a/src/rules/property.rs +++ b/src/rules/property.rs @@ -5,7 +5,6 @@ use super::Location; use crate::visitor::Visit; use crate::{ error::{ParserError, PrinterError}, - printer::Printer, properties::custom::TokenList, traits::{Parse, ToCss}, values::{ @@ -14,7 +13,6 @@ use crate::{ }, }; use cssparser::*; -use std::fmt::Write; /// A [@property](https://drafts.css-houdini.org/css-properties-values-api/#at-property-rule) rule. #[derive(Debug, PartialEq, Clone)] @@ -111,10 +109,7 @@ impl<'i> PropertyRule<'i> { } impl<'i> ToCss for PropertyRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@property ")?; @@ -145,7 +140,7 @@ impl<'i> ToCss for PropertyRule<'i> { dest.whitespace()?; initial_value.to_css(dest)?; - if !dest.minify { + if !dest.options().minify { dest.write_char(';')?; } } diff --git a/src/rules/scope.rs b/src/rules/scope.rs index c93f7be4..e1347066 100644 --- a/src/rules/scope.rs +++ b/src/rules/scope.rs @@ -4,12 +4,11 @@ use super::Location; use super::{CssRuleList, MinifyContext}; use crate::error::{MinifyError, PrinterError}; use crate::parser::DefaultAtRule; -use crate::printer::Printer; +use crate::printer::ContextAccess; use crate::selector::{is_pure_css_modules_selector, SelectorList}; use crate::traits::ToCss; #[cfg(feature = "visitor")] use crate::visitor::Visit; -use std::fmt::Write; /// A [@scope](https://drafts.csswg.org/css-cascade-6/#scope-atrule) rule. /// @@ -65,10 +64,7 @@ impl<'i, T: Clone> ScopeRule<'i, T> { } impl<'i, T: ToCss> ToCss for ScopeRule<'i, T> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@scope")?; @@ -80,14 +76,14 @@ impl<'i, T: ToCss> ToCss for ScopeRule<'i, T> { dest.whitespace()?; } if let Some(scope_end) = &self.scope_end { - if dest.minify { + if dest.options().minify { dest.write_char(' ')?; } dest.write_str("to (")?; // is treated as an ancestor of scope end. // https://drafts.csswg.org/css-nesting/#nesting-at-scope if let Some(scope_start) = &self.scope_start { - dest.with_context(scope_start, |dest| scope_end.to_css(dest))?; + dest.with_context(ContextAccess, scope_start, |dest| scope_end.to_css(dest))?; } else { scope_end.to_css(dest)?; } @@ -100,7 +96,7 @@ impl<'i, T: ToCss> ToCss for ScopeRule<'i, T> { // Nested style rules within @scope are implicitly relative to the // so clear our style context while printing them to avoid replacing & ourselves. // https://drafts.csswg.org/css-cascade-6/#scoped-rules - dest.with_cleared_context(|dest| self.rules.to_css(dest))?; + dest.with_cleared_context(ContextAccess, |dest| self.rules.to_css(dest))?; dest.dedent(); dest.newline()?; dest.write_char('}')?; diff --git a/src/rules/starting_style.rs b/src/rules/starting_style.rs index 4f4ab17a..a65d370a 100644 --- a/src/rules/starting_style.rs +++ b/src/rules/starting_style.rs @@ -4,11 +4,9 @@ use super::Location; use super::{CssRuleList, MinifyContext}; use crate::error::{MinifyError, PrinterError}; use crate::parser::DefaultAtRule; -use crate::printer::Printer; use crate::traits::ToCss; #[cfg(feature = "visitor")] use crate::visitor::Visit; -use std::fmt::Write; /// A [@starting-style](https://drafts.csswg.org/css-transitions-2/#defining-before-change-style-the-starting-style-rule) rule. #[derive(Debug, PartialEq, Clone)] @@ -37,10 +35,7 @@ impl<'i, T: Clone> StartingStyleRule<'i, T> { } impl<'i, T: ToCss> ToCss for StartingStyleRule<'i, T> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@starting-style")?; diff --git a/src/rules/style.rs b/src/rules/style.rs index 120eba70..a8aad4a5 100644 --- a/src/rules/style.rs +++ b/src/rules/style.rs @@ -1,6 +1,5 @@ //! Style rules. -use std::fmt::Write; use std::hash::{Hash, Hasher}; use std::ops::Range; @@ -11,7 +10,7 @@ use crate::declaration::DeclarationBlock; use crate::error::ParserError; use crate::error::{MinifyError, PrinterError}; use crate::parser::DefaultAtRule; -use crate::printer::Printer; +use crate::printer::ContextAccess; use crate::rules::{CssRule, CssRuleList}; use crate::selector::{ downlevel_selectors, get_prefix, is_compatible, is_pure_css_modules_selector, is_unused, SelectorList, @@ -212,10 +211,7 @@ where } impl<'a, 'i, T: ToCss> ToCss for StyleRule<'i, T> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if self.vendor_prefix.is_empty() { self.to_css_base(dest) } else { @@ -224,28 +220,24 @@ impl<'a, 'i, T: ToCss> ToCss for StyleRule<'i, T> { if first_rule { first_rule = false; } else { - if !dest.minify { + if !dest.options().minify { dest.write_char('\n')?; // no indent } dest.newline()?; } - dest.vendor_prefix = prefix; + dest.set_vendor_prefix(prefix); self.to_css_base(dest)?; } - - dest.vendor_prefix = VendorPrefix::empty(); + dest.set_vendor_prefix(VendorPrefix::empty()); Ok(()) } } } impl<'a, 'i, T: ToCss> StyleRule<'i, T> { - fn to_css_base(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css_base(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { // If supported, or there are no targets, preserve nesting. Otherwise, write nested rules after parent. - let supports_nesting = self.rules.0.is_empty() || !should_compile!(dest.targets.current, Nesting); + let supports_nesting = self.rules.0.is_empty() || !should_compile!(dest.targets().current, Nesting); let must_preserve_rule = |rule: &CssRule<'i, T>| matches!(rule, CssRule::Unknown(_)); let has_preserved_rules = !supports_nesting && self.rules.0.iter().any(must_preserve_rule); let has_hoisted_rules = !supports_nesting && self.rules.0.iter().any(|rule| !must_preserve_rule(rule)); @@ -273,7 +265,10 @@ impl<'a, 'i, T: ToCss> StyleRule<'i, T> { macro_rules! newline { () => { - if !dest.minify && (supports_nesting || len > 0 || has_preserved_rules) && !self.rules.0.is_empty() { + if !dest.options().minify + && (supports_nesting || len > 0 || has_preserved_rules) + && !self.rules.0.is_empty() + { if len > 0 || has_preserved_rules { dest.write_char('\n')?; } @@ -300,7 +295,7 @@ impl<'a, 'i, T: ToCss> StyleRule<'i, T> { } else { let mut first = true; for rule in self.rules.0.iter().filter(|rule| must_preserve_rule(rule)) { - if !dest.minify || first { + if !dest.options().minify || first { dest.newline()?; } rule.to_css(dest)?; @@ -310,25 +305,153 @@ impl<'a, 'i, T: ToCss> StyleRule<'i, T> { if has_hoisted_rules { newline!(); - dest.with_context(&self.selectors, |dest| { - let mut first = true; - for rule in self.rules.0.iter().filter(|rule| !must_preserve_rule(rule)) { - if first { - first = false; - } else { - if !dest.minify { - dest.write_char('\n')?; - } - dest.newline()?; - } - rule.to_css(dest)?; - } + dest.with_context(ContextAccess, &self.selectors, |dest| self.to_css_hoisted_rules(dest))?; + } + } + + Ok(()) + } - Ok::<(), PrinterError>(()) - })?; + fn to_css_hoisted_rules( + &self, + dest: &mut PrinterT, + ) -> Result<(), PrinterError> { + let mut first = true; + for rule in self.rules.0.iter().filter(|rule| !matches!(rule, CssRule::Unknown(_))) { + if first { + first = false; + } else { + if !dest.options().minify { + dest.write_char('\n')?; + } + dest.newline()?; } + rule.to_css(dest)?; } Ok(()) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::printer::{Printer, PrinterOptions, PrinterTrait}; + use crate::rules::StyleContext; + use crate::stylesheet::{ParserOptions, StyleSheet}; + use crate::targets::Features; + use std::cell::Cell; + + fn nesting_options() -> PrinterOptions<'static> { + PrinterOptions { + targets: Targets { + include: Features::Nesting, + ..Targets::default() + }, + ..PrinterOptions::default() + } + } + + #[test] + fn restores_context_after_nested_writer_error() { + struct FailingWriter<'a> { + writes: &'a Cell, + fail_at: usize, + } + + impl std::fmt::Write for FailingWriter<'_> { + fn write_str(&mut self, _: &str) -> std::fmt::Result { + let index = self.writes.get(); + self.writes.set(index + 1); + if index == self.fail_at { + Err(std::fmt::Error) + } else { + Ok(()) + } + } + } + + let sheet = StyleSheet::parse( + ".a { & .b { & .c { color: red } } & .d { color: blue } }", + ParserOptions::default(), + ) + .unwrap(); + let CssRule::Style(rule) = &sheet.rules.0[0] else { + panic!("expected style rule"); + }; + let parent = StyleContext { + selectors: &rule.selectors, + parent: None, + }; + + for context in [None, Some(&parent)] { + let writes = Cell::new(0); + let mut writer = FailingWriter { + writes: &writes, + fail_at: usize::MAX, + }; + let mut printer = Printer::new(&mut writer, nesting_options()); + printer.state.context = context; + rule.to_css(&mut printer).unwrap(); + let total_writes = writes.get(); + + // Fail at every write, including separators between hoisted rules. + for fail_at in 0..total_writes { + writes.set(0); + let mut writer = FailingWriter { + writes: &writes, + fail_at, + }; + let mut printer = Printer::new(&mut writer, nesting_options()); + printer.state.context = context; + assert!(rule.to_css(&mut printer).is_err()); + assert!(same_context(printer.state.context, context), "write {fail_at}"); + rule.to_css(&mut printer).unwrap(); + assert!(same_context(printer.state.context, context)); + } + } + } + + #[test] + fn restores_context_after_nested_custom_rule_error() { + struct FailingRule; + + impl ToCss for FailingRule { + fn to_css(&self, _: &mut P) -> Result<(), PrinterError> { + Err(std::fmt::Error.into()) + } + } + + let sheet = StyleSheet::parse(".a {}", ParserOptions::default()).unwrap(); + let CssRule::Style(parsed) = &sheet.rules.0[0] else { + panic!("expected style rule"); + }; + let rule = StyleRule { + selectors: parsed.selectors.clone(), + vendor_prefix: parsed.vendor_prefix, + declarations: parsed.declarations.clone(), + rules: CssRuleList(vec![CssRule::Custom(FailingRule)]), + loc: parsed.loc, + }; + let parent = StyleContext { + selectors: &parsed.selectors, + parent: None, + }; + for context in [None, Some(&parent)] { + let mut css = String::new(); + let mut printer = Printer::new(&mut css, nesting_options()); + printer.state.context = context; + assert!(rule.to_css(&mut printer).is_err()); + assert!(same_context(printer.state.context, context)); + parsed.to_css(&mut printer).unwrap(); + } + } + + fn same_context<'i>(a: Option<&StyleContext<'_, 'i>>, b: Option<&StyleContext<'_, 'i>>) -> bool { + match (a, b) { + (Some(a), Some(b)) => std::ptr::eq(a, b), + (None, None) => true, + _ => false, + } + } +} diff --git a/src/rules/supports.rs b/src/rules/supports.rs index 0a235cc2..4c00ab85 100644 --- a/src/rules/supports.rs +++ b/src/rules/supports.rs @@ -1,13 +1,11 @@ //! The `@supports` rule. use std::collections::HashMap; -use std::fmt::Write; use super::Location; use super::{CssRuleList, MinifyContext}; use crate::error::{MinifyError, ParserError, PrinterError}; use crate::parser::DefaultAtRule; -use crate::printer::Printer; use crate::properties::custom::TokenList; use crate::properties::PropertyId; use crate::targets::{Features, FeaturesIterator, Targets}; @@ -61,10 +59,7 @@ impl<'i, T: Clone> SupportsRule<'i, T> { } impl<'a, 'i, T: ToCss> ToCss for SupportsRule<'i, T> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@supports ")?; @@ -74,10 +69,10 @@ impl<'a, 'i, T: ToCss> ToCss for SupportsRule<'i, T> { dest.indent(); dest.newline()?; - let inserted = dest.targets.enter_supports(self.condition.get_supported_features()); + let inserted = dest.targets_mut().enter_supports(self.condition.get_supported_features()); self.rules.to_css(dest)?; if inserted { - dest.targets.exit_supports(); + dest.targets_mut().exit_supports(); } dest.dedent(); @@ -339,10 +334,11 @@ impl<'i> SupportsCondition<'i> { } } - fn to_css_with_parens_if_needed(&self, dest: &mut Printer, needs_parens: bool) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css_with_parens_if_needed( + &self, + dest: &mut PrinterT, + needs_parens: bool, + ) -> Result<(), PrinterError> { if needs_parens { dest.write_char('(')?; } @@ -355,10 +351,7 @@ impl<'i> SupportsCondition<'i> { } impl<'i> ToCss for SupportsCondition<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { SupportsCondition::Not(condition) => { dest.write_str("not ")?; diff --git a/src/rules/unknown.rs b/src/rules/unknown.rs index e0ec15fa..88cca70a 100644 --- a/src/rules/unknown.rs +++ b/src/rules/unknown.rs @@ -2,13 +2,11 @@ use super::Location; use crate::error::PrinterError; -use crate::printer::Printer; use crate::properties::custom::TokenList; use crate::traits::ToCss; use crate::values::string::CowArcStr; #[cfg(feature = "visitor")] use crate::visitor::Visit; -use std::fmt::Write; /// An unknown at-rule, stored as raw tokens. #[derive(Debug, PartialEq, Clone)] @@ -31,10 +29,7 @@ pub struct UnknownAtRule<'i> { } impl<'i> ToCss for UnknownAtRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_char('@')?; diff --git a/src/rules/view_transition.rs b/src/rules/view_transition.rs index afe4c6e1..ba3562ea 100644 --- a/src/rules/view_transition.rs +++ b/src/rules/view_transition.rs @@ -2,7 +2,6 @@ use super::Location; use crate::error::{ParserError, PrinterError}; -use crate::printer::Printer; use crate::properties::custom::CustomProperty; use crate::stylesheet::ParserOptions; use crate::traits::{Parse, ToCss}; @@ -10,7 +9,6 @@ use crate::values::ident::NoneOrCustomIdentList; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; -use std::fmt::Write; /// A [@view-transition](https://drafts.csswg.org/css-view-transitions-2/#view-transition-rule) rule. #[derive(Debug, PartialEq, Clone)] @@ -148,10 +146,7 @@ impl<'i> ViewTransitionRule<'i> { } impl<'i> ToCss for ViewTransitionRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_str("@view-transition")?; @@ -162,7 +157,7 @@ impl<'i> ToCss for ViewTransitionRule<'i> { for (i, prop) in self.properties.iter().enumerate() { dest.newline()?; prop.to_css(dest)?; - if i != len - 1 || !dest.minify { + if i != len - 1 || !dest.options().minify { dest.write_char(';')?; } } @@ -174,10 +169,7 @@ impl<'i> ToCss for ViewTransitionRule<'i> { } impl<'i> ToCss for ViewTransitionProperty<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { macro_rules! property { ($prop: literal, $value: expr) => {{ dest.write_str($prop)?; diff --git a/src/rules/viewport.rs b/src/rules/viewport.rs index 47da3117..ca6599a5 100644 --- a/src/rules/viewport.rs +++ b/src/rules/viewport.rs @@ -3,12 +3,10 @@ use super::Location; use crate::declaration::DeclarationBlock; use crate::error::PrinterError; -use crate::printer::Printer; use crate::traits::ToCss; use crate::vendor_prefix::VendorPrefix; #[cfg(feature = "visitor")] use crate::visitor::Visit; -use std::fmt::Write; /// A [@viewport](https://drafts.csswg.org/css-device-adapt/#atviewport-rule) rule. #[derive(Debug, PartialEq, Clone)] @@ -33,10 +31,7 @@ pub struct ViewportRule<'i> { } impl<'i> ToCss for ViewportRule<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { #[cfg(feature = "sourcemap")] dest.add_mapping(self.loc); dest.write_char('@')?; diff --git a/src/selector.rs b/src/selector.rs index e98776f2..a4ece9f4 100644 --- a/src/selector.rs +++ b/src/selector.rs @@ -3,7 +3,7 @@ use crate::compat::Feature; use crate::error::{ParserError, PrinterError, SelectorError}; use crate::parser::ParserFlags; -use crate::printer::Printer; +use crate::printer::{ContextAccess, Printer}; use crate::properties::custom::TokenList; use crate::rules::StyleContext; use crate::stylesheet::{ParserOptions, PrinterOptions}; @@ -24,7 +24,6 @@ use rspack_lightningcss_selectors::{ use smallvec::SmallVec; use std::collections::HashSet; use std::fmt; -use std::fmt::Write; #[cfg(feature = "serde")] use crate::serialization::*; @@ -692,20 +691,17 @@ impl<'i> cssparser::ToCss for PseudoClass<'i> { W: fmt::Write, { let mut s = String::new(); - serialize_pseudo_class(self, &mut Printer::new(&mut s, Default::default()), None) - .map_err(|_| std::fmt::Error)?; + let mut printer = Printer::new(&mut s, PrinterOptions::default()); + serialize_pseudo_class(self, &mut printer, None).map_err(|_| std::fmt::Error)?; write!(dest, "{}", s) } } -fn serialize_pseudo_class<'a, 'i, W>( +fn serialize_pseudo_class<'a, 'i, PrinterT: crate::printer::PrinterTrait>( pseudo_class: &PseudoClass<'i>, - dest: &mut Printer, + dest: &mut PrinterT, context: Option<&StyleContext>, -) -> Result<(), PrinterError> -where - W: fmt::Write, -{ +) -> Result<(), PrinterError> { use PseudoClass::*; match pseudo_class { Lang { languages: lang } => { @@ -741,8 +737,8 @@ where ($prefix: ident, $val: expr) => {{ dest.write_char(':')?; // If the printer has a vendor prefix override, use that. - let vp = if !dest.vendor_prefix.is_empty() { - (dest.vendor_prefix & *$prefix).or_none() + let vp = if !dest.vendor_prefix().is_empty() { + (dest.vendor_prefix() & *$prefix).or_none() } else { *$prefix }; @@ -754,19 +750,18 @@ where macro_rules! pseudo { ($key: ident, $s: literal) => {{ - let class = if let Some(pseudo_classes) = &dest.pseudo_classes { - pseudo_classes.$key - } else { - None - }; - - if let Some(class) = class { - dest.write_char('.')?; - dest.write_ident(class, true) - } else { - dest.write_str($s)?; - Ok(()) - } + dest.with_pseudo_class( + |pseudo_classes| pseudo_classes.$key, + |dest, class| { + if let Some(class) = class { + dest.write_char('.')?; + dest.write_ident(class, true) + } else { + dest.write_str($s)?; + Ok(()) + } + }, + ) }}; } @@ -825,8 +820,8 @@ where // https://fullscreen.spec.whatwg.org/#:fullscreen-pseudo-class Fullscreen(prefix) => { dest.write_char(':')?; - let vp = if !dest.vendor_prefix.is_empty() { - (dest.vendor_prefix & *prefix).or_none() + let vp = if !dest.vendor_prefix().is_empty() { + (dest.vendor_prefix() & *prefix).or_none() } else { *prefix }; @@ -984,12 +979,7 @@ where } Local { selector } => serialize_selector(selector, dest, context, false), - Global { selector } => { - let css_module = std::mem::take(&mut dest.css_module); - serialize_selector(selector, dest, context, false)?; - dest.css_module = css_module; - Ok(()) - } + Global { selector } => dest.without_css_module(|dest| serialize_selector(selector, dest, context, false)), // https://webkit.org/blog/363/styling-scrollbars/ WebKitScrollbar(s) => { @@ -1250,10 +1240,7 @@ impl<'i> Parse<'i> for ViewTransitionPartName<'i> { } impl<'i> ToCss for ViewTransitionPartName<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match self { ViewTransitionPartName::All => { dest.write_char('*')?; @@ -1302,10 +1289,7 @@ impl<'i> Parse<'i> for ViewTransitionPartSelector<'i> { } impl<'i> ToCss for ViewTransitionPartSelector<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: std::fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { if let Some(name) = &self.name { name.to_css(dest)?; } @@ -1323,28 +1307,25 @@ impl<'i> cssparser::ToCss for PseudoElement<'i> { W: fmt::Write, { let mut s = String::new(); - serialize_pseudo_element(self, &mut Printer::new(&mut s, Default::default()), None) - .map_err(|_| std::fmt::Error)?; + let mut printer = Printer::new(&mut s, PrinterOptions::default()); + serialize_pseudo_element(self, &mut printer, None).map_err(|_| std::fmt::Error)?; write!(dest, "{}", s) } } -fn serialize_pseudo_element<'a, 'i, W>( +fn serialize_pseudo_element<'a, 'i, PrinterT: crate::printer::PrinterTrait>( pseudo_element: &PseudoElement, - dest: &mut Printer, + dest: &mut PrinterT, context: Option<&StyleContext>, -) -> Result<(), PrinterError> -where - W: fmt::Write, -{ +) -> Result<(), PrinterError> { use PseudoElement::*; macro_rules! write_prefix { ($prefix: ident) => {{ dest.write_str("::")?; // If the printer has a vendor prefix override, use that. - let vp = if !dest.vendor_prefix.is_empty() { - (dest.vendor_prefix & *$prefix).or_none() + let vp = if !dest.vendor_prefix().is_empty() { + (dest.vendor_prefix() & *$prefix).or_none() } else { *$prefix }; @@ -1608,19 +1589,15 @@ impl<'i> PseudoElement<'i> { } impl<'a, 'i> ToCss for SelectorList<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: fmt::Write, - { - serialize_selector_list(self.0.iter(), dest, dest.context(), false) + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { + dest.with_current_context(ContextAccess, |dest, context| { + serialize_selector_list(self.0.iter(), dest, context, false) + }) } } impl ToCss for Combinator { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: fmt::Write, - { + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { match *self { Combinator::Child => dest.delim('>', true), Combinator::Descendant => { @@ -1645,23 +1622,19 @@ impl ToCss for Combinator { // Copied from the selectors crate and modified to override to_css implementation. impl<'a, 'i> ToCss for Selector<'i> { - fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> - where - W: fmt::Write, - { - serialize_selector(self, dest, dest.context(), false) + fn to_css(&self, dest: &mut PrinterT) -> Result<(), PrinterError> { + dest.with_current_context(ContextAccess, |dest, context| { + serialize_selector(self, dest, context, false) + }) } } -fn serialize_selector<'a, 'i, W>( +fn serialize_selector<'a, 'i, PrinterT: crate::printer::PrinterTrait>( selector: &Selector<'i>, - dest: &mut Printer, + dest: &mut PrinterT, context: Option<&StyleContext>, mut is_relative: bool, -) -> Result<(), PrinterError> -where - W: fmt::Write, -{ +) -> Result<(), PrinterError> { use rspack_lightningcss_selectors::parser::*; // Compound selectors invert the order of their contents, so we need to // undo that during serialization. @@ -1677,7 +1650,7 @@ where let mut combinators = selector.iter_raw_match_order().rev().filter_map(|x| x.as_combinator()); let compound_selectors = selector.iter_raw_match_order().as_slice().split(|x| x.is_combinator()).rev(); - let should_compile_nesting = should_compile!(dest.targets.current, Nesting); + let should_compile_nesting = should_compile!(dest.targets().current, Nesting); let mut first = true; let mut combinators_exhausted = false; @@ -1821,14 +1794,11 @@ where Ok(()) } -fn serialize_component<'a, 'i, W>( +fn serialize_component<'a, 'i, PrinterT: crate::printer::PrinterTrait>( component: &Component, - dest: &mut Printer, + dest: &mut PrinterT, context: Option<&StyleContext>, -) -> Result<(), PrinterError> -where - W: fmt::Write, -{ +) -> Result<(), PrinterError> { match component { Component::Combinator(ref c) => c.to_css(dest), Component::AttributeInNoNamespace { @@ -1842,7 +1812,7 @@ where cssparser::ToCss::to_css(local_name, dest)?; cssparser::ToCss::to_css(operator, dest)?; - if dest.minify { + if dest.options().minify { // Serialize as both an identifier and a string and choose the shorter one. let mut id = String::new(); serialize_identifier(&value, &mut id)?; @@ -1880,7 +1850,7 @@ where return Ok(()); } - let vp = dest.vendor_prefix; + let vp = dest.vendor_prefix(); if vp.intersects(VendorPrefix::WebKit | VendorPrefix::Moz) { dest.write_char(':')?; vp.to_css(dest)?; @@ -1893,7 +1863,7 @@ where dest.write_str(":not(")?; } Component::Any(prefix, ..) => { - let vp = dest.vendor_prefix.or(prefix); + let vp = dest.vendor_prefix().or(prefix); if vp.intersects(VendorPrefix::WebKit | VendorPrefix::Moz) { dest.write_char(':')?; vp.to_css(dest)?; @@ -1967,14 +1937,11 @@ fn should_unwrap_is<'i>(selectors: &Box<[Selector<'i>]>) -> bool { false } -fn serialize_nesting( - dest: &mut Printer, +fn serialize_nesting( + dest: &mut PrinterT, context: Option<&StyleContext>, first: bool, -) -> Result<(), PrinterError> -where - W: fmt::Write, -{ +) -> Result<(), PrinterError> { if let Some(ctx) = context { // If there's only one simple selector, just serialize it directly. // Otherwise, use an :is() pseudo class. @@ -1993,7 +1960,7 @@ where } else { // If there is no context, we are at the root if nesting is supported. This is equivalent to :scope. // Otherwise, if nesting is supported, serialize the nesting selector directly. - if should_compile!(dest.targets.current, Nesting) { + if should_compile!(dest.targets().current, Nesting) { dest.write_str(":scope")?; Ok(()) } else { @@ -2043,15 +2010,14 @@ fn is_namespace(component: Option<&Component>) -> bool { ) } -fn serialize_selector_list<'a, 'i: 'a, I, W>( +fn serialize_selector_list<'a, 'i: 'a, I, PrinterT: crate::printer::PrinterTrait>( iter: I, - dest: &mut Printer, + dest: &mut PrinterT, context: Option<&StyleContext>, is_relative: bool, ) -> Result<(), PrinterError> where I: Iterator>, - W: fmt::Write, { let mut first = true; for selector in iter { diff --git a/src/stylesheet.rs b/src/stylesheet.rs index 7fba986a..259b1309 100644 --- a/src/stylesheet.rs +++ b/src/stylesheet.rs @@ -3,6 +3,8 @@ //! A [StyleSheet](StyleSheet) represents a `.css` file or `