Skip to main content

oak_tailwind/ast/
mod.rs

1#![doc = include_str!("readme.md")]
2//! Abstract Syntax Tree for Tailwind DSL.
3use core::range::Range;
4#[cfg(feature = "serde")]
5#[allow(unused_imports)]
6use serde::{Deserialize, Serialize};
7
8/// The root node of a Tailwind document.
9#[derive(Debug, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct TailwindRoot {
12    /// The span of the entire root.
13    #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
14    pub span: Range<usize>,
15    /// The children of the root.
16    pub children: Vec<TailwindNode>,
17}
18
19/// A node in the Tailwind AST.
20#[derive(Debug, Clone, PartialEq, Eq)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22pub enum TailwindNode {
23    /// A CSS directive (e.g., @tailwind base).
24    Directive(TailwindDirective),
25    /// A utility class (e.g., bg-red-500).
26    Class(TailwindClass),
27    /// A comment.
28    Comment(TailwindComment),
29}
30
31/// A Tailwind class (e.g., hover:bg-red-500, !p-4).
32#[derive(Debug, Clone, PartialEq, Eq)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34pub struct TailwindClass {
35    /// The span of the entire class.
36    #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
37    pub span: Range<usize>,
38    /// Whether the class has an important flag (!).
39    pub is_important: bool,
40    /// The modifiers applied to the class.
41    pub modifiers: Vec<TailwindModifier>,
42    /// The kind of class (utility or arbitrary value).
43    pub kind: TailwindClassKind,
44}
45
46/// The kind of Tailwind class.
47#[derive(Debug, Clone, PartialEq, Eq)]
48#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
49pub enum TailwindClassKind {
50    /// A utility class (e.g., `bg-red-500`).
51    Utility(TailwindUtility),
52    /// An arbitrary value (e.g., `[100px]`).
53    ArbitraryValue(TailwindArbitraryValue),
54}
55
56/// A Tailwind modifier (e.g., hover:).
57#[derive(Debug, Clone, PartialEq, Eq)]
58#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
59pub struct TailwindModifier {
60    /// The span of the modifier.
61    #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
62    pub span: Range<usize>,
63    /// The name of the modifier.
64    pub name: String,
65}
66
67/// A Tailwind utility (e.g., bg-red-500).
68#[derive(Debug, Clone, PartialEq, Eq)]
69#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
70pub struct TailwindUtility {
71    /// The span of the utility.
72    #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
73    pub span: Range<usize>,
74    /// The name of the utility.
75    pub name: String,
76}
77
78/// A Tailwind arbitrary value (e.g., [100px]).
79#[derive(Debug, Clone, PartialEq, Eq)]
80#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
81pub struct TailwindArbitraryValue {
82    /// The span of the arbitrary value.
83    #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
84    pub span: Range<usize>,
85    /// The value inside the brackets.
86    pub value: String,
87}
88
89/// A Tailwind directive (e.g., @tailwind base).
90#[derive(Debug, Clone, PartialEq, Eq)]
91#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
92pub struct TailwindDirective {
93    /// The span of the directive.
94    #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
95    pub span: Range<usize>,
96    /// The name of the directive (e.g., "tailwind").
97    pub name: String,
98    /// The optional body of the directive (e.g., "base").
99    pub body: Option<String>,
100}
101
102/// A Tailwind comment.
103#[derive(Debug, Clone, PartialEq, Eq)]
104#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
105pub struct TailwindComment {
106    /// The span of the comment.
107    #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
108    pub span: Range<usize>,
109    /// The content of the comment.
110    pub content: String,
111}
112
113impl TailwindRoot {
114    /// Creates a new Tailwind root node with the given span.
115    pub fn new(span: Range<usize>, children: Vec<TailwindNode>) -> Self {
116        Self { span, children }
117    }
118}