oak_css/ast/mod.rs
1#![doc = include_str!("readme.md")]
2use core::range::Range;
3use oak_core::tree::{GreenNode, RedNode, TypedNode};
4
5/// CSS selector variant.
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7#[derive(Clone, Debug, PartialEq, Eq, Hash)]
8pub enum Selector {
9 /// Element selector (e.g., `div`).
10 Element(String),
11 /// Class selector (e.g., `.class`).
12 Class(String),
13 /// ID selector (e.g., `#id`).
14 Id(String),
15 /// Attribute selector (e.g., `[attr]`).
16 Attribute {
17 /// The attribute name.
18 name: String,
19 /// Optional attribute value.
20 value: Option<String>,
21 /// Optional attribute operator.
22 operator: Option<String>,
23 },
24 /// Pseudo-class selector (e.g., `:hover`).
25 PseudoClass(String),
26 /// Pseudo-element selector (e.g., `::before`).
27 PseudoElement(String),
28 /// Descendant selector (e.g., `div p`).
29 Descendant(Box<Selector>, Box<Selector>),
30 /// Child selector (e.g., `div > p`).
31 Child(Box<Selector>, Box<Selector>),
32 /// Adjacent sibling selector (e.g., `div + p`).
33 AdjacentSibling(Box<Selector>, Box<Selector>),
34 /// General sibling selector (e.g., `div ~ p`).
35 GeneralSibling(Box<Selector>, Box<Selector>),
36}
37
38/// CSS value variant.
39#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
40#[derive(Clone, Debug, PartialEq)]
41pub enum Value {
42 /// Keyword value (e.g., `none`, `auto`).
43 Keyword(String),
44 /// Numeric value with unit (e.g., `10px`, `50%`).
45 Numeric {
46 /// The numeric value.
47 value: f64,
48 /// Optional unit.
49 unit: Option<String>,
50 },
51 /// Color value (e.g., `#fff`, `rgb(255, 255, 255)`).
52 Color(String),
53 /// String value (e.g., `"text"`).
54 String(String),
55 /// URL value (e.g., `url("image.png")`).
56 Url(String),
57 /// Function value (e.g., `calc(100% - 20px)`).
58 Function {
59 /// The function name.
60 name: String,
61 /// The function arguments.
62 arguments: Vec<Value>,
63 },
64 /// List of values (e.g., `1px 2px 3px`).
65 List(Vec<Value>),
66 /// Nested value (for complex expressions).
67 Nested(Box<Value>),
68}
69
70/// CSS declaration consisting of a property name, value, and source span.
71#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
72#[derive(Clone, Debug, PartialEq)]
73pub struct Declaration {
74 /// The property name (e.g., `color`).
75 pub property: String,
76 /// The property value.
77 pub value: Value,
78 /// The range in the source code where this declaration is defined.
79 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
80 pub span: Range<usize>,
81}
82
83/// CSS rule set consisting of selectors and declarations.
84#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
85#[derive(Clone, Debug, PartialEq)]
86pub struct RuleSet {
87 /// The selectors for this rule set.
88 pub selectors: Vec<Selector>,
89 /// The declarations for this rule set.
90 pub declarations: Vec<Declaration>,
91 /// The range in the source code where this rule set is defined.
92 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
93 pub span: Range<usize>,
94}
95
96/// CSS at-rule variant.
97#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
98#[derive(Clone, Debug, PartialEq)]
99pub enum AtRule {
100 /// Media query rule (e.g., `@media screen and (max-width: 600px)`).
101 Media {
102 /// The media query condition.
103 condition: String,
104 /// The rule sets inside the media query.
105 rules: Vec<RuleSet>,
106 /// The range in the source code where this media rule is defined.
107 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
108 span: Range<usize>,
109 },
110 /// Import rule (e.g., `@import "style.css"`).
111 Import {
112 /// The import path.
113 path: String,
114 /// Optional media query.
115 media: Option<String>,
116 /// The range in the source code where this import rule is defined.
117 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
118 span: Range<usize>,
119 },
120 /// Font face rule (e.g., `@font-face`).
121 FontFace {
122 /// The font face declarations.
123 declarations: Vec<Declaration>,
124 /// The range in the source code where this font face rule is defined.
125 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
126 span: Range<usize>,
127 },
128 /// Keyframes rule (e.g., `@keyframes animation`).
129 Keyframes {
130 /// The animation name.
131 name: String,
132 /// The keyframe rules.
133 keyframes: Vec<(String, Vec<Declaration>)>,
134 /// The range in the source code where this keyframes rule is defined.
135 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
136 span: Range<usize>,
137 },
138 /// Other at-rules.
139 Other {
140 /// The at-rule name.
141 name: String,
142 /// The at-rule content.
143 content: String,
144 /// The range in the source code where this at-rule is defined.
145 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
146 span: Range<usize>,
147 },
148}
149
150/// CSS AST node variant.
151#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
152#[derive(Clone, Debug, PartialEq)]
153pub enum CssNode {
154 /// A rule set.
155 RuleSet(RuleSet),
156 /// An at-rule.
157 AtRule(AtRule),
158 /// A comment.
159 Comment(String),
160}
161
162/// Root node of the CSS AST.
163#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
164#[derive(Clone, Debug, PartialEq)]
165pub struct CssRoot {
166 /// The top-level nodes in the CSS document.
167 pub nodes: Vec<CssNode>,
168}
169
170impl<'a> TypedNode<'a> for CssRoot {
171 type Language = crate::CssLanguage;
172
173 fn cast(_node: RedNode<'a, Self::Language>) -> Option<Self> {
174 // 这里需要根据实际情况实现从 RedNode 到 CssRoot 的转换
175 // 暂时返回一个空的 CssRoot
176 Some(Self { nodes: Vec::new() })
177 }
178
179 fn green(&self) -> &'a GreenNode<'a, Self::Language> {
180 // 这里需要返回底层的 GreenNode
181 // 暂时返回一个空的 GreenNode 引用
182 // 注意:这是一个临时实现,需要根据实际情况修复
183 panic!("CssRoot::green() not implemented")
184 }
185}