Skip to main content

css_ast/rules/
import.rs

1use super::prelude::*;
2use crate::{LayerName, MediaQueryList, SupportsCondition, UrlOrString};
3
4/// <https://drafts.csswg.org/css-cascade-5/#at-ruledef-import>
5///
6/// ```text
7/// @import [ <url> | <string> ]
8///  [ layer | layer(<layer-name>) ]?
9///  <import-conditions> ;
10///
11/// <import-conditions>  = [ supports( [ <supports-condition> | <declaration> ] ) ]?
12///                      <media-query-list>?
13/// ```
14#[node]
15#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
17#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
18#[derive(csskit_derives::NodeWithMetadata)]
19pub struct ImportRule<'a> {
20	#[cfg_attr(feature = "visitable", visit(skip))]
21	#[atom(CssAtomSet::Import)]
22	pub name: T![AtKeyword],
23	pub url: UrlOrString,
24	pub layer: Option<ImportLayer<'a>>,
25	pub supports_condition: Option<ImportSupportsFunction<'a>>,
26	pub media_condition: Option<MediaQueryList<'a>>,
27	#[cfg_attr(feature = "visitable", visit(skip))]
28	#[semantic_eq(skip)]
29	pub semicolon: Option<T![;]>,
30}
31
32#[node]
33#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
34#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
35#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit(self))]
36#[derive(csskit_derives::NodeWithMetadata)]
37pub enum ImportLayer<'a> {
38	#[atom(CssAtomSet::Layer)]
39	#[cfg_attr(feature = "visitable", visit(skip))]
40	Layer(T![Ident]),
41	#[atom(CssAtomSet::Layer)]
42	LayerFunction(ImportLayerFunction<'a>),
43}
44
45#[node]
46#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
48#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
49#[derive(csskit_derives::NodeWithMetadata)]
50pub struct ImportLayerFunction<'a> {
51	#[atom(CssAtomSet::Layer)]
52	#[cfg_attr(feature = "visitable", visit(skip))]
53	pub name: T![Function],
54	pub layer: LayerName<'a>,
55	#[cfg_attr(feature = "visitable", visit(skip))]
56	#[semantic_eq(skip)]
57	pub close: T![')'],
58}
59
60#[node]
61#[derive(Parse, Peek, ToCursors, ToSpan, SemanticEq, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
62#[cfg_attr(feature = "serde", derive(serde::Serialize), serde())]
63#[cfg_attr(feature = "visitable", derive(csskit_derives::Visitable), visit)]
64#[derive(csskit_derives::NodeWithMetadata)]
65pub struct ImportSupportsFunction<'a> {
66	#[atom(CssAtomSet::Supports)]
67	#[cfg_attr(feature = "visitable", visit(skip))]
68	pub name: T![Function],
69	pub condition: SupportsCondition<'a>,
70	#[cfg_attr(feature = "visitable", visit(skip))]
71	#[semantic_eq(skip)]
72	pub close: T![')'],
73}
74
75#[cfg(test)]
76mod tests {
77	use super::*;
78	use css_parse::assert_parse;
79
80	#[test]
81	fn test_writes() {
82		assert_parse!(CssAtomSet::ATOMS, ImportRule, "@import \"foo.css\";");
83		assert_parse!(CssAtomSet::ATOMS, ImportRule, "@import url(\"foo.css\");");
84		assert_parse!(CssAtomSet::ATOMS, ImportRule, "@import url(\"foo.css\") print;");
85		assert_parse!(CssAtomSet::ATOMS, ImportRule, "@import url('foo.css') projection, tv;");
86		assert_parse!(CssAtomSet::ATOMS, ImportRule, "@import url('foo.css') handheld and (max-width: 400px);");
87		assert_parse!(CssAtomSet::ATOMS, ImportRule, "@import url('foo.css') supports(not (display: flex));");
88		assert_parse!(
89			CssAtomSet::ATOMS,
90			ImportRule,
91			"@import url('foo.css') layer supports(not (display: flex)) media, print;"
92		);
93		assert_parse!(
94			CssAtomSet::ATOMS,
95			ImportRule,
96			"@import url('foo.css') layer(main) supports(not (display: flex)) media, print;"
97		);
98	}
99}