From ac313ee0bd96a06e895d738b2aac8ba0a234c35f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Sun, 7 Jun 2026 18:30:52 +0200 Subject: [PATCH] fix: don't double backslash escapes in non-CSS embedded templates --- src/generation/generate.rs | 19 +++++++++++++++++-- tests/specs/external_formatter/html.txt | 7 +++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/generation/generate.rs b/src/generation/generate.rs index 7fb3a332..c50196d5 100644 --- a/src/generation/generate.rs +++ b/src/generation/generate.rs @@ -3064,8 +3064,23 @@ fn maybe_gen_tagged_tpl_with_external_formatter<'a>(node: &TaggedTpl<'a>, contex .unwrap(); // Then formats the text with the external formatter. - let formatted_tpl = match external_formatter(embedded_lang, text.replace(r"\\", "\\"), context.config) { - Ok(formatted_tpl) => formatted_tpl?.replace("\\", r"\\"), + // + // Only CSS needs the `\\` -> `\` round-trip, so the CSS parser sees escapes + // like Tailwind's `\\[\\#86efac\\]` as `\[\#86efac\]`. For other embedded + // languages the raw text must be passed through verbatim; unescaping there + // doubles lone escape sequences such as `\n` or `` \` `` (see + // denoland/deno#30103 and #30948). + let needs_unescape = embedded_lang == "css"; + let input = if needs_unescape { text.replace(r"\\", "\\") } else { text }; + let formatted_tpl = match external_formatter(embedded_lang, input, context.config) { + Ok(formatted_tpl) => { + let formatted = formatted_tpl?; + if needs_unescape { + formatted.replace("\\", r"\\") + } else { + formatted + } + } Err(err) => { context.diagnostics.push(context::GenerateDiagnostic { message: format!("Error formatting tagged template literal at line {}: {}", node.start_line() + 1, err), diff --git a/tests/specs/external_formatter/html.txt b/tests/specs/external_formatter/html.txt index ef31cd05..a105816a 100644 --- a/tests/specs/external_formatter/html.txt +++ b/tests/specs/external_formatter/html.txt @@ -97,3 +97,10 @@ const a = html` `; + +== should preserve a lone newline escape, not double it (deno#30103) == +html`\n`; +[expect] +html` + \n +`;