css_parse/syntax/
declaration_group.rs

1use crate::{
2	CursorSink, DeclarationOrBad, DeclarationValue, NodeMetadata, NodeWithMetadata, SemanticEq, Span, ToCursors, ToSpan,
3};
4use bumpalo::collections::Vec;
5
6/// A group of declarations that can be interleaved with rules.
7///
8/// Per [CSS Syntax ยง 5.4.4](https://drafts.csswg.org/css-syntax-3/#consume-block-contents),
9/// blocks return a list containing either rules or lists of declarations. This allows
10/// declarations to be properly interleaved with nested rules while maintaining their order.
11///
12/// For example, in `a { color: red; b { } color: blue; }`, the declarations need to be
13/// grouped separately before and after the nested `b` rule.
14#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(transparent))]
16pub struct DeclarationGroup<'a, D, M>
17where
18	D: DeclarationValue<'a, M>,
19	M: NodeMetadata,
20{
21	pub declarations: Vec<'a, DeclarationOrBad<'a, D, M>>,
22}
23
24impl<'a, D, M> ToCursors for DeclarationGroup<'a, D, M>
25where
26	D: DeclarationValue<'a, M> + ToCursors,
27	M: NodeMetadata,
28{
29	fn to_cursors(&self, s: &mut impl CursorSink) {
30		for decl in &self.declarations {
31			decl.to_cursors(s);
32		}
33	}
34}
35
36impl<'a, D, M> ToSpan for DeclarationGroup<'a, D, M>
37where
38	D: DeclarationValue<'a, M> + ToSpan,
39	M: NodeMetadata,
40{
41	fn to_span(&self) -> Span {
42		self.declarations.to_span()
43	}
44}
45
46impl<'a, D, M> SemanticEq for DeclarationGroup<'a, D, M>
47where
48	D: DeclarationValue<'a, M>,
49	M: NodeMetadata,
50{
51	fn semantic_eq(&self, other: &Self) -> bool {
52		self.declarations.semantic_eq(&other.declarations)
53	}
54}
55
56impl<'a, D, M> NodeWithMetadata<M> for DeclarationGroup<'a, D, M>
57where
58	D: DeclarationValue<'a, M>,
59	M: NodeMetadata,
60{
61	fn metadata(&self) -> M {
62		let mut meta = M::default();
63		for decl in &self.declarations {
64			meta = meta.merge(decl.metadata());
65		}
66		meta
67	}
68}