use url::Url;
pub(super) fn cross_scheme_to_file(from: &str, to: &str) -> bool {
let to_is_file = Url::parse(to)
.map(|u| u.scheme().eq_ignore_ascii_case("file"))
.unwrap_or(false);
if !to_is_file {
return false;
}
Url::parse(from)
.map(|u| !u.scheme().eq_ignore_ascii_case("file"))
.unwrap_or(true)
}
pub(super) fn subresource_allowed(page_url: Option<&Url>, resource: &str) -> bool {
let Ok(target) = Url::parse(resource) else { return false };
let scheme = target.scheme().to_ascii_lowercase();
match scheme.as_str() {
"http" | "https" => true,
"file" => page_url
.map(|u| u.scheme().eq_ignore_ascii_case("file"))
.unwrap_or(false),
_ => false,
}
}
pub(super) fn escape_for_js_template_literal(input: &str) -> String {
let mut out = String::with_capacity(input.len());
for ch in input.chars() {
match ch {
'\\' => out.push_str("\\\\"),
'`' => out.push_str("\\`"),
'$' => out.push_str("\\$"),
'\u{2028}' => out.push_str("\\u2028"),
'\u{2029}' => out.push_str("\\u2029"),
'\u{0000}' => out.push_str("\\0"),
'\r' => out.push_str("\\r"),
c if (c as u32) < 0x20 => {
out.push_str(&format!("\\u{:04x}", c as u32));
}
c => out.push(c),
}
}
out
}