use std::sync::LazyLock;
use regex::Regex;
static NON_PATH_SCHEME: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(&format!(
r"^(?i)[{}]*(?:data|javascript|vbscript):",
super::js::JS_SPACE_CLASS
))
.expect("a constant pattern compiles")
});
pub(crate) fn is_excluded_scheme(value: &str) -> bool {
NON_PATH_SCHEME.is_match(value)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_three_schemes_are_excluded() {
assert!(is_excluded_scheme("data:image/png;base64,AAA"));
assert!(is_excluded_scheme("javascript:void(0)"));
assert!(is_excluded_scheme("vbscript:msgbox"));
}
#[test]
fn case_and_leading_whitespace_do_not_evade_it() {
assert!(is_excluded_scheme("JavaScript:void(0)"));
assert!(is_excluded_scheme(" vbscript:x"));
assert!(is_excluded_scheme("\t\nDATA:x"));
}
#[test]
fn real_paths_and_real_schemes_pass() {
assert!(!is_excluded_scheme("./a/b.png"));
assert!(!is_excluded_scheme("https://example.com"));
assert!(!is_excluded_scheme("file:///a"));
assert!(!is_excluded_scheme("metadata:not-a-scheme"));
}
#[test]
fn a_byte_order_mark_does_not_evade_it() {
assert!(is_excluded_scheme("\u{feff}javascript:void(0)"));
}
}