1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use super::{
CallArgs, Callable, Name, SassString, Selectors, SrcRange, Value,
VariableDeclaration,
};
use crate::input::SourcePos;
use std::collections::BTreeSet;
/// Every sass file is a sequence of sass items.
/// Scoping items contains further sequences of items.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd)]
pub enum Item {
/// An `@import` directive.
Import(Vec<SassString>, Value, SourcePos),
/// A variable declaration.
VariableDeclaration(VariableDeclaration),
/// An `@at-root` directive.
AtRoot(Selectors, Vec<Item>),
/// An `@media` directive.
AtMedia {
/// Any arguments
args: Value,
/// The directive may have a body.
body: Option<Vec<Item>>,
/// The source location of this at rule.
pos: SourcePos,
},
/// A generic `@` directive.
AtRule {
/// The name of this directive
name: SassString,
/// Any arguments
args: Value,
/// The directive may have a body.
body: Option<Vec<Item>>,
/// The source location of this at rule.
pos: SourcePos,
},
/// An `@debug` directive.
Debug(Value),
/// An `@warn` directive.
Warn(Value),
/// An `@error` directive.
Error(Value, SourcePos),
/// A `@mixin` directive, declaring a mixin.
MixinDeclaration(String, Callable),
/// An `@include` directive, calling a mixin.
MixinCall(String, CallArgs, Option<Callable>, SourcePos),
/// An `@content` directive (in a mixin declaration).
Content(CallArgs, SourcePos),
/// An `@function` declaration.
FunctionDeclaration(String, Callable),
/// An `@return` statement in a function declaration.
Return(Value, SourcePos),
/// An `@if` conditional directive.
IfStatement(Value, Vec<Item>, Vec<Item>),
/// An `@each` loop directive.
///
/// The value may be or evaluate to a list.
Each(Vec<Name>, Value, Vec<Item>),
/// An `@for` loop directive.
For(Name, SrcRange, Vec<Item>),
/// An `@while` loop directive.
While(Value, Vec<Item>),
/// An `@use` directive.
Use(SassString, UseAs, Vec<(Name, Value, bool)>, SourcePos),
/// An `@forward` directive.
Forward(
SassString,
UseAs,
Expose,
Vec<(Name, Value, bool)>,
SourcePos,
),
/// Extend rule (not really supported yet).
Extend(Selectors),
/// A sass rule; selectors followed by a block of items.
Rule(Selectors, Vec<Item>),
/// A sass namespace rule; a name followed by a block of properties.
NamespaceRule(SassString, Value, Vec<Item>),
/// A sass property; a name and a value.
/// The position is the full value.
Property(SassString, Value, SourcePos),
/// A custom property.
CustomProperty(SassString, SassString),
/// A comment (that might be preserved for the output).
Comment(SassString),
/// Nothing
None,
}
impl From<VariableDeclaration> for Item {
fn from(value: VariableDeclaration) -> Self {
Self::VariableDeclaration(value)
}
}
/// How an `@forward`-ed module should be exposed.
///
/// As directed by the `show` or `hide` keywords or their absense.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd)]
pub enum Expose {
/// No `show` or `hide` specified; expose everything.
All,
/// Only show the listed items.
///
/// The first list is functions and mixins, the second is variables.
Show(BTreeSet<Name>, BTreeSet<Name>),
/// Hide the listed items, show everything else.
///
/// The first list is functions and mixins, the second is variables.
Hide(BTreeSet<Name>, BTreeSet<Name>),
}
impl Expose {
/// Check if `name` should be exposed as a function/mixin.
pub fn allow_fun(&self, name: &Name) -> bool {
match self {
Self::All => true,
Self::Show(show, _) => show.contains(name),
Self::Hide(hide, _) => !hide.contains(name),
}
}
/// Check if `name` should be exposed as a variable.
pub fn allow_var(&self, name: &Name) -> bool {
match self {
Self::All => true,
Self::Show(_, show) => show.contains(name),
Self::Hide(_, hide) => !hide.contains(name),
}
}
}
/// The `as` part of an `@use` or `@forward` directive.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd)]
pub enum UseAs {
/// A plain `@use foo;`.
KeepName,
/// Include the module contents directly in the scope, `@use foo as *;`.
Star,
/// An explicit name, `@use foo as bar`.
Name(String),
/// A prefix, `@forward foo as foo-*`.
Prefix(String),
}