css_variable_lsp/
types.rs1use serde::{Deserialize, Serialize};
2use tower_lsp::lsp_types::{Position, Range, Url};
3
4use crate::runtime_config::RuntimeConfig;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct CssVariable {
9 pub name: String,
11
12 pub value: String,
14
15 pub uri: Url,
17
18 pub range: Range,
20
21 pub name_range: Option<Range>,
23
24 pub value_range: Option<Range>,
26
27 pub selector: String,
29
30 pub important: bool,
32
33 pub inline: bool,
35
36 pub source_position: usize,
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct CssVariableUsage {
43 pub name: String,
45
46 pub uri: Url,
48
49 pub range: Range,
51
52 pub name_range: Option<Range>,
54
55 pub usage_context: String,
57
58 pub dom_node: Option<DOMNodeInfo>,
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct DOMNodeInfo {
65 pub tag: String,
67
68 pub id: Option<String>,
70
71 pub classes: Vec<String>,
73
74 pub position: usize,
76
77 pub node_index: Option<usize>,
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct Config {
84 pub lookup_files: Vec<String>,
86
87 pub ignore_globs: Vec<String>,
89
90 pub enable_color_provider: bool,
92
93 pub color_only_on_variables: bool,
95}
96
97impl Default for Config {
98 fn default() -> Self {
99 Self {
100 lookup_files: vec![
101 "**/*.css".to_string(),
102 "**/*.scss".to_string(),
103 "**/*.sass".to_string(),
104 "**/*.less".to_string(),
105 "**/*.html".to_string(),
106 "**/*.vue".to_string(),
107 "**/*.svelte".to_string(),
108 "**/*.astro".to_string(),
109 "**/*.ripple".to_string(),
110 ],
111 ignore_globs: vec![
112 "**/node_modules/**".to_string(),
113 "**/dist/**".to_string(),
114 "**/out/**".to_string(),
115 "**/.git/**".to_string(),
116 ],
117 enable_color_provider: true,
118 color_only_on_variables: false,
119 }
120 }
121}
122
123impl Config {
124 pub fn from_runtime(runtime: &RuntimeConfig) -> Self {
125 let mut config = Config::default();
126 if let Some(lookup) = &runtime.lookup_files {
127 if !lookup.is_empty() {
128 config.lookup_files = lookup.clone();
129 }
130 }
131 if let Some(ignore) = &runtime.ignore_globs {
132 if !ignore.is_empty() {
133 config.ignore_globs = ignore.clone();
134 }
135 }
136 config.enable_color_provider = runtime.enable_color_provider;
137 config.color_only_on_variables = runtime.color_only_on_variables;
138 config
139 }
140}
141
142pub fn offset_to_position(text: &str, offset: usize) -> Position {
144 let mut line = 0;
145 let mut character = 0;
146
147 for (idx, ch) in text.char_indices() {
148 if idx >= offset {
149 break;
150 }
151 if ch == '\n' {
152 line += 1;
153 character = 0;
154 } else {
155 character += ch.len_utf16() as u32;
156 }
157 }
158
159 Position::new(line, character)
160}
161
162pub fn position_to_offset(text: &str, position: Position) -> Option<usize> {
164 let mut line = 0;
165 let mut character = 0;
166
167 for (idx, ch) in text.char_indices() {
168 if line == position.line && character == position.character {
169 return Some(idx);
170 }
171 if ch == '\n' {
172 line += 1;
173 character = 0;
174 } else {
175 character += ch.len_utf16() as u32;
176 }
177 }
178
179 if line == position.line && character == position.character {
180 Some(text.len())
181 } else {
182 None
183 }
184}