From f0773861e2ea492002e0f20987f379e3faad4a19 Mon Sep 17 00:00:00 2001 From: AsyncIter Date: Tue, 3 Nov 2026 19:44:21 +0800 Subject: [PATCH] refactor: use std::fmt::Write for printer output --- derive/src/to_css.rs | 5 +- examples/custom_at_rule.rs | 5 +- napi/src/at_rule_parser.rs | 2 +- src/declaration.rs | 4 +- src/macros.rs | 3 +- src/media_query.rs | 14 +- src/printer.rs | 92 ++++---- src/properties/align.rs | 64 ++--- src/properties/animation.rs | 19 +- src/properties/background.rs | 21 +- src/properties/border.rs | 1 + src/properties/border_image.rs | 4 +- src/properties/box_shadow.rs | 1 + src/properties/contain.rs | 7 +- src/properties/css_modules.rs | 1 + src/properties/custom.rs | 22 +- src/properties/display.rs | 37 +-- src/properties/effects.rs | 36 ++- src/properties/flex.rs | 1 + src/properties/font.rs | 21 +- src/properties/grid.rs | 51 +++- src/properties/list.rs | 4 +- src/properties/masking.rs | 6 +- src/properties/mod.rs | 2 + src/properties/outline.rs | 1 + src/properties/overflow.rs | 1 + src/properties/position.rs | 24 +- src/properties/size.rs | 75 ++++-- src/properties/svg.rs | 6 +- src/properties/text.rs | 16 +- src/properties/transform.rs | 69 ++++-- src/properties/transition.rs | 1 + src/properties/ui.rs | 10 +- src/rules/container.rs | 7 +- src/rules/counter_style.rs | 1 + src/rules/custom_media.rs | 4 +- src/rules/document.rs | 4 +- src/rules/font_face.rs | 16 +- src/rules/font_feature_values.rs | 6 +- src/rules/font_palette_values.rs | 14 +- src/rules/import.rs | 4 +- src/rules/keyframes.rs | 15 +- src/rules/layer.rs | 7 +- src/rules/media.rs | 4 +- src/rules/mod.rs | 2 + src/rules/namespace.rs | 4 +- src/rules/nesting.rs | 1 + src/rules/page.rs | 4 +- src/rules/position_try.rs | 1 + src/rules/property.rs | 4 +- src/rules/scope.rs | 4 +- src/rules/starting_style.rs | 4 +- src/rules/style.rs | 1 + src/rules/supports.rs | 16 +- src/rules/unknown.rs | 7 +- src/rules/view_transition.rs | 4 +- src/rules/viewport.rs | 1 + src/selector.rs | 394 +++++++++++++++++++++++-------- src/stylesheet.rs | 5 +- src/values/calc.rs | 31 ++- src/values/color.rs | 25 +- src/values/easing.rs | 29 +-- src/values/gradient.rs | 37 ++- src/values/ident.rs | 6 +- src/values/image.rs | 4 +- src/values/length.rs | 13 +- src/values/number.rs | 7 +- src/values/percentage.rs | 7 +- src/values/position.rs | 10 +- src/values/rect.rs | 1 + src/values/shape.rs | 13 +- src/values/size.rs | 1 + src/values/syntax.rs | 18 +- src/values/time.rs | 13 +- src/values/url.rs | 3 +- tests/test_custom_parser.rs | 5 +- 76 files changed, 983 insertions(+), 400 deletions(-) diff --git a/derive/src/to_css.rs b/derive/src/to_css.rs index 739a16d40..bd515efad 100644 --- a/derive/src/to_css.rs +++ b/derive/src/to_css.rs @@ -121,7 +121,10 @@ fn derive_enum(data: &DataEnum, opts: &CssOptions) -> TokenStream2 { Fields::Unit => { let s = Literal::string(&variant.ident.to_string().to_case(opts.case)); quote! { - Self::#name => dest.write_str(#s) + Self::#name => { + dest.write_str(#s)?; + Ok(()) + } } } Fields::Named(_) => { diff --git a/examples/custom_at_rule.rs b/examples/custom_at_rule.rs index b3cb49650..749566d19 100644 --- a/examples/custom_at_rule.rs +++ b/examples/custom_at_rule.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, convert::Infallible}; +use std::{collections::HashMap, convert::Infallible, fmt::Write}; use cssparser::*; use rspack_lightningcss::{ @@ -295,7 +295,8 @@ impl ToCss for AtRule { TailwindDirective::Utilities => "TAILWIND UTILITIES HERE", TailwindDirective::Variants => "TAILWIND VARIANTS HERE", }; - dest.write_str(directive) + dest.write_str(directive)?; + Ok(()) } AtRule::Apply(_) => Ok(()), } diff --git a/napi/src/at_rule_parser.rs b/napi/src/at_rule_parser.rs index dfec381b1..50cbd2c7b 100644 --- a/napi/src/at_rule_parser.rs +++ b/napi/src/at_rule_parser.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, fmt::Write}; use cssparser::*; use rspack_lightningcss::{ diff --git a/src/declaration.rs b/src/declaration.rs index 595bd3857..e9e83abaa 100644 --- a/src/declaration.rs +++ b/src/declaration.rs @@ -1,6 +1,7 @@ //! CSS declarations. use std::borrow::Cow; +use std::fmt::Write; use std::ops::Range; use crate::context::{DeclarationContext, PropertyHandlerContext}; @@ -170,7 +171,8 @@ impl<'i> DeclarationBlock<'i> { dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } pub(crate) fn has_printable_declarations(&self) -> bool { diff --git a/src/macros.rs b/src/macros.rs index 76a0c882f..be6a9d31b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -84,7 +84,8 @@ macro_rules! enum_property { impl ToCss for $name { fn to_css(&self, dest: &mut Printer) -> Result<(), PrinterError> where W: std::fmt::Write { - dest.write_str(self.as_str()) + dest.write_str(self.as_str())?; + Ok(()) } } }; diff --git a/src/media_query.rs b/src/media_query.rs index 189a61832..2d246bb57 100644 --- a/src/media_query.rs +++ b/src/media_query.rs @@ -24,6 +24,7 @@ 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; @@ -1216,7 +1217,9 @@ impl<'i, FeatureId: FeatureToCss> ToCss for QueryFeature<'i, FeatureId> { } } - dest.write_char(')') + dest.write_char(')')?; + + Ok(()) } } @@ -1508,7 +1511,8 @@ impl FeatureToCss for MediaFeatureId { MediaFeatureId::WebKitDevicePixelRatio => { dest.write_str("-webkit-")?; dest.write_str(prefix)?; - dest.write_str("device-pixel-ratio") + dest.write_str("device-pixel-ratio")?; + Ok(()) } _ => { dest.write_str(prefix)?; @@ -1704,9 +1708,11 @@ impl<'i> ToCss for MediaFeatureValue<'i> { MediaFeatureValue::Integer(num) => num.to_css(dest), MediaFeatureValue::Boolean(b) => { if *b { - dest.write_char('1') + dest.write_char('1')?; + Ok(()) } else { - dest.write_char('0') + dest.write_char('0')?; + Ok(()) } } MediaFeatureValue::Resolution(res) => res.to_css(dest), diff --git a/src/printer.rs b/src/printer.rs index 917875c36..bb21cd829 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -10,6 +10,7 @@ use crate::vendor_prefix::VendorPrefix; use cssparser::{serialize_identifier, serialize_name}; #[cfg(feature = "sourcemap")] use parcel_sourcemap::{OriginalLocation, SourceMap}; +use std::fmt::Write; /// Options that control how CSS is serialized to a string. #[derive(Default)] @@ -140,47 +141,6 @@ impl<'a, 'c, W: std::fmt::Write + Sized> Printer<'a, 'c, W> { } } - /// Writes a raw string to the underlying destination. - /// - /// NOTE: Is is assumed that the string does not contain any newline characters. - /// If such a string is written, it will break source maps. - pub fn write_str(&mut self, s: &str) -> Result<(), PrinterError> { - self.col += s.len() as u32; - self.dest.write_str(s)?; - Ok(()) - } - - /// Writes a raw string which may contain newlines to the underlying destination. - pub fn write_str_with_newlines(&mut self, s: &str) -> Result<(), PrinterError> { - let mut last_line_start: usize = 0; - - for (idx, n) in s.char_indices() { - if n == '\n' { - self.line += 1; - self.col = 0; - - // Keep track of where the *next* line starts - last_line_start = idx + 1; - } - } - - self.col += (s.len() - last_line_start) as u32; - self.dest.write_str(s)?; - Ok(()) - } - - /// Write a single character to the underlying destination. - pub fn write_char(&mut self, c: char) -> Result<(), PrinterError> { - if c == '\n' { - self.line += 1; - self.col = 0; - } else { - self.col += 1; - } - self.dest.write_char(c)?; - Ok(()) - } - /// Writes a single whitespace character, unless the `minify` option is enabled. /// /// Use `write_char` instead if you wish to force a space character to be written, @@ -190,7 +150,8 @@ impl<'a, 'c, W: std::fmt::Write + Sized> Printer<'a, 'c, W> { return Ok(()); } - self.write_char(' ') + self.write_char(' ')?; + Ok(()) } /// Writes a delimiter character, followed by whitespace (depending on the `minify` option). @@ -422,9 +383,52 @@ impl<'a, 'c, W: std::fmt::Write + Sized> Printer<'a, 'c, W> { } } -impl<'a, 'b, 'c, W: std::fmt::Write + Sized> std::fmt::Write for Printer<'a, 'c, W> { +impl<'a, 'c, W: std::fmt::Write + Sized> Write for Printer<'a, 'c, W> { fn write_str(&mut self, s: &str) -> std::fmt::Result { - self.col += s.len() as u32; + let mut last_line_start = 0; + for (idx, c) in s.char_indices() { + if c == '\n' { + self.line += 1; + last_line_start = idx + 1; + } + } + + self.col = if last_line_start == 0 { + self.col + s.len() as u32 + } else { + (s.len() - last_line_start) as u32 + }; self.dest.write_str(s) } + + fn write_char(&mut self, c: char) -> std::fmt::Result { + if c == '\n' { + self.line += 1; + self.col = 0; + } else { + self.col += 1; + } + + self.dest.write_char(c) + } +} + +#[cfg(test)] +mod tests { + use super::{Printer, PrinterOptions}; + use std::fmt::Write; + + #[test] + fn write_tracks_multiline_positions() { + let mut output = String::new(); + let mut printer = Printer::new(&mut output, PrinterOptions::default()); + + printer.write_str("a\nbc").unwrap(); + printer.write_char('\n').unwrap(); + printer.write_str("d").unwrap(); + + assert_eq!((printer.line, printer.col), (2, 1)); + drop(printer); + assert_eq!(output, "a\nbc\nd"); + } } diff --git a/src/properties/align.rs b/src/properties/align.rs index 644903cc2..c4ec29696 100644 --- a/src/properties/align.rs +++ b/src/properties/align.rs @@ -16,6 +16,7 @@ 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; @@ -64,9 +65,10 @@ impl ToCss for BaselinePosition { W: std::fmt::Write, { match self { - BaselinePosition::First => dest.write_str("baseline"), - BaselinePosition::Last => dest.write_str("last baseline"), - } + BaselinePosition::First => dest.write_str("baseline")?, + BaselinePosition::Last => dest.write_str("last baseline")?, + }; + Ok(()) } } @@ -211,15 +213,15 @@ impl ToCss for JustifyContent { W: std::fmt::Write, { match self { - JustifyContent::Normal => dest.write_str("normal"), - JustifyContent::ContentDistribution(value) => value.to_css(dest), + JustifyContent::Normal => dest.write_str("normal")?, + JustifyContent::ContentDistribution(value) => value.to_css(dest)?, JustifyContent::ContentPosition { overflow, value } => { if let Some(overflow) = overflow { overflow.to_css(dest)?; dest.write_str(" ")?; } - value.to_css(dest) + value.to_css(dest)?; } JustifyContent::Left { overflow } => { if let Some(overflow) = overflow { @@ -227,7 +229,7 @@ impl ToCss for JustifyContent { dest.write_str(" ")?; } - dest.write_str("left") + dest.write_str("left")?; } JustifyContent::Right { overflow } => { if let Some(overflow) = overflow { @@ -235,9 +237,10 @@ impl ToCss for JustifyContent { dest.write_str(" ")?; } - dest.write_str("right") + dest.write_str("right")?; } - } + }; + Ok(()) } } @@ -434,17 +437,17 @@ impl ToCss for JustifySelf { W: std::fmt::Write, { match self { - JustifySelf::Auto => dest.write_str("auto"), - JustifySelf::Normal => dest.write_str("normal"), - JustifySelf::Stretch => dest.write_str("stretch"), - JustifySelf::BaselinePosition(val) => val.to_css(dest), + JustifySelf::Auto => dest.write_str("auto")?, + JustifySelf::Normal => dest.write_str("normal")?, + JustifySelf::Stretch => dest.write_str("stretch")?, + JustifySelf::BaselinePosition(val) => val.to_css(dest)?, JustifySelf::SelfPosition { overflow, value } => { if let Some(overflow) = overflow { overflow.to_css(dest)?; dest.write_str(" ")?; } - value.to_css(dest) + value.to_css(dest)?; } JustifySelf::Left { overflow } => { if let Some(overflow) = overflow { @@ -452,7 +455,7 @@ impl ToCss for JustifySelf { dest.write_str(" ")?; } - dest.write_str("left") + dest.write_str("left")?; } JustifySelf::Right { overflow } => { if let Some(overflow) = overflow { @@ -460,9 +463,10 @@ impl ToCss for JustifySelf { dest.write_str(" ")?; } - dest.write_str("right") + dest.write_str("right")?; } - } + }; + Ok(()) } } @@ -616,10 +620,11 @@ impl ToCss for LegacyJustify { { dest.write_str("legacy ")?; match self { - LegacyJustify::Left => dest.write_str("left"), - LegacyJustify::Right => dest.write_str("right"), - LegacyJustify::Center => dest.write_str("center"), - } + LegacyJustify::Left => dest.write_str("left")?, + LegacyJustify::Right => dest.write_str("right")?, + LegacyJustify::Center => dest.write_str("center")?, + }; + Ok(()) } } @@ -704,17 +709,17 @@ impl ToCss for JustifyItems { W: std::fmt::Write, { match self { - JustifyItems::Normal => dest.write_str("normal"), - JustifyItems::Stretch => dest.write_str("stretch"), - JustifyItems::BaselinePosition(val) => val.to_css(dest), - JustifyItems::Legacy(val) => val.to_css(dest), + JustifyItems::Normal => dest.write_str("normal")?, + JustifyItems::Stretch => dest.write_str("stretch")?, + JustifyItems::BaselinePosition(val) => val.to_css(dest)?, + JustifyItems::Legacy(val) => val.to_css(dest)?, JustifyItems::SelfPosition { overflow, value } => { if let Some(overflow) = overflow { overflow.to_css(dest)?; dest.write_str(" ")?; } - value.to_css(dest) + value.to_css(dest)?; } JustifyItems::Left { overflow } => { if let Some(overflow) = overflow { @@ -722,7 +727,7 @@ impl ToCss for JustifyItems { dest.write_str(" ")?; } - dest.write_str("left") + dest.write_str("left")?; } JustifyItems::Right { overflow } => { if let Some(overflow) = overflow { @@ -730,9 +735,10 @@ impl ToCss for JustifyItems { dest.write_str(" ")?; } - dest.write_str("right") + dest.write_str("right")?; } - } + }; + Ok(()) } } diff --git a/src/properties/animation.rs b/src/properties/animation.rs index c5930ce58..5e6b65416 100644 --- a/src/properties/animation.rs +++ b/src/properties/animation.rs @@ -1,6 +1,7 @@ //! CSS properties related to keyframe animations. use std::borrow::Cow; +use std::fmt::Write; use crate::context::PropertyHandlerContext; use crate::declaration::{DeclarationBlock, DeclarationList}; @@ -54,7 +55,10 @@ impl<'i> ToCss for AnimationName<'i> { dest.css_module.as_ref().map_or(false, |css_module| css_module.config.animation); match self { - AnimationName::None => dest.write_str("none"), + AnimationName::None => { + dest.write_str("none")?; + Ok(()) + } AnimationName::Ident(s) => { if css_module_animation_enabled { if let Some(css_module) = &mut dest.css_module { @@ -270,7 +274,9 @@ impl ToCss for ScrollTimeline { self.axis.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + + Ok(()) } } @@ -372,7 +378,9 @@ impl ToCss for ViewTimeline { self.inset.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + + Ok(()) } } @@ -451,7 +459,10 @@ impl<'i> AnimationAttachmentRange { W: std::fmt::Write, { match self { - Self::Normal => dest.write_str("normal"), + Self::Normal => { + dest.write_str("normal")?; + Ok(()) + } Self::LengthPercentage(val) => val.to_css(dest), Self::TimelineRange { name, offset } => { name.to_css(dest)?; diff --git a/src/properties/background.rs b/src/properties/background.rs index efaae2fba..1864e7e76 100644 --- a/src/properties/background.rs +++ b/src/properties/background.rs @@ -18,6 +18,7 @@ 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)] @@ -81,8 +82,14 @@ impl ToCss for BackgroundSize { use BackgroundSize::*; match &self { - Cover => dest.write_str("cover"), - Contain => dest.write_str("contain"), + Cover => { + dest.write_str("cover")?; + Ok(()) + } + Contain => { + dest.write_str("contain")?; + Ok(()) + } Explicit { width, height } => { width.to_css(dest)?; if *height != NonNegative(LengthPercentageOrAuto::Auto) { @@ -173,8 +180,14 @@ impl ToCss for BackgroundRepeat { { use BackgroundRepeatKeyword::*; match (&self.x, &self.y) { - (Repeat, NoRepeat) => dest.write_str("repeat-x"), - (NoRepeat, Repeat) => dest.write_str("repeat-y"), + (Repeat, NoRepeat) => { + dest.write_str("repeat-x")?; + Ok(()) + } + (NoRepeat, Repeat) => { + dest.write_str("repeat-y")?; + Ok(()) + } (x, y) => { x.to_css(dest)?; if y != x { diff --git a/src/properties/border.rs b/src/properties/border.rs index 34cd971ad..2825276ef 100644 --- a/src/properties/border.rs +++ b/src/properties/border.rs @@ -22,6 +22,7 @@ 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)] diff --git a/src/properties/border_image.rs b/src/properties/border_image.rs index ed68bb343..f38c7b7ee 100644 --- a/src/properties/border_image.rs +++ b/src/properties/border_image.rs @@ -23,6 +23,7 @@ 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. @@ -311,7 +312,8 @@ impl<'i> BorderImage<'i> { // A shorthand with only initial components must still have a value. if !has_source && !has_slice && !has_width && !has_outset && !has_repeat { - return dest.write_str("none"); + dest.write_str("none")?; + return Ok(()); } if has_source { diff --git a/src/properties/box_shadow.rs b/src/properties/box_shadow.rs index bf4b4403f..bab3bfb57 100644 --- a/src/properties/box_shadow.rs +++ b/src/properties/box_shadow.rs @@ -17,6 +17,7 @@ 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)] diff --git a/src/properties/contain.rs b/src/properties/contain.rs index 99e406ae8..134b22229 100644 --- a/src/properties/contain.rs +++ b/src/properties/contain.rs @@ -2,6 +2,8 @@ #![allow(non_upper_case_globals)] +use std::fmt::Write; + use cssparser::*; use smallvec::SmallVec; @@ -96,7 +98,10 @@ impl<'i> ToCss for ContainerNameList<'i> { W: std::fmt::Write, { match self { - ContainerNameList::None => dest.write_str("none"), + ContainerNameList::None => { + dest.write_str("none")?; + Ok(()) + } ContainerNameList::Names(names) => { let mut first = true; for name in names { diff --git a/src/properties/css_modules.rs b/src/properties/css_modules.rs index 49170ff41..f699bbe38 100644 --- a/src/properties/css_modules.rs +++ b/src/properties/css_modules.rs @@ -10,6 +10,7 @@ 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)] diff --git a/src/properties/custom.rs b/src/properties/custom.rs index d78247847..f77fff28a 100644 --- a/src/properties/custom.rs +++ b/src/properties/custom.rs @@ -26,6 +26,7 @@ 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")] @@ -1221,7 +1222,8 @@ impl<'i> Variable<'i> { } fallback.to_css(dest, is_custom_property)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } fn get_fallback(&self, kind: ColorFallbackKind) -> Self { @@ -1398,7 +1400,8 @@ impl<'i> EnvironmentVariable<'i> { } fallback.to_css(dest, is_custom_property)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } fn get_fallback(&self, kind: ColorFallbackKind) -> Self { @@ -1433,7 +1436,8 @@ impl<'i> Function<'i> { self.name.to_css(dest)?; dest.write_char('(')?; self.arguments.to_css(dest, is_custom_property)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } fn get_fallback(&self, kind: ColorFallbackKind) -> Self { @@ -1577,7 +1581,8 @@ impl<'i> UnresolvedColor<'i> { b.to_css(dest)?; dest.delim('/', true)?; alpha.to_css(dest, is_custom_property)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } UnresolvedColor::HSL { h, s, l, alpha } => { if should_compile!(dest.targets.current, SpaceSeparatedColorNotation) { @@ -1601,7 +1606,8 @@ impl<'i> UnresolvedColor<'i> { Percentage(*l / 100.0).to_css(dest)?; dest.delim('/', true)?; alpha.to_css(dest, is_custom_property)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } UnresolvedColor::LightDark { light, dark } => { if should_compile!(dest.targets.current, LightDark) { @@ -1613,14 +1619,16 @@ impl<'i> UnresolvedColor<'i> { dest.write_str("var(--lightningcss-dark")?; dest.delim(',', false)?; dark.to_css(dest, is_custom_property)?; - return dest.write_char(')'); + dest.write_char(')')?; + return Ok(()); } dest.write_str("light-dark(")?; light.to_css(dest, is_custom_property)?; dest.delim(',', false)?; dark.to_css(dest, is_custom_property)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } } } diff --git a/src/properties/display.rs b/src/properties/display.rs index 8b1e0a0f1..a82e30abd 100644 --- a/src/properties/display.rs +++ b/src/properties/display.rs @@ -13,6 +13,7 @@ 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. @@ -72,24 +73,25 @@ impl ToCss for DisplayInside { W: std::fmt::Write, { match self { - DisplayInside::Flow => dest.write_str("flow"), - DisplayInside::FlowRoot => dest.write_str("flow-root"), - DisplayInside::Table => dest.write_str("table"), + DisplayInside::Flow => dest.write_str("flow")?, + DisplayInside::FlowRoot => dest.write_str("flow-root")?, + DisplayInside::Table => dest.write_str("table")?, DisplayInside::Flex(prefix) => { prefix.to_css(dest)?; if *prefix == VendorPrefix::Ms { - dest.write_str("flexbox") + dest.write_str("flexbox")?; } else { - dest.write_str("flex") + dest.write_str("flex")?; } } DisplayInside::Box(prefix) => { prefix.to_css(dest)?; - dest.write_str("box") + dest.write_str("box")?; } - DisplayInside::Grid => dest.write_str("grid"), - DisplayInside::Ruby => dest.write_str("ruby"), - } + DisplayInside::Grid => dest.write_str("grid")?, + DisplayInside::Ruby => dest.write_str("ruby")?, + }; + Ok(()) } } @@ -235,12 +237,12 @@ impl ToCss for DisplayPair { outside: DisplayOutside::Inline, inside: DisplayInside::FlowRoot, is_list_item: false, - } => dest.write_str("inline-block"), + } => dest.write_str("inline-block")?, DisplayPair { outside: DisplayOutside::Inline, inside: DisplayInside::Table, is_list_item: false, - } => dest.write_str("inline-table"), + } => dest.write_str("inline-table")?, DisplayPair { outside: DisplayOutside::Inline, inside: DisplayInside::Flex(prefix), @@ -248,9 +250,9 @@ impl ToCss for DisplayPair { } => { prefix.to_css(dest)?; if *prefix == VendorPrefix::Ms { - dest.write_str("inline-flexbox") + dest.write_str("inline-flexbox")?; } else { - dest.write_str("inline-flex") + dest.write_str("inline-flex")?; } } DisplayPair { @@ -259,13 +261,13 @@ impl ToCss for DisplayPair { is_list_item: false, } => { prefix.to_css(dest)?; - dest.write_str("inline-box") + dest.write_str("inline-box")?; } DisplayPair { outside: DisplayOutside::Inline, inside: DisplayInside::Grid, is_list_item: false, - } => dest.write_str("inline-grid"), + } => dest.write_str("inline-grid")?, DisplayPair { outside, inside, @@ -296,10 +298,9 @@ impl ToCss for DisplayPair { } dest.write_str("list-item")?; } - - Ok(()) } - } + }; + Ok(()) } } diff --git a/src/properties/effects.rs b/src/properties/effects.rs index 684965ef6..0979cd735 100644 --- a/src/properties/effects.rs +++ b/src/properties/effects.rs @@ -12,6 +12,7 @@ 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)] @@ -127,7 +128,8 @@ impl<'i> ToCss for Filter<'i> { if *val != NonNegative::zero() { val.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Filter::Brightness(val) => { dest.write_str("brightness(")?; @@ -135,7 +137,8 @@ impl<'i> ToCss for Filter<'i> { if v != 1.0 { val.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Filter::Contrast(val) => { dest.write_str("contrast(")?; @@ -143,7 +146,8 @@ impl<'i> ToCss for Filter<'i> { if v != 1.0 { val.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Filter::Grayscale(val) => { dest.write_str("grayscale(")?; @@ -151,14 +155,16 @@ impl<'i> ToCss for Filter<'i> { if v != 1.0 { val.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Filter::HueRotate(val) => { dest.write_str("hue-rotate(")?; if !val.is_zero() { val.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Filter::Invert(val) => { dest.write_str("invert(")?; @@ -166,7 +172,8 @@ impl<'i> ToCss for Filter<'i> { if v != 1.0 { val.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Filter::Opacity(val) => { dest.write_str("opacity(")?; @@ -174,7 +181,8 @@ impl<'i> ToCss for Filter<'i> { if v != 1.0 { val.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Filter::Saturate(val) => { dest.write_str("saturate(")?; @@ -182,7 +190,8 @@ impl<'i> ToCss for Filter<'i> { if v != 1.0 { val.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Filter::Sepia(val) => { dest.write_str("sepia(")?; @@ -190,12 +199,14 @@ impl<'i> ToCss for Filter<'i> { if v != 1.0 { val.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Filter::DropShadow(val) => { dest.write_str("drop-shadow(")?; val.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Filter::Url(url) => url.to_css(dest), } @@ -350,7 +361,10 @@ impl<'i> ToCss for FilterList<'i> { W: std::fmt::Write, { match self { - FilterList::None => dest.write_str("none"), + FilterList::None => { + dest.write_str("none")?; + Ok(()) + } FilterList::Filters(filters) => { let mut first = true; for filter in filters { diff --git a/src/properties/flex.rs b/src/properties/flex.rs index 0a474b222..2ec6f884e 100644 --- a/src/properties/flex.rs +++ b/src/properties/flex.rs @@ -20,6 +20,7 @@ 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. diff --git a/src/properties/font.rs b/src/properties/font.rs index 68db243df..f59b9b450 100644 --- a/src/properties/font.rs +++ b/src/properties/font.rs @@ -1,6 +1,7 @@ //! CSS properties related to fonts. use std::collections::HashSet; +use std::fmt::Write; use super::{Property, PropertyId}; use crate::compat::Feature; @@ -87,10 +88,11 @@ impl ToCss for AbsoluteFontWeight { { 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" }), - } + 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" })?, + }; + Ok(()) } } @@ -439,7 +441,8 @@ impl<'i> ToCss for FamilyName<'i> { serialize_identifier(slice, &mut id)?; } if id.len() < val.len() + 2 { - return dest.write_str(&id); + dest.write_str(&id)?; + return Ok(()); } } serialize_string(&val, dest)?; @@ -512,17 +515,17 @@ impl ToCss for FontStyle { W: std::fmt::Write, { match self { - FontStyle::Normal => dest.write_str("normal"), - FontStyle::Italic => dest.write_str("italic"), + FontStyle::Normal => dest.write_str("normal")?, + FontStyle::Italic => dest.write_str("italic")?, FontStyle::Oblique(angle) => { dest.write_str("oblique")?; if *angle != FontStyle::default_oblique_angle() { dest.write_char(' ')?; angle.to_css(dest)?; } - Ok(()) } - } + }; + Ok(()) } } diff --git a/src/properties/grid.rs b/src/properties/grid.rs index 6c7cb3bfe..b4a20bc9a 100644 --- a/src/properties/grid.rs +++ b/src/properties/grid.rs @@ -2,6 +2,8 @@ #![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}; @@ -231,12 +233,14 @@ impl ToCss for TrackSize { min.to_css(dest)?; dest.delim(',', false)?; max.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } TrackSize::FitContent(len) => { dest.write_str("fit-content(")?; len.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } } } @@ -294,9 +298,18 @@ impl ToCss for TrackBreadth { W: std::fmt::Write, { match self { - TrackBreadth::Auto => dest.write_str("auto"), - TrackBreadth::MinContent => dest.write_str("min-content"), - TrackBreadth::MaxContent => dest.write_str("max-content"), + TrackBreadth::Auto => { + dest.write_str("auto")?; + Ok(()) + } + TrackBreadth::MinContent => { + dest.write_str("min-content")?; + Ok(()) + } + TrackBreadth::MaxContent => { + dest.write_str("max-content")?; + Ok(()) + } TrackBreadth::Length(len) => len.to_css(dest), TrackBreadth::Flex(flex) => serialize_dimension(flex.0, "fr", dest), } @@ -363,7 +376,9 @@ impl<'i> ToCss for TrackRepeat<'i> { first = false; } - dest.write_char(')') + dest.write_char(')')?; + + Ok(()) } } @@ -394,7 +409,8 @@ where } write_ident(&name.0, dest)?; } - dest.write_char(']') + dest.write_char(']')?; + Ok(()) } fn write_ident(name: &str, dest: &mut Printer) -> Result<(), PrinterError> @@ -518,7 +534,8 @@ impl ToCss for TrackSizeList { W: std::fmt::Write, { if self.0.len() == 0 { - return dest.write_str("auto"); + dest.write_str("auto")?; + return Ok(()); } let mut first = true; @@ -632,7 +649,10 @@ impl ToCss for GridTemplateAreas { W: std::fmt::Write, { match self { - GridTemplateAreas::None => dest.write_str("none"), + GridTemplateAreas::None => { + dest.write_str("none")?; + Ok(()) + } GridTemplateAreas::Areas { areas, .. } => { let mut iter = areas.iter(); let mut next = iter.next(); @@ -701,7 +721,9 @@ impl GridTemplateAreas { *next = iter.next(); } - dest.write_char('"') + dest.write_char('"')?; + + Ok(()) } } @@ -1102,7 +1124,9 @@ impl ToCss for GridAutoFlow { unreachable!(); }; - dest.write_str(s) + dest.write_str(s)?; + + Ok(()) } } @@ -1436,7 +1460,10 @@ impl ToCss for GridLine<'_> { W: std::fmt::Write, { match self { - GridLine::Auto => dest.write_str("auto"), + GridLine::Auto => { + dest.write_str("auto")?; + Ok(()) + } GridLine::Area { name } => write_ident(&name.0, dest), GridLine::Line { index, name } => { index.to_css(dest)?; diff --git a/src/properties/list.rs b/src/properties/list.rs index 09ef38c6a..84a04e9e8 100644 --- a/src/properties/list.rs +++ b/src/properties/list.rs @@ -13,6 +13,7 @@ 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)] @@ -240,7 +241,8 @@ impl ToCss for CounterStyle<'_> { symbol.to_css(dest)?; needs_space = true; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } } } diff --git a/src/properties/masking.rs b/src/properties/masking.rs index 07e2e02d7..e9f89b361 100644 --- a/src/properties/masking.rs +++ b/src/properties/masking.rs @@ -23,6 +23,7 @@ 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. @@ -433,7 +434,10 @@ impl<'i> ToCss for ClipPath<'i> { W: std::fmt::Write, { match self { - ClipPath::None => dest.write_str("none"), + ClipPath::None => { + dest.write_str("none")?; + Ok(()) + } ClipPath::Url(url) => url.to_css(dest), ClipPath::Shape { shape, diff --git a/src/properties/mod.rs b/src/properties/mod.rs index 956e8964c..1b5b6ead0 100644 --- a/src/properties/mod.rs +++ b/src/properties/mod.rs @@ -90,6 +90,8 @@ #![deny(missing_docs)] +use std::fmt::Write; + pub mod align; pub mod animation; pub mod background; diff --git a/src/properties/outline.rs b/src/properties/outline.rs index c31654e53..839147c76 100644 --- a/src/properties/outline.rs +++ b/src/properties/outline.rs @@ -13,6 +13,7 @@ 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 bb5e54b09..3c6b9e516 100644 --- a/src/properties/overflow.rs +++ b/src/properties/overflow.rs @@ -11,6 +11,7 @@ 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 diff --git a/src/properties/position.rs b/src/properties/position.rs index d3e611d4c..3bd40b56a 100644 --- a/src/properties/position.rs +++ b/src/properties/position.rs @@ -12,6 +12,7 @@ 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)] @@ -60,13 +61,26 @@ impl ToCss for Position { W: std::fmt::Write, { match self { - Position::Static => dest.write_str("static"), - Position::Relative => dest.write_str("relative"), - Position::Absolute => dest.write_str("absolute"), - Position::Fixed => dest.write_str("fixed"), + Position::Static => { + dest.write_str("static")?; + Ok(()) + } + Position::Relative => { + dest.write_str("relative")?; + Ok(()) + } + Position::Absolute => { + dest.write_str("absolute")?; + Ok(()) + } + Position::Fixed => { + dest.write_str("fixed")?; + Ok(()) + } Position::Sticky(prefix) => { prefix.to_css(dest)?; - dest.write_str("sticky") + dest.write_str("sticky")?; + Ok(()) } } } diff --git a/src/properties/size.rs b/src/properties/size.rs index f0e7d47e9..1ca771eea 100644 --- a/src/properties/size.rs +++ b/src/properties/size.rs @@ -17,6 +17,7 @@ use crate::vendor_prefix::VendorPrefix; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; +use std::fmt::Write; #[cfg(feature = "serde")] use crate::serialization::*; @@ -103,30 +104,49 @@ impl ToCss for Size { { use Size::*; match self { - Auto => dest.write_str("auto"), - Contain => dest.write_str("contain"), + Auto => { + dest.write_str("auto")?; + Ok(()) + } + Contain => { + dest.write_str("contain")?; + Ok(()) + } MinContent(vp) => { vp.to_css(dest)?; - dest.write_str("min-content") + dest.write_str("min-content")?; + Ok(()) } MaxContent(vp) => { vp.to_css(dest)?; - dest.write_str("max-content") + dest.write_str("max-content")?; + Ok(()) } FitContent(vp) => { vp.to_css(dest)?; - dest.write_str("fit-content") + dest.write_str("fit-content")?; + Ok(()) } Stretch(vp) => match *vp { - VendorPrefix::None => dest.write_str("stretch"), - VendorPrefix::WebKit => dest.write_str("-webkit-fill-available"), - VendorPrefix::Moz => dest.write_str("-moz-available"), + VendorPrefix::None => { + dest.write_str("stretch")?; + Ok(()) + } + VendorPrefix::WebKit => { + dest.write_str("-webkit-fill-available")?; + Ok(()) + } + VendorPrefix::Moz => { + dest.write_str("-moz-available")?; + Ok(()) + } _ => unreachable!(), }, FitContentFunction(l) => { dest.write_str("fit-content(")?; l.to_css(dest)?; - dest.write_str(")") + dest.write_str(")")?; + Ok(()) } LengthPercentage(l) => l.to_css(dest), } @@ -236,30 +256,49 @@ impl ToCss for MaxSize { { use MaxSize::*; match self { - None => dest.write_str("none"), - Contain => dest.write_str("contain"), + None => { + dest.write_str("none")?; + Ok(()) + } + Contain => { + dest.write_str("contain")?; + Ok(()) + } MinContent(vp) => { vp.to_css(dest)?; - dest.write_str("min-content") + dest.write_str("min-content")?; + Ok(()) } MaxContent(vp) => { vp.to_css(dest)?; - dest.write_str("max-content") + dest.write_str("max-content")?; + Ok(()) } FitContent(vp) => { vp.to_css(dest)?; - dest.write_str("fit-content") + dest.write_str("fit-content")?; + Ok(()) } Stretch(vp) => match *vp { - VendorPrefix::None => dest.write_str("stretch"), - VendorPrefix::WebKit => dest.write_str("-webkit-fill-available"), - VendorPrefix::Moz => dest.write_str("-moz-available"), + VendorPrefix::None => { + dest.write_str("stretch")?; + Ok(()) + } + VendorPrefix::WebKit => { + dest.write_str("-webkit-fill-available")?; + Ok(()) + } + VendorPrefix::Moz => { + dest.write_str("-moz-available")?; + Ok(()) + } _ => unreachable!(), }, FitContentFunction(l) => { dest.write_str("fit-content(")?; l.to_css(dest)?; - dest.write_str(")") + dest.write_str(")")?; + Ok(()) } LengthPercentage(l) => l.to_css(dest), } diff --git a/src/properties/svg.rs b/src/properties/svg.rs index 374d6ed5a..ea9657cd1 100644 --- a/src/properties/svg.rs +++ b/src/properties/svg.rs @@ -11,6 +11,7 @@ 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. @@ -175,7 +176,10 @@ impl ToCss for StrokeDasharray { W: std::fmt::Write, { match self { - StrokeDasharray::None => dest.write_str("none"), + StrokeDasharray::None => { + dest.write_str("none")?; + Ok(()) + } StrokeDasharray::Values(values) => { let mut first = true; for value in values { diff --git a/src/properties/text.rs b/src/properties/text.rs index ffba74af0..5d4f3c90b 100644 --- a/src/properties/text.rs +++ b/src/properties/text.rs @@ -2,6 +2,8 @@ #![allow(non_upper_case_globals)] +use std::fmt::Write; + use super::{Property, PropertyId}; use crate::compat; use crate::context::PropertyHandlerContext; @@ -537,15 +539,18 @@ impl ToCss for TextDecorationLine { W: std::fmt::Write, { if self.is_empty() { - return dest.write_str("none"); + dest.write_str("none")?; + return Ok(()); } if self.contains(TextDecorationLine::SpellingError) { - return dest.write_str("spelling-error"); + dest.write_str("spelling-error")?; + return Ok(()); } if self.contains(TextDecorationLine::GrammarError) { - return dest.write_str("grammar-error"); + dest.write_str("grammar-error")?; + return Ok(()); } let mut needs_space = false; @@ -926,7 +931,10 @@ impl<'i> ToCss for TextEmphasisStyle<'i> { W: std::fmt::Write, { match self { - TextEmphasisStyle::None => dest.write_str("none"), + TextEmphasisStyle::None => { + dest.write_str("none")?; + Ok(()) + } TextEmphasisStyle::String(s) => s.to_css(dest), TextEmphasisStyle::Keyword { fill, shape } => { let mut needs_space = false; diff --git a/src/properties/transform.rs b/src/properties/transform.rs index b3135c3e6..a6e906319 100644 --- a/src/properties/transform.rs +++ b/src/properties/transform.rs @@ -19,6 +19,7 @@ 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)] @@ -1041,22 +1042,26 @@ impl ToCss for Transform { y.to_css(dest)?; } } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } TranslateX(x) => { dest.write_str(if dest.minify { "translate(" } else { "translateX(" })?; x.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } TranslateY(y) => { dest.write_str("translateY(")?; y.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } TranslateZ(z) => { dest.write_str("translateZ(")?; z.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Translate3d(x, y, z) => { if dest.minify && y.is_zero() && z.is_zero() { @@ -1081,7 +1086,8 @@ impl ToCss for Transform { dest.delim(',', false)?; z.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Scale(x, y) => { let x: f32 = x.into(); @@ -1100,25 +1106,29 @@ impl ToCss for Transform { y.to_css(dest)?; } } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } ScaleX(x) => { let x: f32 = x.into(); dest.write_str("scaleX(")?; x.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } ScaleY(y) => { let y: f32 = y.into(); dest.write_str("scaleY(")?; y.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } ScaleZ(z) => { let z: f32 = z.into(); dest.write_str("scaleZ(")?; z.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Scale3d(x, y, z) => { let x: f32 = x.into(); @@ -1154,27 +1164,32 @@ impl ToCss for Transform { dest.delim(',', false)?; z.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Rotate(angle) => { dest.write_str("rotate(")?; angle.to_css_with_unitless_zero(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } RotateX(angle) => { dest.write_str("rotateX(")?; angle.to_css_with_unitless_zero(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } RotateY(angle) => { dest.write_str("rotateY(")?; angle.to_css_with_unitless_zero(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } RotateZ(angle) => { dest.write_str(if dest.minify { "rotate(" } else { "rotateZ(" })?; angle.to_css_with_unitless_zero(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Rotate3d(x, y, z, angle) => { if dest.minify && *x == 1.0 && *y == 0.0 && *z == 0.0 { @@ -1199,7 +1214,8 @@ impl ToCss for Transform { dest.delim(',', false)?; angle.to_css_with_unitless_zero(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Skew(x, y) => { if dest.minify && x.is_zero() && !y.is_zero() { @@ -1213,22 +1229,26 @@ impl ToCss for Transform { y.to_css_with_unitless_zero(dest)?; } } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } SkewX(angle) => { dest.write_str(if dest.minify { "skew(" } else { "skewX(" })?; angle.to_css_with_unitless_zero(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } SkewY(angle) => { dest.write_str("skewY(")?; angle.to_css_with_unitless_zero(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Perspective(len) => { dest.write_str("perspective(")?; len.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Matrix(super::transform::Matrix { a, b, c, d, e, f }) => { dest.write_str("matrix(")?; @@ -1243,7 +1263,8 @@ impl ToCss for Transform { e.to_css(dest)?; dest.delim(',', false)?; f.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Matrix3d(super::transform::Matrix3d { m11, @@ -1295,7 +1316,8 @@ impl ToCss for Transform { m43.to_css(dest)?; dest.delim(',', false)?; m44.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } } } @@ -1579,7 +1601,10 @@ impl ToCss for Rotate { W: std::fmt::Write, { match self { - Rotate::None => dest.write_str("none"), + Rotate::None => { + dest.write_str("none")?; + Ok(()) + } Rotate::XYZ { x, y, z, angle } => { // CSS Transforms 2 ยง5.1: // "If the axis is parallel with the x or y axes, it must serialize as the appropriate keyword." diff --git a/src/properties/transition.rs b/src/properties/transition.rs index 092f13fd1..892281dbf 100644 --- a/src/properties/transition.rs +++ b/src/properties/transition.rs @@ -19,6 +19,7 @@ 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. diff --git a/src/properties/ui.rs b/src/properties/ui.rs index f0b37074b..a6fa1789d 100644 --- a/src/properties/ui.rs +++ b/src/properties/ui.rs @@ -17,6 +17,7 @@ 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}; @@ -371,7 +372,8 @@ impl<'i> ToCss for Appearance<'i> { where W: std::fmt::Write, { - dest.write_str(self.to_str()) + dest.write_str(self.to_str())?; + Ok(()) } } @@ -480,7 +482,8 @@ impl ToCss for ColorScheme { W: std::fmt::Write, { if self.is_empty() { - return dest.write_str("normal"); + dest.write_str("normal")?; + return Ok(()); } if self.contains(ColorScheme::Light) { @@ -497,7 +500,8 @@ impl ToCss for ColorScheme { if self.contains(ColorScheme::Only) { // Avoid parsing `color-scheme: only` as `color-scheme: only` if !self.intersects(ColorScheme::Light | ColorScheme::Dark) { - return dest.write_str("only"); + dest.write_str("only")?; + return Ok(()); } dest.write_str(" only")?; } diff --git a/src/rules/container.rs b/src/rules/container.rs index 90ca7fac2..0b8c341ae 100644 --- a/src/rules/container.rs +++ b/src/rules/container.rs @@ -1,6 +1,7 @@ //! The `@container` rule. use cssparser::*; +use std::fmt::Write; use super::Location; use super::{CssRuleList, MinifyContext}; @@ -366,7 +367,8 @@ impl<'i> ToCss for ContainerCondition<'i> { ContainerCondition::Style(ref query) => { dest.write_str("style(")?; query.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } ContainerCondition::ScrollState(ref query) => { let needs_parens = !matches!(query, ScrollStateQuery::Feature(_)); @@ -502,6 +504,7 @@ impl<'a, 'i, T: ToCss> ToCss for ContainerRule<'i, T> { self.rules.to_css(dest)?; dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } diff --git a/src/rules/counter_style.rs b/src/rules/counter_style.rs index 703618d3e..1550cbe9b 100644 --- a/src/rules/counter_style.rs +++ b/src/rules/counter_style.rs @@ -8,6 +8,7 @@ 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)] diff --git a/src/rules/custom_media.rs b/src/rules/custom_media.rs index 2fbd0a1de..9c3b74536 100644 --- a/src/rules/custom_media.rs +++ b/src/rules/custom_media.rs @@ -8,6 +8,7 @@ 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)] @@ -37,6 +38,7 @@ impl<'i> ToCss for CustomMediaRule<'i> { self.name.to_css(dest)?; dest.write_char(' ')?; self.query.to_css(dest)?; - dest.write_char(';') + dest.write_char(';')?; + Ok(()) } } diff --git a/src/rules/document.rs b/src/rules/document.rs index 669609cfc..4f99c816e 100644 --- a/src/rules/document.rs +++ b/src/rules/document.rs @@ -8,6 +8,7 @@ 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. /// @@ -48,6 +49,7 @@ impl<'i, T: ToCss> ToCss for MozDocumentRule<'i, T> { self.rules.to_css(dest)?; dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } diff --git a/src/rules/font_face.rs b/src/rules/font_face.rs index 6be608220..15f2e2693 100644 --- a/src/rules/font_face.rs +++ b/src/rules/font_face.rs @@ -110,7 +110,8 @@ impl<'i> ToCss for Source<'i> { Source::Local(local) => { dest.write_str("local(")?; local.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } } } @@ -425,8 +426,14 @@ impl ToCss for FontStyle { W: std::fmt::Write, { match self { - FontStyle::Normal => dest.write_str("normal"), - FontStyle::Italic => dest.write_str("italic"), + FontStyle::Normal => { + dest.write_str("normal")?; + Ok(()) + } + FontStyle::Italic => { + dest.write_str("italic")?; + Ok(()) + } FontStyle::Oblique(angle) => { dest.write_str("oblique")?; if *angle != FontStyle::default_oblique_angle() { @@ -530,7 +537,8 @@ impl<'i> ToCss for FontFaceRule<'i> { } dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } diff --git a/src/rules/font_feature_values.rs b/src/rules/font_feature_values.rs index 32b0c5c56..d8ff73d94 100644 --- a/src/rules/font_feature_values.rs +++ b/src/rules/font_feature_values.rs @@ -169,7 +169,8 @@ impl<'i> ToCss for FontFeatureValuesRule<'i> { dest.newline()?; } } - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } @@ -272,7 +273,8 @@ impl<'i> ToCss for FontFeatureSubrule<'i> { } dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } diff --git a/src/rules/font_palette_values.rs b/src/rules/font_palette_values.rs index 05805dcbc..cb5a3d7ef 100644 --- a/src/rules/font_palette_values.rs +++ b/src/rules/font_palette_values.rs @@ -15,6 +15,7 @@ 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)] @@ -207,8 +208,14 @@ impl ToCss for BasePalette { W: std::fmt::Write, { match self { - BasePalette::Light => dest.write_str("light"), - BasePalette::Dark => dest.write_str("dark"), + BasePalette::Light => { + dest.write_str("light")?; + Ok(()) + } + BasePalette::Dark => { + dest.write_str("dark")?; + Ok(()) + } BasePalette::Integer(i) => (*i as CSSInteger).to_css(dest), } } @@ -379,7 +386,8 @@ impl<'i> ToCss for FontPaletteValuesRule<'i> { } dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } diff --git a/src/rules/import.rs b/src/rules/import.rs index 18fd52480..0dff48c2a 100644 --- a/src/rules/import.rs +++ b/src/rules/import.rs @@ -12,6 +12,7 @@ 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)] @@ -84,6 +85,7 @@ impl<'i> ToCss for ImportRule<'i> { dest.write_char(' ')?; self.media.to_css(dest)?; } - dest.write_str(";") + dest.write_str(";")?; + Ok(()) } } diff --git a/src/rules/keyframes.rs b/src/rules/keyframes.rs index 6a0257da6..2ec19af96 100644 --- a/src/rules/keyframes.rs +++ b/src/rules/keyframes.rs @@ -21,6 +21,7 @@ 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)] @@ -321,19 +322,25 @@ impl ToCss for KeyframeSelector { match self { KeyframeSelector::Percentage(p) => { if dest.minify && *p == Percentage(1.0) { - dest.write_str("to") + dest.write_str("to")?; + Ok(()) } else { p.to_css(dest) } } KeyframeSelector::From => { if dest.minify { - dest.write_str("0%") + dest.write_str("0%")?; + Ok(()) } else { - dest.write_str("from") + dest.write_str("from")?; + Ok(()) } } - KeyframeSelector::To => dest.write_str("to"), + KeyframeSelector::To => { + dest.write_str("to")?; + Ok(()) + } KeyframeSelector::TimelineRangePercentage(TimelineRangePercentage { name: timeline_range_name, percentage, diff --git a/src/rules/layer.rs b/src/rules/layer.rs index a4ed0b223..d20d608c7 100644 --- a/src/rules/layer.rs +++ b/src/rules/layer.rs @@ -10,6 +10,7 @@ use crate::values::string::CowArcStr; 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. @@ -107,7 +108,8 @@ impl<'i> ToCss for LayerStatementRule<'i> { dest.add_mapping(self.loc); dest.write_str("@layer ")?; self.names.to_css(dest)?; - dest.write_char(';') + dest.write_char(';')?; + Ok(()) } } @@ -161,6 +163,7 @@ impl<'a, 'i, T: ToCss> ToCss for LayerBlockRule<'i, T> { self.rules.to_css(dest)?; dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } diff --git a/src/rules/media.rs b/src/rules/media.rs index ecc065a38..5913f25d5 100644 --- a/src/rules/media.rs +++ b/src/rules/media.rs @@ -9,6 +9,7 @@ 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)] @@ -66,6 +67,7 @@ impl<'a, 'i, T: ToCss> ToCss for MediaRule<'i, T> { self.rules.to_css(dest)?; dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } diff --git a/src/rules/mod.rs b/src/rules/mod.rs index 1ab67b092..71941c633 100644 --- a/src/rules/mod.rs +++ b/src/rules/mod.rs @@ -36,6 +36,8 @@ #![deny(missing_docs)] +use std::fmt::Write; + pub mod container; pub mod counter_style; pub mod custom_media; diff --git a/src/rules/namespace.rs b/src/rules/namespace.rs index 7af26091b..bd4ff475e 100644 --- a/src/rules/namespace.rs +++ b/src/rules/namespace.rs @@ -8,6 +8,7 @@ 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)] @@ -43,6 +44,7 @@ impl<'i> ToCss for NamespaceRule<'i> { } self.url.to_css(dest)?; - dest.write_char(';') + dest.write_char(';')?; + Ok(()) } } diff --git a/src/rules/nesting.rs b/src/rules/nesting.rs index 78e15ef8a..9c824f9c8 100644 --- a/src/rules/nesting.rs +++ b/src/rules/nesting.rs @@ -1,6 +1,7 @@ //! The `@nest` rule. use smallvec::SmallVec; +use std::fmt::Write; use super::style::StyleRule; use super::Location; diff --git a/src/rules/page.rs b/src/rules/page.rs index 8da2fc78f..7f16fc8f1 100644 --- a/src/rules/page.rs +++ b/src/rules/page.rs @@ -11,6 +11,7 @@ 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. @@ -277,7 +278,8 @@ impl<'i> ToCss for PageRule<'i> { dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } diff --git a/src/rules/position_try.rs b/src/rules/position_try.rs index 34f28be99..dfa8fd2ea 100644 --- a/src/rules/position_try.rs +++ b/src/rules/position_try.rs @@ -8,6 +8,7 @@ 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)] diff --git a/src/rules/property.rs b/src/rules/property.rs index d63b20da6..49a4876b7 100644 --- a/src/rules/property.rs +++ b/src/rules/property.rs @@ -14,6 +14,7 @@ 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)] @@ -151,7 +152,8 @@ impl<'i> ToCss for PropertyRule<'i> { dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } diff --git a/src/rules/scope.rs b/src/rules/scope.rs index 6499cc22c..c93f7be4c 100644 --- a/src/rules/scope.rs +++ b/src/rules/scope.rs @@ -9,6 +9,7 @@ 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. /// @@ -102,6 +103,7 @@ impl<'i, T: ToCss> ToCss for ScopeRule<'i, T> { dest.with_cleared_context(|dest| self.rules.to_css(dest))?; dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } diff --git a/src/rules/starting_style.rs b/src/rules/starting_style.rs index b2066dc9f..4f4ab17ae 100644 --- a/src/rules/starting_style.rs +++ b/src/rules/starting_style.rs @@ -8,6 +8,7 @@ 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)] @@ -50,6 +51,7 @@ impl<'i, T: ToCss> ToCss for StartingStyleRule<'i, T> { self.rules.to_css(dest)?; dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } diff --git a/src/rules/style.rs b/src/rules/style.rs index b954bc435..120eba708 100644 --- a/src/rules/style.rs +++ b/src/rules/style.rs @@ -1,5 +1,6 @@ //! Style rules. +use std::fmt::Write; use std::hash::{Hash, Hasher}; use std::ops::Range; diff --git a/src/rules/supports.rs b/src/rules/supports.rs index 07dfe88d8..0a235cc20 100644 --- a/src/rules/supports.rs +++ b/src/rules/supports.rs @@ -1,6 +1,7 @@ //! The `@supports` rule. use std::collections::HashMap; +use std::fmt::Write; use super::Location; use super::{CssRuleList, MinifyContext}; @@ -81,7 +82,8 @@ impl<'a, 'i, T: ToCss> ToCss for SupportsRule<'i, T> { dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } @@ -413,14 +415,20 @@ impl<'i> ToCss for SupportsCondition<'i> { dest.write_char(')')?; } - dest.write_char(')') + dest.write_char(')')?; + + Ok(()) } SupportsCondition::Selector(sel) => { dest.write_str("selector(")?; dest.write_str(sel)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) + } + SupportsCondition::Unknown(unknown) => { + dest.write_str(&unknown)?; + Ok(()) } - SupportsCondition::Unknown(unknown) => dest.write_str(&unknown), } } } diff --git a/src/rules/unknown.rs b/src/rules/unknown.rs index 1377833a3..e0ec15fa3 100644 --- a/src/rules/unknown.rs +++ b/src/rules/unknown.rs @@ -8,6 +8,7 @@ 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)] @@ -52,9 +53,11 @@ impl<'i> ToCss for UnknownAtRule<'i> { block.to_css(dest, false)?; dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } else { - dest.write_char(';') + dest.write_char(';')?; + Ok(()) } } } diff --git a/src/rules/view_transition.rs b/src/rules/view_transition.rs index 0807546b2..afe4c6e13 100644 --- a/src/rules/view_transition.rs +++ b/src/rules/view_transition.rs @@ -10,6 +10,7 @@ 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)] @@ -167,7 +168,8 @@ impl<'i> ToCss for ViewTransitionRule<'i> { } dest.dedent(); dest.newline()?; - dest.write_char('}') + dest.write_char('}')?; + Ok(()) } } diff --git a/src/rules/viewport.rs b/src/rules/viewport.rs index b5867bde3..47da31179 100644 --- a/src/rules/viewport.rs +++ b/src/rules/viewport.rs @@ -8,6 +8,7 @@ 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)] diff --git a/src/selector.rs b/src/selector.rs index dc0527ed2..e98776f23 100644 --- a/src/selector.rs +++ b/src/selector.rs @@ -24,6 +24,7 @@ use rspack_lightningcss_selectors::{ use smallvec::SmallVec; use std::collections::HashSet; use std::fmt; +use std::fmt::Write; #[cfg(feature = "serde")] use crate::serialization::*; @@ -718,17 +719,20 @@ where } serialize_identifier(lang, dest)?; } - return dest.write_str(")"); + dest.write_str(")")?; + return Ok(()); } Dir { direction: dir } => { dest.write_str(":dir(")?; dir.to_css(dest)?; - return dest.write_str(")"); + dest.write_str(")")?; + return Ok(()); } State { state } => { dest.write_str(":state(")?; state.to_css(dest)?; - return dest.write_str(")"); + dest.write_str(")")?; + return Ok(()); } _ => {} } @@ -743,7 +747,8 @@ where *$prefix }; vp.to_css(dest)?; - dest.write_str($val) + dest.write_str($val)?; + Ok(()) }}; } @@ -759,7 +764,8 @@ where dest.write_char('.')?; dest.write_ident(class, true) } else { - dest.write_str($s) + dest.write_str($s)?; + Ok(()) } }}; } @@ -773,18 +779,48 @@ where FocusWithin => pseudo!(focus_within, ":focus-within"), // https://drafts.csswg.org/selectors-4/#time-pseudos - Current => dest.write_str(":current"), - Past => dest.write_str(":past"), - Future => dest.write_str(":future"), + Current => { + dest.write_str(":current")?; + Ok(()) + } + Past => { + dest.write_str(":past")?; + Ok(()) + } + Future => { + dest.write_str(":future")?; + Ok(()) + } // https://drafts.csswg.org/selectors-4/#resource-pseudos - Playing => dest.write_str(":playing"), - Paused => dest.write_str(":paused"), - Seeking => dest.write_str(":seeking"), - Buffering => dest.write_str(":buffering"), - Stalled => dest.write_str(":stalled"), - Muted => dest.write_str(":muted"), - VolumeLocked => dest.write_str(":volume-locked"), + Playing => { + dest.write_str(":playing")?; + Ok(()) + } + Paused => { + dest.write_str(":paused")?; + Ok(()) + } + Seeking => { + dest.write_str(":seeking")?; + Ok(()) + } + Buffering => { + dest.write_str(":buffering")?; + Ok(()) + } + Stalled => { + dest.write_str(":stalled")?; + Ok(()) + } + Muted => { + dest.write_str(":muted")?; + Ok(()) + } + VolumeLocked => { + dest.write_str(":volume-locked")?; + Ok(()) + } // https://fullscreen.spec.whatwg.org/#:fullscreen-pseudo-class Fullscreen(prefix) => { @@ -796,65 +832,155 @@ where }; vp.to_css(dest)?; if vp == VendorPrefix::WebKit || vp == VendorPrefix::Moz { - dest.write_str("full-screen") + dest.write_str("full-screen")?; + Ok(()) } else { - dest.write_str("fullscreen") + dest.write_str("fullscreen")?; + Ok(()) } } // https://drafts.csswg.org/selectors/#display-state-pseudos - Open => dest.write_str(":open"), - Closed => dest.write_str(":closed"), - Modal => dest.write_str(":modal"), - PictureInPicture => dest.write_str(":picture-in-picture"), + Open => { + dest.write_str(":open")?; + Ok(()) + } + Closed => { + dest.write_str(":closed")?; + Ok(()) + } + Modal => { + dest.write_str(":modal")?; + Ok(()) + } + PictureInPicture => { + dest.write_str(":picture-in-picture")?; + Ok(()) + } // https://html.spec.whatwg.org/multipage/semantics-other.html#selector-popover-open - PopoverOpen => dest.write_str(":popover-open"), + PopoverOpen => { + dest.write_str(":popover-open")?; + Ok(()) + } // https://drafts.csswg.org/selectors-4/#the-defined-pseudo - Defined => dest.write_str(":defined"), + Defined => { + dest.write_str(":defined")?; + Ok(()) + } // https://drafts.csswg.org/selectors-4/#location AnyLink(prefix) => write_prefixed!(prefix, "any-link"), - Link => dest.write_str(":link"), - LocalLink => dest.write_str(":local-link"), - Target => dest.write_str(":target"), - TargetWithin => dest.write_str(":target-within"), + Link => { + dest.write_str(":link")?; + Ok(()) + } + LocalLink => { + dest.write_str(":local-link")?; + Ok(()) + } + Target => { + dest.write_str(":target")?; + Ok(()) + } + TargetWithin => { + dest.write_str(":target-within")?; + Ok(()) + } // https://drafts.csswg.org/css-overflow-5/#active-before-after-scroll-markers - TargetCurrent => dest.write_str(":target-current"), - TargetBefore => dest.write_str(":target-before"), - TargetAfter => dest.write_str(":target-after"), + TargetCurrent => { + dest.write_str(":target-current")?; + Ok(()) + } + TargetBefore => { + dest.write_str(":target-before")?; + Ok(()) + } + TargetAfter => { + dest.write_str(":target-after")?; + Ok(()) + } - Visited => dest.write_str(":visited"), + Visited => { + dest.write_str(":visited")?; + Ok(()) + } // https://drafts.csswg.org/selectors-4/#input-pseudos - Enabled => dest.write_str(":enabled"), - Disabled => dest.write_str(":disabled"), + Enabled => { + dest.write_str(":enabled")?; + Ok(()) + } + Disabled => { + dest.write_str(":disabled")?; + Ok(()) + } ReadOnly(prefix) => write_prefixed!(prefix, "read-only"), ReadWrite(prefix) => write_prefixed!(prefix, "read-write"), PlaceholderShown(prefix) => write_prefixed!(prefix, "placeholder-shown"), - Default => dest.write_str(":default"), - Checked => dest.write_str(":checked"), - Indeterminate => dest.write_str(":indeterminate"), - Blank => dest.write_str(":blank"), - Valid => dest.write_str(":valid"), - Invalid => dest.write_str(":invalid"), - InRange => dest.write_str(":in-range"), - OutOfRange => dest.write_str(":out-of-range"), - Required => dest.write_str(":required"), - Optional => dest.write_str(":optional"), - UserValid => dest.write_str(":user-valid"), - UserInvalid => dest.write_str(":user-invalid"), + Default => { + dest.write_str(":default")?; + Ok(()) + } + Checked => { + dest.write_str(":checked")?; + Ok(()) + } + Indeterminate => { + dest.write_str(":indeterminate")?; + Ok(()) + } + Blank => { + dest.write_str(":blank")?; + Ok(()) + } + Valid => { + dest.write_str(":valid")?; + Ok(()) + } + Invalid => { + dest.write_str(":invalid")?; + Ok(()) + } + InRange => { + dest.write_str(":in-range")?; + Ok(()) + } + OutOfRange => { + dest.write_str(":out-of-range")?; + Ok(()) + } + Required => { + dest.write_str(":required")?; + Ok(()) + } + Optional => { + dest.write_str(":optional")?; + Ok(()) + } + UserValid => { + dest.write_str(":user-valid")?; + Ok(()) + } + UserInvalid => { + dest.write_str(":user-invalid")?; + Ok(()) + } // https://html.spec.whatwg.org/multipage/semantics-other.html#selector-autofill Autofill(prefix) => write_prefixed!(prefix, "autofill"), - ActiveViewTransition => dest.write_str(":active-view-transition"), + ActiveViewTransition => { + dest.write_str(":active-view-transition")?; + Ok(()) + } ActiveViewTransitionType { kind } => { dest.write_str(":active-view-transition-type(")?; kind.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Local { selector } => serialize_selector(selector, dest, context, false), @@ -880,20 +1006,23 @@ where NoButton => ":no-button", CornerPresent => ":corner-present", WindowInactive => ":window-inactive", - }) + })?; + Ok(()) } Lang { languages: _ } | Dir { direction: _ } | State { .. } => unreachable!(), Custom { name } => { dest.write_char(':')?; - return dest.write_str(&name); + dest.write_str(&name)?; + return Ok(()); } CustomFunction { name, arguments: args } => { dest.write_char(':')?; dest.write_str(name)?; dest.write_char('(')?; args.to_css_raw(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } } } @@ -1126,7 +1255,10 @@ impl<'i> ToCss for ViewTransitionPartName<'i> { W: std::fmt::Write, { match self { - ViewTransitionPartName::All => dest.write_char('*'), + ViewTransitionPartName::All => { + dest.write_char('*')?; + Ok(()) + } ViewTransitionPartName::Name(name) => name.to_css(dest), } } @@ -1224,7 +1356,8 @@ where macro_rules! write_prefixed { ($prefix: ident, $val: expr) => {{ write_prefix!($prefix); - dest.write_str($val) + dest.write_str($val)?; + Ok(()) }}; } @@ -1232,49 +1365,87 @@ where // CSS2 pseudo elements support a single colon syntax in addition // to the more correct double colon for other pseudo elements. // We use that here because it's supported everywhere and is shorter. - After => dest.write_str(":after"), - Before => dest.write_str(":before"), - FirstLine => dest.write_str(":first-line"), - FirstLetter => dest.write_str(":first-letter"), - DetailsContent => dest.write_str("::details-content"), - TargetText => dest.write_str("::target-text"), - SearchText => dest.write_str("::search-text"), + After => { + dest.write_str(":after")?; + Ok(()) + } + Before => { + dest.write_str(":before")?; + Ok(()) + } + FirstLine => { + dest.write_str(":first-line")?; + Ok(()) + } + FirstLetter => { + dest.write_str(":first-letter")?; + Ok(()) + } + DetailsContent => { + dest.write_str("::details-content")?; + Ok(()) + } + TargetText => { + dest.write_str("::target-text")?; + Ok(()) + } + SearchText => { + dest.write_str("::search-text")?; + Ok(()) + } HighlightFunction { name } => { dest.write_str("::highlight(")?; name.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) + } + Marker => { + dest.write_str("::marker")?; + Ok(()) } - Marker => dest.write_str("::marker"), Selection(prefix) => write_prefixed!(prefix, "selection"), - Cue => dest.write_str("::cue"), - CueRegion => dest.write_str("::cue-region"), + Cue => { + dest.write_str("::cue")?; + Ok(()) + } + CueRegion => { + dest.write_str("::cue-region")?; + Ok(()) + } CueFunction { selector } => { dest.write_str("::cue(")?; serialize_selector(selector, dest, context, false)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } CueRegionFunction { selector } => { dest.write_str("::cue-region(")?; serialize_selector(selector, dest, context, false)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Placeholder(prefix) => { let vp = write_prefix!(prefix); if vp == VendorPrefix::WebKit || vp == VendorPrefix::Ms { - dest.write_str("input-placeholder") + dest.write_str("input-placeholder")?; + Ok(()) } else { - dest.write_str("placeholder") + dest.write_str("placeholder")?; + Ok(()) } } Backdrop(prefix) => write_prefixed!(prefix, "backdrop"), FileSelectorButton(prefix) => { let vp = write_prefix!(prefix); if vp == VendorPrefix::WebKit { - dest.write_str("file-upload-button") + dest.write_str("file-upload-button")?; + Ok(()) } else if vp == VendorPrefix::Ms { - dest.write_str("browse") + dest.write_str("browse")?; + Ok(()) } else { - dest.write_str("file-selector-button") + dest.write_str("file-selector-button")?; + Ok(()) } } WebKitScrollbar(s) => { @@ -1287,48 +1458,71 @@ where Thumb => "::-webkit-scrollbar-thumb", Corner => "::-webkit-scrollbar-corner", Resizer => "::-webkit-resizer", - }) + })?; + Ok(()) + } + ViewTransition => { + dest.write_str("::view-transition")?; + Ok(()) } - ViewTransition => dest.write_str("::view-transition"), ViewTransitionGroup { part } => { dest.write_str("::view-transition-group(")?; part.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } ViewTransitionImagePair { part } => { dest.write_str("::view-transition-image-pair(")?; part.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } ViewTransitionOld { part } => { dest.write_str("::view-transition-old(")?; part.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } ViewTransitionNew { part } => { dest.write_str("::view-transition-new(")?; part.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } PickerFunction { identifier } => { dest.write_str("::picker(")?; identifier.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) + } + PickerIcon => { + dest.write_str("::picker-icon")?; + Ok(()) + } + Checkmark => { + dest.write_str("::checkmark")?; + Ok(()) + } + GrammarError => { + dest.write_str("::grammar-error")?; + Ok(()) + } + SpellingError => { + dest.write_str("::spelling-error")?; + Ok(()) } - PickerIcon => dest.write_str("::picker-icon"), - Checkmark => dest.write_str("::checkmark"), - GrammarError => dest.write_str("::grammar-error"), - SpellingError => dest.write_str("::spelling-error"), Custom { name: val } => { dest.write_str("::")?; - return dest.write_str(val); + dest.write_str(val)?; + return Ok(()); } CustomFunction { name, arguments: args } => { dest.write_str("::")?; dest.write_str(name)?; dest.write_char('(')?; args.to_css_raw(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } } } @@ -1429,10 +1623,16 @@ impl ToCss for Combinator { { match *self { Combinator::Child => dest.delim('>', true), - Combinator::Descendant => dest.write_str(" "), + Combinator::Descendant => { + dest.write_str(" ")?; + Ok(()) + } Combinator::NextSibling => dest.delim('+', true), Combinator::LaterSibling => dest.delim('~', true), - Combinator::Deep => dest.write_str(" /deep/ "), + Combinator::Deep => { + dest.write_str(" /deep/ ")?; + Ok(()) + } Combinator::DeepDescendant => { dest.whitespace()?; dest.write_str(">>>")?; @@ -1664,7 +1864,8 @@ where rspack_lightningcss_selectors::attr::ParsedCaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?, rspack_lightningcss_selectors::attr::ParsedCaseSensitivity::ExplicitCaseSensitive => dest.write_str(" s")?, } - dest.write_char(']') + dest.write_char(']')?; + Ok(()) } Component::Is(ref list) | Component::Where(ref list) @@ -1704,12 +1905,14 @@ where _ => unreachable!(), } serialize_selector_list(list.iter(), dest, context, false)?; - dest.write_str(")") + dest.write_str(")")?; + Ok(()) } Component::Has(ref list) => { dest.write_str(":has(")?; serialize_selector_list(list.iter(), dest, context, true)?; - dest.write_str(")") + dest.write_str(")")?; + Ok(()) } Component::NonTSPseudoClass(pseudo) => serialize_pseudo_class(pseudo, dest, context), Component::PseudoElement(pseudo) => serialize_pseudo_element(pseudo, dest, context), @@ -1734,7 +1937,8 @@ where Component::Slotted(ref selector) => { dest.write_str("::slotted(")?; selector.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } Component::NthOf(ref nth_of_data) => { let nth_data = nth_of_data.nth_data(); @@ -1742,7 +1946,8 @@ where nth_data.write_affine(dest)?; dest.write_str(" of ")?; serialize_selector_list(nth_of_data.selectors().iter(), dest, context, true)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } _ => { cssparser::ToCss::to_css(component, dest)?; @@ -1782,15 +1987,18 @@ where } else { dest.write_str(":is(")?; serialize_selector_list(ctx.selectors.0.iter(), dest, ctx.parent, false)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } } 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) { - dest.write_str(":scope") + dest.write_str(":scope")?; + Ok(()) } else { - dest.write_char('&') + dest.write_char('&')?; + Ok(()) } } } diff --git a/src/stylesheet.rs b/src/stylesheet.rs index c6d974eee..7fba986a9 100644 --- a/src/stylesheet.rs +++ b/src/stylesheet.rs @@ -20,6 +20,7 @@ use cssparser::{Parser, ParserInput, StyleSheetParser}; #[cfg(feature = "sourcemap")] use parcel_sourcemap::SourceMap; use std::collections::{HashMap, HashSet}; +use std::fmt::Write; pub use crate::parser::{ParserFlags, ParserOptions}; pub use crate::printer::PrinterOptions; @@ -293,8 +294,8 @@ where for comment in &self.license_comments { printer.write_str("/*")?; - printer.write_str_with_newlines(comment)?; - printer.write_str_with_newlines("*/\n")?; + printer.write_str(comment)?; + printer.write_str("*/\n")?; } if let Some(config) = &self.options.css_modules { diff --git a/src/values/calc.rs b/src/values/calc.rs index c3f4242d6..e80a7cac0 100644 --- a/src/values/calc.rs +++ b/src/values/calc.rs @@ -10,6 +10,7 @@ use crate::traits::{IsCompatible, Parse, Sign, ToCss, TryMap, TryOp, TrySign}; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; +use std::fmt::Write; use super::angle::Angle; use super::length::Length; @@ -131,7 +132,8 @@ impl + TrySign + Clone + std::fmt::Deb MathFunction::Calc(calc) => { dest.write_str("calc(")?; calc.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } MathFunction::Min(args) => { dest.write_str("min(")?; @@ -144,7 +146,8 @@ impl + TrySign + Clone + std::fmt::Deb } arg.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } MathFunction::Max(args) => { dest.write_str("max(")?; @@ -157,7 +160,8 @@ impl + TrySign + Clone + std::fmt::Deb } arg.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } MathFunction::Clamp(a, b, c) => { // If clamp() is unsupported by targets, output min()/max() @@ -179,7 +183,8 @@ impl + TrySign + Clone + std::fmt::Deb b.to_css(dest)?; dest.delim(',', false)?; c.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } MathFunction::Round(strategy, a, b) => { dest.write_str("round(")?; @@ -190,31 +195,36 @@ impl + TrySign + Clone + std::fmt::Deb a.to_css(dest)?; dest.delim(',', false)?; b.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } MathFunction::Rem(a, b) => { dest.write_str("rem(")?; a.to_css(dest)?; dest.delim(',', false)?; b.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } MathFunction::Mod(a, b) => { dest.write_str("mod(")?; a.to_css(dest)?; dest.delim(',', false)?; b.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } MathFunction::Abs(v) => { dest.write_str("abs(")?; v.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } MathFunction::Sign(v) => { dest.write_str("sign(")?; v.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } MathFunction::Hypot(args) => { dest.write_str("hypot(")?; @@ -227,7 +237,8 @@ impl + TrySign + Clone + std::fmt::Deb } arg.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } } } diff --git a/src/values/color.rs b/src/values/color.rs index c082135d7..3e442a357 100644 --- a/src/values/color.rs +++ b/src/values/color.rs @@ -636,12 +636,16 @@ impl ToCss for CssColor { W: std::fmt::Write, { match self { - CssColor::CurrentColor => dest.write_str("currentColor"), + CssColor::CurrentColor => { + dest.write_str("currentColor")?; + Ok(()) + } CssColor::RGBA(color) => { if color.alpha == 255 { let hex: u32 = ((color.red as u32) << 16) | ((color.green as u32) << 8) | (color.blue as u32); if let Some(name) = short_color_name(hex) { - return dest.write_str(name); + dest.write_str(name)?; + return Ok(()); } let compact = compact_hex(hex); @@ -656,7 +660,8 @@ impl ToCss for CssColor { // If the browser doesn't support `#rrggbbaa` color syntax, it is converted to `transparent` when compressed(minify = true). // https://www.w3.org/TR/css-color-4/#transparent-black if dest.minify && color.red == 0 && color.green == 0 && color.blue == 0 && color.alpha == 0 { - return dest.write_str("transparent"); + dest.write_str("transparent")?; + return Ok(()); } else { dest.write_str("rgba(")?; write!(dest, "{}", color.red)?; @@ -714,14 +719,16 @@ impl ToCss for CssColor { dest.write_str("var(--lightningcss-dark")?; dest.delim(',', false)?; dark.to_css(dest)?; - return dest.write_char(')'); + dest.write_char(')')?; + return Ok(()); } dest.write_str("light-dark(")?; light.to_css(dest)?; dest.delim(',', false)?; dark.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } CssColor::System(system) => system.to_css(dest), } @@ -1567,7 +1574,9 @@ where write_component(alpha, dest)?; } - dest.write_char(')') + dest.write_char(')')?; + + Ok(()) } #[inline] @@ -1616,7 +1625,9 @@ where write_component(alpha, dest)?; } - dest.write_char(')') + dest.write_char(')')?; + + Ok(()) } bitflags! { diff --git a/src/values/easing.rs b/src/values/easing.rs index 2bd49f208..f389c044c 100644 --- a/src/values/easing.rs +++ b/src/values/easing.rs @@ -115,12 +115,12 @@ impl ToCss for EasingFunction { W: std::fmt::Write, { match self { - EasingFunction::Linear => dest.write_str("linear"), - EasingFunction::Ease => dest.write_str("ease"), - EasingFunction::EaseIn => dest.write_str("ease-in"), - EasingFunction::EaseOut => dest.write_str("ease-out"), - EasingFunction::EaseInOut => dest.write_str("ease-in-out"), - _ if self.is_ease() => dest.write_str("ease"), + EasingFunction::Linear => dest.write_str("linear")?, + EasingFunction::Ease => dest.write_str("ease")?, + EasingFunction::EaseIn => dest.write_str("ease-in")?, + EasingFunction::EaseOut => dest.write_str("ease-out")?, + EasingFunction::EaseInOut => dest.write_str("ease-in-out")?, + _ if self.is_ease() => dest.write_str("ease")?, x if *x == EasingFunction::CubicBezier { x1: 0.42, @@ -129,7 +129,7 @@ impl ToCss for EasingFunction { y2: 1.0, } => { - dest.write_str("ease-in") + dest.write_str("ease-in")?; } x if *x == EasingFunction::CubicBezier { @@ -139,7 +139,7 @@ impl ToCss for EasingFunction { y2: 1.0, } => { - dest.write_str("ease-out") + dest.write_str("ease-out")?; } x if *x == EasingFunction::CubicBezier { @@ -149,7 +149,7 @@ impl ToCss for EasingFunction { y2: 1.0, } => { - dest.write_str("ease-in-out") + dest.write_str("ease-in-out")?; } EasingFunction::CubicBezier { x1, y1, x2, y2 } => { dest.write_str("cubic-bezier(")?; @@ -160,24 +160,25 @@ impl ToCss for EasingFunction { x2.to_css(dest)?; dest.delim(',', false)?; y2.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; } EasingFunction::Steps { count: 1, position: StepPosition::Start, - } => dest.write_str("step-start"), + } => dest.write_str("step-start")?, EasingFunction::Steps { count: 1, position: StepPosition::End, - } => dest.write_str("step-end"), + } => dest.write_str("step-end")?, EasingFunction::Steps { count, position } => { dest.write_str("steps(")?; write!(dest, "{}", count)?; dest.delim(',', false)?; position.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; } - } + }; + Ok(()) } } diff --git a/src/values/gradient.rs b/src/values/gradient.rs index fc1d16a5b..6fe3a1c7c 100644 --- a/src/values/gradient.rs +++ b/src/values/gradient.rs @@ -20,6 +20,7 @@ use crate::vendor_prefix::VendorPrefix; use crate::visitor::Visit; use cssparser::*; use std::f32::consts::PI; +use std::fmt::Write; #[cfg(feature = "serde")] use crate::serialization::ValueWrapper; @@ -221,7 +222,9 @@ impl ToCss for Gradient { Gradient::WebKitGradient(g) => g.to_css(dest)?, } - dest.write_char(')') + dest.write_char(')')?; + + Ok(()) } } @@ -507,8 +510,14 @@ impl LineDirection { LineDirection::Horizontal(k) => { if dest.minify { match k { - HorizontalPositionKeyword::Left => dest.write_str("270deg"), - HorizontalPositionKeyword::Right => dest.write_str("90deg"), + HorizontalPositionKeyword::Left => { + dest.write_str("270deg")?; + Ok(()) + } + HorizontalPositionKeyword::Right => { + dest.write_str("90deg")?; + Ok(()) + } } } else { if !is_prefixed { @@ -520,8 +529,14 @@ impl LineDirection { LineDirection::Vertical(k) => { if dest.minify { match k { - VerticalPositionKeyword::Top => dest.write_str("0deg"), - VerticalPositionKeyword::Bottom => dest.write_str("180deg"), + VerticalPositionKeyword::Top => { + dest.write_str("0deg")?; + Ok(()) + } + VerticalPositionKeyword::Bottom => { + dest.write_str("180deg")?; + Ok(()) + } } } else { if !is_prefixed { @@ -1272,7 +1287,8 @@ impl ToCss for WebKitColorStop { dest.delim(',', false)?; self.color.to_css(dest)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } } @@ -1360,14 +1376,17 @@ impl> ToCss for WebKitGradientPointCom match &self { Center => { if dest.minify { - dest.write_str("50%") + dest.write_str("50%")?; + Ok(()) } else { - dest.write_str("center") + dest.write_str("center")?; + Ok(()) } } Number(lp) => { if matches!(lp, NumberOrPercentage::Percentage(Percentage(p)) if *p == 0.0) { - dest.write_char('0') + dest.write_char('0')?; + Ok(()) } else { lp.to_css(dest) } diff --git a/src/values/ident.rs b/src/values/ident.rs index 32c17efe2..273d962bb 100644 --- a/src/values/ident.rs +++ b/src/values/ident.rs @@ -10,6 +10,7 @@ use crate::visitor::Visit; use cssparser::*; use smallvec::SmallVec; use std::borrow::Borrow; +use std::fmt::Write; use std::ops::Deref; use super::string::impl_string_type; @@ -121,7 +122,10 @@ impl<'i> ToCss for NoneOrCustomIdentList<'i> { W: std::fmt::Write, { match self { - NoneOrCustomIdentList::None => dest.write_str("none"), + NoneOrCustomIdentList::None => { + dest.write_str("none")?; + Ok(()) + } NoneOrCustomIdentList::Idents(types) => { let mut first = true; for ident in types { diff --git a/src/values/image.rs b/src/values/image.rs index 808833f93..b8445d44a 100644 --- a/src/values/image.rs +++ b/src/values/image.rs @@ -17,6 +17,7 @@ use crate::vendor_prefix::VendorPrefix; use crate::visitor::Visit; use cssparser::*; use smallvec::SmallVec; +use std::fmt::Write; /// A CSS [``](https://www.w3.org/TR/css-images-3/#image-values) value. #[derive(Debug, Clone, PartialEq, Parse, ToCss)] @@ -383,7 +384,8 @@ impl<'i> ToCss for ImageSet<'i> { } option.to_css(dest, self.vendor_prefix != VendorPrefix::None)?; } - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } } diff --git a/src/values/length.rs b/src/values/length.rs index 6708ec50c..4ce00a2ad 100644 --- a/src/values/length.rs +++ b/src/values/length.rs @@ -16,6 +16,7 @@ use crate::traits::{IsCompatible, TrySign}; use crate::visitor::Visit; use const_str; use cssparser::*; +use std::fmt::Write; /// A CSS [``](https://www.w3.org/TR/css-values-4/#typedef-length-percentage) value. /// May be specified as either a length or a percentage that resolves to an length. @@ -491,7 +492,8 @@ impl ToCss for LengthValue { // The unit can be omitted if the value is zero, except inside calc() // expressions, where unitless numbers won't be parsed as dimensions. if !dest.in_calc && value == 0.0 { - return dest.write_char('0'); + dest.write_char('0')?; + return Ok(()); } serialize_dimension(value, unit, dest) @@ -528,12 +530,15 @@ where if value < 0.0 { if let Some(stripped) = s.strip_prefix("-0") { dest.write_char('-')?; - dest.write_str(stripped) + dest.write_str(stripped)?; + Ok(()) } else { - dest.write_str(&s) + dest.write_str(&s)?; + Ok(()) } } else { - dest.write_str(s.trim_start_matches('0')) + dest.write_str(s.trim_start_matches('0'))?; + Ok(()) } } else { token.to_css(dest)?; diff --git a/src/values/number.rs b/src/values/number.rs index 6d03f120f..3b85e6969 100644 --- a/src/values/number.rs +++ b/src/values/number.rs @@ -9,6 +9,7 @@ use crate::traits::{IsCompatible, Map, Op, Parse, ParseNumeric, Sign, ToCss, Try #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; +use std::fmt::Write; /// Describes what values are allowed when parsing a numeric value. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -130,9 +131,11 @@ impl ToCss for CSSNumber { cssparser::ToCss::to_css(self, &mut s)?; if number < 0.0 { dest.write_char('-')?; - dest.write_str(s.trim_start_matches("-").trim_start_matches("0")) + dest.write_str(s.trim_start_matches("-").trim_start_matches("0"))?; + Ok(()) } else { - dest.write_str(s.trim_start_matches('0')) + dest.write_str(s.trim_start_matches('0'))?; + Ok(()) } } else { cssparser::ToCss::to_css(self, dest)?; diff --git a/src/values/percentage.rs b/src/values/percentage.rs index d9b90bb43..8c98e8ead 100644 --- a/src/values/percentage.rs +++ b/src/values/percentage.rs @@ -12,6 +12,7 @@ use crate::traits::{ #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; +use std::fmt::Write; /// A CSS [``](https://www.w3.org/TR/css-values-4/#percentages) value. /// @@ -66,9 +67,11 @@ impl ToCss for Percentage { percent.to_css(&mut s)?; if self.0 < 0.0 { dest.write_char('-')?; - dest.write_str(s.trim_start_matches("-0")) + dest.write_str(s.trim_start_matches("-0"))?; + Ok(()) } else { - dest.write_str(s.trim_start_matches('0')) + dest.write_str(s.trim_start_matches('0'))?; + Ok(()) } } else { percent.to_css(dest)?; diff --git a/src/values/position.rs b/src/values/position.rs index 91e428cd5..924caa9e9 100644 --- a/src/values/position.rs +++ b/src/values/position.rs @@ -10,6 +10,7 @@ use crate::traits::{IsCompatible, Parse, ToCss, Zero}; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; +use std::fmt::Write; #[cfg(feature = "serde")] use crate::serialization::ValueWrapper; @@ -185,7 +186,8 @@ impl ToCss for Position { { // If there is a side keyword with an offset, "center" must be a keyword not a percentage. x_pos.to_css(dest)?; - dest.write_str(" center") + dest.write_str(" center")?; + Ok(()) } (&HorizontalPosition::Length(ref x_lp), y_pos @ &VerticalPosition::Side { side, offset: Some(_) }) if side != VerticalPositionKeyword::Top => @@ -368,9 +370,11 @@ impl ToCss for PositionComponent { match &self { Center => { if dest.minify { - dest.write_str("50%") + dest.write_str("50%")?; + Ok(()) } else { - dest.write_str("center") + dest.write_str("center")?; + Ok(()) } } Length(lp) => lp.to_css(dest), diff --git a/src/values/rect.rs b/src/values/rect.rs index 9df2738b0..41b4645ef 100644 --- a/src/values/rect.rs +++ b/src/values/rect.rs @@ -6,6 +6,7 @@ use crate::traits::{IsCompatible, Parse, ToCss}; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; +use std::fmt::Write; /// A generic value that represents a value for four sides of a box, /// e.g. border-width, margin, padding, etc. diff --git a/src/values/shape.rs b/src/values/shape.rs index afa235306..1f379b0b0 100644 --- a/src/values/shape.rs +++ b/src/values/shape.rs @@ -12,6 +12,7 @@ use crate::values::number::NonNegative; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; +use std::fmt::Write; /// A CSS [``](https://www.w3.org/TR/css-shapes-1/#basic-shape-functions) value. #[derive(Debug, Clone, PartialEq)] @@ -243,22 +244,26 @@ impl ToCss for BasicShape { BasicShape::Inset(rect) => { dest.write_str("inset(")?; rect.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } BasicShape::Circle(circle) => { dest.write_str("circle(")?; circle.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } BasicShape::Ellipse(ellipse) => { dest.write_str("ellipse(")?; ellipse.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } BasicShape::Polygon(poly) => { dest.write_str("polygon(")?; poly.to_css(dest)?; - dest.write_char(')') + dest.write_char(')')?; + Ok(()) } } } diff --git a/src/values/size.rs b/src/values/size.rs index e6a1ad1c6..e0dfd99c1 100644 --- a/src/values/size.rs +++ b/src/values/size.rs @@ -6,6 +6,7 @@ use crate::traits::{IsCompatible, Parse, ToCss}; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; +use std::fmt::Write; /// A generic value that represents a value with two components, e.g. a border radius. /// diff --git a/src/values/syntax.rs b/src/values/syntax.rs index e0b6d5613..70511f779 100644 --- a/src/values/syntax.rs +++ b/src/values/syntax.rs @@ -11,6 +11,7 @@ use crate::values; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; +use std::fmt::Write; /// A CSS [syntax string](https://drafts.css-houdini.org/css-properties-values-api/#syntax-strings) /// used to define the grammar for a registered custom property. @@ -417,7 +418,9 @@ impl ToCss for SyntaxString { } } - dest.write_char('"') + dest.write_char('"')?; + + Ok(()) } } @@ -429,8 +432,14 @@ impl ToCss for SyntaxComponent { self.kind.to_css(dest)?; match self.multiplier { Multiplier::None => Ok(()), - Multiplier::Comma => dest.write_char('#'), - Multiplier::Space => dest.write_char('+'), + Multiplier::Comma => { + dest.write_char('#')?; + Ok(()) + } + Multiplier::Space => { + dest.write_char('+')?; + Ok(()) + } } } } @@ -459,7 +468,8 @@ impl ToCss for SyntaxComponentKind { CustomIdent => "", Literal(l) => l, }; - dest.write_str(s) + dest.write_str(s)?; + Ok(()) } } diff --git a/src/values/time.rs b/src/values/time.rs index 01bdacc62..b7ff5fcee 100644 --- a/src/values/time.rs +++ b/src/values/time.rs @@ -10,6 +10,7 @@ use crate::traits::{impl_op, Map, Op, Parse, ParseNumeric, Sign, ToCss, Zero}; #[cfg(feature = "visitor")] use crate::visitor::Visit; use cssparser::*; +use std::fmt::Write; /// A CSS [`