pub mod regexes;
use minify_selectors_utils::*;
use onig::*;
use crate::markup::html_attributes::*;
use crate::style::regexes as style_regex;
pub fn analyse_css(
file_string: &mut str,
selectors: &mut Selectors,
config: &Config,
) {
analyse_css_selectors(file_string, selectors);
analyse_css_attributes(file_string, selectors, config);
analyse_css_functions(file_string, selectors);
super::analyse_prefixed_selectors(file_string, selectors);
}
pub fn rewrite_css(
file_string: &mut String,
selectors: &Selectors,
config: &Config,
) {
rewrite_css_selectors(file_string, selectors);
rewrite_css_attributes(file_string, selectors, config);
rewrite_css_functions(file_string, selectors);
super::rewrite_prefixed_selectors(file_string, selectors);
}
pub fn analyse_css_selectors(
file_string: &mut str,
selectors: &mut Selectors,
) {
for capture in style_regex::CSS_SELECTORS.captures_iter(file_string) {
if capture.at(2).is_some() {
super::add_selector_to_map(
&format!(
"{prefix}{identifier}",
prefix = &capture.at(1).unwrap(),
identifier = &unescape_css_chars(capture.at(2).unwrap()),
),
selectors,
Some(SelectorUsage::Style),
);
}
}
}
pub fn rewrite_css_selectors(
file_string: &mut String,
selectors: &Selectors,
) {
*file_string = style_regex::CSS_SELECTORS.replace_all(file_string, |capture: &Captures| {
if capture.at(2).is_some() {
return format!(
"{prefix}{identifier}",
prefix = &capture.at(1).unwrap(),
identifier = super::get_encoded_selector(
&unescape_css_chars(capture.at(0).unwrap()),
selectors,
)
.unwrap_or_else(|| capture.at(0).unwrap().to_string()),
);
}
capture.at(0).unwrap().to_owned()
});
}
pub fn analyse_css_attributes(
file_string: &mut str,
selectors: &mut Selectors,
config: &Config,
) {
for capture in style_regex::CSS_ATTRIBUTES.captures_iter(file_string) {
if capture.at(2).is_none() {
continue;
}
let attribute_name: String = unescape_css_chars(capture.at(1).unwrap());
let attribute_flag: &str = capture.at(6).unwrap_or("");
let mut attribute_value: String = capture.at(4).unwrap().to_string();
if !WHITELIST.contains_key(&attribute_name) {
continue;
}
if attribute_flag.to_lowercase().contains('i') {
continue;
}
let attribute_type_designation: &str = WHITELIST.get(&attribute_name).unwrap();
match attribute_type_designation {
"id" | "class" => {
super::analyse_string_of_tokens(
&mut attribute_value,
selectors,
attribute_type_designation,
Some(SelectorUsage::Style),
);
},
"selector" => {
attribute_value = unescape_css_chars(&attribute_value);
analyse_css(&mut attribute_value, selectors, config);
},
"anchor" => {
attribute_value = unescape_css_chars(&attribute_value);
super::analyse_anchor_links(&mut attribute_value, selectors);
},
_ => {},
}
}
}
pub fn rewrite_css_attributes(
file_string: &mut String,
selectors: &Selectors,
config: &Config,
) {
*file_string = style_regex::CSS_ATTRIBUTES.replace_all(file_string, |capture: &Captures| {
if capture.at(2).is_none() {
return capture.at(0).unwrap().to_owned();
}
let attribute_name: String = unescape_css_chars(capture.at(1).unwrap());
let attribute_quote_type: &str = capture.at(3).unwrap_or("");
let attribute_flag: &str = capture.at(6).unwrap_or("");
let mut attribute_value: String = capture.at(4).unwrap().to_string();
if !WHITELIST.contains_key(&attribute_name) {
return capture.at(0).unwrap().to_string();
}
if attribute_flag.to_lowercase().contains('i') {
return capture.at(0).unwrap().to_string();
}
let attribute_type_designation: &str = WHITELIST.get(&attribute_name).unwrap();
match attribute_type_designation {
"id" | "class" => {
super::rewrite_string_of_tokens(
&mut attribute_value,
selectors,
attribute_type_designation,
);
},
"selector" => {
attribute_value = unescape_css_chars(&attribute_value);
rewrite_css(&mut attribute_value, selectors, config);
},
"anchor" => {
attribute_value = unescape_css_chars(&attribute_value);
super::rewrite_anchor_links(&mut attribute_value, selectors);
},
_ => {},
}
format!(
"[{attribute}{operator}{quote}{value}{quote}{space}{flag}]",
attribute = capture.at(1).unwrap(),
operator = capture.at(2).unwrap(),
quote = attribute_quote_type,
value = attribute_value,
space = capture.at(5).unwrap(),
flag = attribute_flag,
)
});
}
pub fn analyse_css_functions(
file_string: &mut str,
selectors: &mut Selectors,
) {
for capture in style_regex::CSS_FUNCTIONS.captures_iter(file_string) {
if capture.at(4).is_none() {
continue;
}
let mut function_argument = capture.at(4).unwrap().to_string();
super::analyse_anchor_links(&mut function_argument, selectors);
}
}
pub fn rewrite_css_functions(
file_string: &mut String,
selectors: &Selectors,
) {
*file_string = style_regex::CSS_FUNCTIONS.replace_all(file_string, |capture: &Captures| {
if capture.at(4).is_none() {
return capture.at(0).unwrap().to_owned();
}
let function_name: &str = capture.at(1).unwrap();
let mut function_argument = capture.at(4).unwrap().to_string();
super::rewrite_anchor_links(&mut function_argument, selectors);
format!(
"{function}{join}{quote}{argument}",
function = function_name,
join = capture.at(2).unwrap(),
quote = capture.at(3).unwrap(),
argument = function_argument,
)
});
}
pub fn unescape_css_chars(selector_string: &str) -> String {
let mut unescaped = selector_string.to_string();
if style_regex::ESCAPED_CSS_CHARS
.find(selector_string)
.is_none()
{
return unescaped;
}
unescaped = style_regex::ESCAPED_CSS_CHARS.replace_all(&unescaped, |capture: &Captures| {
String::from(
if capture.at(1).is_some() {
char::from_u32(
u32::from_str_radix(
capture
.at(1)
.unwrap()
.strip_prefix('\\')
.unwrap()
.trim_end_matches(' '),
16,
)
.unwrap(),
)
.unwrap()
} else if capture.at(2).is_some() {
capture.at(2).unwrap().chars().nth(1).unwrap()
} else {
panic!("Not any of the known capture groups");
},
)
});
unescaped
}