Support formatted Vue Pug template tags

This commit is contained in:
cuishuang 2026-09-10 09:54:21 +08:00
parent 41d9cae8e5
commit 2995898db7

View file

@ -5,7 +5,10 @@ use regex::Regex;
use std::sync;
static TEMPLATE_REGEX: sync::LazyLock<Regex> = sync::LazyLock::new(|| {
Regex::new(r#"<template lang=['"]([^"']*)['"]>([\s\S]*)<\/template>"#).unwrap()
Regex::new(
r#"<template\s+(?:[^>]*\s+)?lang\s*=\s*(?:"([^"]*)"|'([^']*)')[^>]*>([\s\S]*)<\/template>"#,
)
.unwrap()
});
#[derive(Debug, Default)]
@ -17,10 +20,16 @@ impl PreProcessor for Vue {
// Only process template tags if content is valid UTF-8
if let Ok(content_as_str) = std::str::from_utf8(content) {
for (_, [lang, body]) in TEMPLATE_REGEX
.captures_iter(content_as_str)
.map(|c| c.extract())
{
for captures in TEMPLATE_REGEX.captures_iter(content_as_str) {
let lang = captures
.get(1)
.or_else(|| captures.get(2))
.expect("template lang capture should exist")
.as_str();
let body = captures
.get(3)
.expect("template body capture should exist")
.as_str();
let replaced = pre_process_input(body.as_bytes().to_vec(), lang);
result = result.replace(body, replaced);
}
@ -46,6 +55,38 @@ mod tests {
Vue::test_extract_contains(input, vec!["bg-neutral-900", "text-red-500"]);
}
#[test]
fn test_vue_template_pug_with_attributes_and_whitespace() {
for input in [
r#"
<template data-test="true" lang="pug">
.bg-neutral-900.text-red-500 This is a test.
</template>
"#,
r#"
<template
lang = 'pug'
data-test="true"
>
.bg-neutral-900.text-red-500 This is a test.
</template>
"#,
] {
Vue::test_extract_contains(input, vec!["bg-neutral-900", "text-red-500"]);
}
}
#[test]
fn test_vue_template_does_not_treat_data_lang_as_lang() {
let input = r#"
<template data-lang="pug">
.bg-neutral-900.text-red-500 This is a test.
</template>
"#;
Vue::test(input, input);
}
#[test]
fn test_invalid_utf8_does_not_panic() {
// Invalid UTF-8 sequence: 0x80 is a continuation byte without a leading byte