lightningcss/rules/
nesting.rs

1//! The `@nest` rule.
2
3use smallvec::SmallVec;
4
5use super::style::StyleRule;
6use super::Location;
7use super::MinifyContext;
8use crate::context::DeclarationContext;
9use crate::declaration::DeclarationBlock;
10use crate::error::{MinifyError, PrinterError};
11use crate::parser::DefaultAtRule;
12use crate::printer::Printer;
13use crate::targets::should_compile;
14use crate::traits::ToCss;
15#[cfg(feature = "visitor")]
16use crate::visitor::Visit;
17
18/// A [@nest](https://www.w3.org/TR/css-nesting-1/#at-nest) rule.
19#[derive(Debug, PartialEq, Clone)]
20#[cfg_attr(feature = "visitor", derive(Visit))]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22#[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))]
23#[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))]
24pub struct NestingRule<'i, R = DefaultAtRule> {
25  /// The style rule that defines the selector and declarations for the `@nest` rule.
26  #[cfg_attr(feature = "serde", serde(borrow))]
27  pub style: StyleRule<'i, R>,
28  /// The location of the rule in the source file.
29  #[cfg_attr(feature = "visitor", skip_visit)]
30  pub loc: Location,
31}
32
33impl<'i, T: Clone> NestingRule<'i, T> {
34  pub(crate) fn minify(
35    &mut self,
36    context: &mut MinifyContext<'_, 'i>,
37    parent_is_unused: bool,
38  ) -> Result<bool, MinifyError> {
39    self.style.minify(context, parent_is_unused)
40  }
41}
42
43impl<'a, 'i, T: ToCss> ToCss for NestingRule<'i, T> {
44  fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
45  where
46    W: std::fmt::Write,
47  {
48    #[cfg(feature = "sourcemap")]
49    dest.add_mapping(self.loc);
50    if dest.context().is_none() {
51      dest.write_str("@nest ")?;
52    }
53    self.style.to_css(dest)
54  }
55}
56
57/// A [nested declarations](https://drafts.csswg.org/css-nesting/#nested-declarations-rule) rule.
58#[derive(Debug, PartialEq, Clone)]
59#[cfg_attr(feature = "visitor", derive(Visit))]
60#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
61#[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))]
62#[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))]
63pub struct NestedDeclarationsRule<'i> {
64  /// The style rule that defines the selector and declarations for the `@nest` rule.
65  #[cfg_attr(feature = "serde", serde(borrow))]
66  pub declarations: DeclarationBlock<'i>,
67  /// The location of the rule in the source file.
68  #[cfg_attr(feature = "visitor", skip_visit)]
69  pub loc: Location,
70}
71
72impl<'i> NestedDeclarationsRule<'i> {
73  pub(crate) fn minify(&mut self, context: &mut MinifyContext<'_, 'i>, parent_is_unused: bool) -> bool {
74    if parent_is_unused {
75      return true;
76    }
77
78    context.handler_context.context = DeclarationContext::StyleRule;
79    self
80      .declarations
81      .minify(context.handler, context.important_handler, &mut context.handler_context);
82    context.handler_context.context = DeclarationContext::None;
83    return false;
84  }
85}
86
87impl<'i> ToCss for NestedDeclarationsRule<'i> {
88  fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
89  where
90    W: std::fmt::Write,
91  {
92    #[cfg(feature = "sourcemap")]
93    dest.add_mapping(self.loc);
94
95    if should_compile!(dest.targets.current, Nesting) {
96      if let Some(context) = dest.context() {
97        let has_printable_declarations = self.declarations.has_printable_declarations();
98        if has_printable_declarations {
99          dest.with_parent_context(|dest| context.selectors.to_css(dest))?;
100          dest.whitespace()?;
101          dest.write_char('{')?;
102          dest.indent();
103          dest.newline()?;
104        }
105
106        self
107          .declarations
108          .to_css_declarations(dest, false, &context.selectors, self.loc.source_index)?;
109
110        if has_printable_declarations {
111          dest.dedent();
112          dest.newline()?;
113          dest.write_char('}')?;
114        }
115        return Ok(());
116      }
117    }
118
119    self
120      .declarations
121      .to_css_declarations(dest, false, &parcel_selectors::SelectorList(SmallVec::new()), 0)
122  }
123}