html_languageservice/
html_language_types.rs1use std::{
2 path::{Component, PathBuf},
3 str::FromStr,
4};
5
6use lsp_types::{ClientCapabilities, Uri};
7
8#[derive(Default)]
9pub struct HTMLLanguageServiceOptions {
10 pub file_system_provider: Option<Box<dyn FileSystemProvider>>,
13
14 pub client_capabilities: Option<ClientCapabilities>,
16
17 pub case_sensitive: Option<bool>,
19}
20
21pub trait FileSystemProvider: Send + Sync {
22 fn stat(&self, uri: DocumentUri) -> FileStat;
23
24 fn read_directory(&self, uri: DocumentUri) -> (String, FileType);
25}
26
27pub type DocumentUri = String;
28
29pub struct FileStat {
30 pub file_type: FileType,
33 pub ctime: i128,
35 pub mtime: i128,
37 pub size: usize,
39}
40
41pub enum FileType {
42 Unknown = 0,
44 File = 1,
46 Directory = 2,
48 SymbolicLink = 64,
50}
51
52pub trait DocumentContext {
53 fn resolve_reference(&self, reference: &str, base: &str) -> Option<String>;
54}
55
56pub struct DefaultDocumentContext;
57
58impl DocumentContext for DefaultDocumentContext {
59 fn resolve_reference(&self, reference: &str, base: &str) -> Option<String> {
60 if let Ok(uri) = Uri::from_str(reference) {
61 let base_uri = Uri::from_str(base).unwrap();
62 if uri.scheme().is_some() {
63 return Some(uri.to_string());
64 }
65
66 let scheme = base_uri.scheme().unwrap();
67 let auth = if let Some(auth) = uri.authority() {
68 auth.to_string()
69 } else if let Some(auth) = base_uri.authority() {
70 auth.to_string()
71 } else {
72 "".to_string()
73 };
74
75 let mut base_uri_path = PathBuf::from_str(&base_uri.path().to_string()).unwrap();
76 if !base.ends_with("/") {
77 base_uri_path.pop();
78 }
79 let uri_path = PathBuf::from_str(&uri.path().to_string()).unwrap();
80 let path = base_uri_path.join(uri_path);
81 let suffix = if reference.ends_with("/") || reference.ends_with(".") {
82 "/"
83 } else {
84 ""
85 };
86 let mut new_path = vec![];
87 let mut components = path.components();
88 let mut base_uri_components = base_uri_path.components();
89 let base_prefix = {
90 match base_uri_components.next() {
91 Some(Component::Prefix(preifx)) => Some(Component::Prefix(preifx)),
92 Some(Component::RootDir) => {
93 if let Some(Component::Normal(v)) = base_uri_components.next() {
94 if v.to_string_lossy().contains(":") {
95 Some(Component::Normal(v))
96 } else {
97 None
98 }
99 } else {
100 None
101 }
102 }
103 _ => None,
104 }
105 };
106 match components.next() {
108 Some(Component::Prefix(prefix)) => new_path.push(Component::Prefix(prefix)),
109 Some(Component::RootDir) => {
110 let add_prefx = if let Some(Component::Normal(v)) = components.clone().next() {
111 !v.to_string_lossy().contains(":")
112 } else {
113 true
114 };
115 if add_prefx && base_prefix.is_some() {
116 if let Some(Component::Prefix(prefix)) = base_prefix {
117 new_path.push(Component::Prefix(prefix));
118 new_path.push(Component::RootDir);
119 } else if let Some(Component::Normal(prefix)) = base_prefix {
120 new_path.push(Component::RootDir);
121 new_path.push(Component::Normal(prefix));
122 }
123 } else {
124 new_path.push(Component::RootDir);
125 }
126 }
127 Some(Component::Normal(v)) => {
128 if let Some(Component::Prefix(prefix)) = base_prefix {
129 new_path.push(Component::Prefix(prefix));
130 new_path.push(Component::RootDir);
131 } else if let Some(Component::Normal(prefix)) = base_prefix {
132 new_path.push(Component::RootDir);
133 new_path.push(Component::Normal(prefix));
134 } else {
135 new_path.push(Component::RootDir);
136 }
137 new_path.push(Component::Normal(v));
138 }
139 _ => {}
140 }
141 for component in components {
143 match component {
144 Component::Prefix(prefix) => new_path.push(Component::Prefix(prefix)),
145 Component::RootDir => new_path.push(Component::RootDir),
146 Component::CurDir => {}
147 Component::ParentDir => {
148 new_path.pop();
149 }
150 Component::Normal(v) => new_path.push(Component::Normal(v)),
151 }
152 }
153 let new_path = new_path.iter().collect::<PathBuf>();
154 let new_path = new_path.to_string_lossy();
155
156 Some(format!("{}://{}{}{}", scheme, auth, new_path, suffix))
157 } else {
158 None
159 }
160 }
161}