lightningcss/rules/
scope.rs1use super::Location;
4use super::{CssRuleList, MinifyContext};
5use crate::error::{MinifyError, PrinterError};
6use crate::parser::DefaultAtRule;
7use crate::printer::Printer;
8use crate::selector::{is_pure_css_modules_selector, SelectorList};
9use crate::traits::ToCss;
10#[cfg(feature = "visitor")]
11use crate::visitor::Visit;
12
13#[derive(Debug, PartialEq, Clone)]
19#[cfg_attr(feature = "visitor", derive(Visit))]
20#[cfg_attr(
21 feature = "serde",
22 derive(serde::Serialize, serde::Deserialize),
23 serde(rename_all = "camelCase")
24)]
25#[cfg_attr(feature = "jsonschema", derive(schemars::JsonSchema))]
26#[cfg_attr(feature = "into_owned", derive(static_self::IntoOwned))]
27pub struct ScopeRule<'i, R = DefaultAtRule> {
28 pub scope_start: Option<SelectorList<'i>>,
30 pub scope_end: Option<SelectorList<'i>>,
32 #[cfg_attr(feature = "serde", serde(borrow))]
34 pub rules: CssRuleList<'i, R>,
35 #[cfg_attr(feature = "visitor", skip_visit)]
37 pub loc: Location,
38}
39
40impl<'i, T: Clone> ScopeRule<'i, T> {
41 pub(crate) fn minify(&mut self, context: &mut MinifyContext<'_, 'i>) -> Result<(), MinifyError> {
42 if context.pure_css_modules {
43 if let Some(scope_start) = &self.scope_start {
44 if !scope_start.0.iter().all(is_pure_css_modules_selector) {
45 return Err(MinifyError {
46 kind: crate::error::MinifyErrorKind::ImpureCSSModuleSelector,
47 loc: self.loc,
48 });
49 }
50 }
51
52 if let Some(scope_end) = &self.scope_end {
53 if !scope_end.0.iter().all(is_pure_css_modules_selector) {
54 return Err(MinifyError {
55 kind: crate::error::MinifyErrorKind::ImpureCSSModuleSelector,
56 loc: self.loc,
57 });
58 }
59 }
60 }
61
62 self.rules.minify(context, false)
63 }
64}
65
66impl<'i, T: ToCss> ToCss for ScopeRule<'i, T> {
67 fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
68 where
69 W: std::fmt::Write,
70 {
71 #[cfg(feature = "sourcemap")]
72 dest.add_mapping(self.loc);
73 dest.write_str("@scope")?;
74 dest.whitespace()?;
75 if let Some(scope_start) = &self.scope_start {
76 dest.write_char('(')?;
77 scope_start.to_css(dest)?;
78 dest.write_char(')')?;
79 dest.whitespace()?;
80 }
81 if let Some(scope_end) = &self.scope_end {
82 if dest.minify {
83 dest.write_char(' ')?;
84 }
85 dest.write_str("to (")?;
86 if let Some(scope_start) = &self.scope_start {
89 dest.with_context(scope_start, |dest| scope_end.to_css(dest))?;
90 } else {
91 scope_end.to_css(dest)?;
92 }
93 dest.write_char(')')?;
94 dest.whitespace()?;
95 }
96 dest.write_char('{')?;
97 dest.indent();
98 dest.newline()?;
99 dest.with_cleared_context(|dest| self.rules.to_css(dest))?;
103 dest.dedent();
104 dest.newline()?;
105 dest.write_char('}')
106 }
107}