html_languageservice/language_facts/
data_manager.rs1use std::fmt::Debug;
2
3use lazy_static::lazy_static;
4use serde_json::{json, Value};
5
6use super::{
7 data_provider::{HTMLDataProvider, IHTMLDataProvider},
8 web_custom_data::HTML_DATA_INSTANCE,
9};
10
11pub struct HTMLDataManager {
15 data_providers: Vec<Box<dyn IHTMLDataProvider>>,
16 case_sensitive: bool,
17}
18
19impl HTMLDataManager {
20 pub(crate) fn new(
21 use_default_data_provider: bool,
22 custom_data_providers: Option<Vec<Box<dyn IHTMLDataProvider>>>,
23 case_sensitive: bool,
24 ) -> HTMLDataManager {
25 let mut data_manager = HTMLDataManager {
26 data_providers: vec![],
27 case_sensitive,
28 };
29 data_manager.set_data_providers(
30 use_default_data_provider,
31 custom_data_providers.unwrap_or(vec![]),
32 );
33 data_manager
34 }
35
36 pub fn set_data_providers(
38 &mut self,
39 built_in: bool,
40 mut providers: Vec<Box<dyn IHTMLDataProvider>>,
41 ) {
42 self.data_providers.clear();
43 if built_in {
44 self.data_providers.push(Box::new(HTMLDataProvider::new(
45 "html5".to_string(),
46 HTML_DATA_INSTANCE.clone(),
47 self.case_sensitive,
48 )));
49 }
50 self.data_providers.append(&mut providers);
51 }
52
53 pub fn get_data_providers(&self) -> &Vec<Box<dyn IHTMLDataProvider>> {
54 &self.data_providers
55 }
56
57 pub fn is_void_element(&self, tag: &str, void_elements: &Vec<String>) -> bool {
61 void_elements.contains(&tag.to_string())
62 }
63
64 pub fn get_void_elements(&self, language_id: &str) -> Vec<String> {
66 let mut void_tags: Vec<String> = vec![];
67 for provider in &self.data_providers {
68 if provider.is_applicable(language_id) {
69 provider
70 .provide_tags()
71 .iter()
72 .filter(|tag| tag.void.is_some_and(|v| v))
73 .for_each(|tag| void_tags.push(tag.name.clone()))
74 }
75 }
76 void_tags.sort();
77 void_tags
78 }
79
80 pub fn is_path_attribute(&self, tag: &str, attr: &str) -> bool {
82 if ["src", "href"].contains(&attr) {
83 return true;
84 }
85 let value = PATH_TAG_AND_ATTR.as_object().unwrap().get(tag);
86 if let Some(value) = value {
87 if value.is_array() {
88 value
89 .as_array()
90 .unwrap()
91 .contains(&Value::String(attr.to_string()))
92 } else {
93 value.as_str().unwrap() == attr
94 }
95 } else {
96 false
97 }
98 }
99}
100
101impl Default for HTMLDataManager {
102 fn default() -> Self {
103 HTMLDataManager::new(true, None, false)
104 }
105}
106
107impl Debug for HTMLDataManager {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 f.debug_struct("HTMLDataManager")
110 .field("data_providers(len)", &self.data_providers.len())
111 .field("case_sensitive", &self.case_sensitive)
112 .finish()
113 }
114}
115
116lazy_static! {
117 static ref PATH_TAG_AND_ATTR: Value = json!({
118 "a": "href",
120 "area": "href",
121 "body": "background",
122 "blockquote": "cite",
123 "del": "cite",
124 "form": "action",
125 "frame": ["src", "longdesc"],
126 "img": ["src", "longdesc"],
127 "ins": "cite",
128 "link": "href",
129 "object": "data",
130 "q": "cite",
131 "script": "src",
132 "audio": "src",
134 "button": "formaction",
135 "command": "icon",
136 "embed": "src",
137 "html": "manifest",
138 "input": ["src", "formaction"],
139 "source": "src",
140 "track": "src",
141 "video": ["src", "poster"]
142 });
143}