use std::sync::LazyLock;
use regex::Regex;
static QUOTED_MULTILINE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r#"(?s)"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|`(?:\\.|[^`\\])*`"#)
.expect("a constant pattern compiles")
});
static QUOTED: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(
r#""(?:\\[^\r\n]|[^"\\\r\n])*"|'(?:\\[^\r\n]|[^'\\\r\n])*'|`(?:\\[^\r\n]|[^`\\\r\n])*`"#,
)
.expect("a constant pattern compiles")
});
#[cfg(test)]
pub(crate) fn extract(text: &str) -> Vec<String> {
extract_with(text, false)
}
pub(crate) fn runs(text: &str, multiline: bool) -> Vec<&str> {
let pattern = if multiline {
&*QUOTED_MULTILINE
} else {
&*QUOTED
};
pattern
.find_iter(text)
.map(|found| {
let matched = found.as_str();
&matched[1..matched.len() - 1]
})
.collect()
}
pub(crate) fn extract_with(text: &str, multiline: bool) -> Vec<String> {
runs(text, multiline)
.into_iter()
.map(super::text::trim)
.filter(|value| !value.is_empty())
.map(str::to_string)
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn all_three_quote_styles_are_read() {
assert_eq!(
extract("a = \"double\"; b = 'single'; c = `backtick`;"),
["double", "single", "backtick"]
);
}
#[test]
fn the_quotes_themselves_are_not_part_of_the_value() {
assert_eq!(extract("'hello'"), ["hello"]);
}
#[test]
fn empty_and_whitespace_only_runs_are_dropped() {
assert_eq!(extract("a=''; b=' '; c='kept'"), ["kept"]);
}
#[test]
fn an_escaped_quote_does_not_end_the_run_and_is_not_resolved() {
assert_eq!(extract(r"'It\'s fine'"), [r"It\'s fine"]);
assert_eq!(extract(r#""say \"hi\"""#), [r#"say \"hi\""#]);
}
#[test]
fn unquoted_text_yields_nothing() {
assert!(extract("just some words with no quotes").is_empty());
}
#[test]
fn a_run_cannot_span_lines_by_default() {
assert!(extract("`first\nsecond`").is_empty());
}
#[test]
fn a_run_may_span_lines_on_request() {
assert_eq!(extract_with("`first\nsecond`", true), ["first\nsecond"]);
assert_eq!(
extract_with("const body = `Dear reader,\n\nWelcome.`;", true),
["Dear reader,\n\nWelcome."]
);
}
#[test]
fn the_multiline_pattern_agrees_on_single_line_runs() {
let source = "a = \"one\"; b = 'two'; c = `three`;";
assert_eq!(extract(source), extract_with(source, true));
}
#[test]
fn quotes_of_another_style_inside_a_run_are_kept() {
assert_eq!(extract(r#""it's here""#), ["it's here"]);
}
#[test]
fn a_quoted_run_inside_a_comment_is_still_a_run() {
assert_eq!(extract("// see \"the docs\""), ["the docs"]);
}
}