From 2565462efd0b038c82ca1cb063686a5fb41e8434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 23 Jun 2025 21:20:17 +0200 Subject: [PATCH 1/2] feat(BREAKING): external formatter accepts string literal instead of MediaType --- src/format_text.rs | 4 ++-- src/generation/context.rs | 9 +++++---- src/generation/generate.rs | 25 +++++++++---------------- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/format_text.rs b/src/format_text.rs index 3b540bd4..17127352 100644 --- a/src/format_text.rs +++ b/src/format_text.rs @@ -159,8 +159,8 @@ mod test { extension: None, text: "const content = html`
broken html

`".into(), config: &config, - external_formatter: Some(&|media_type, _text, _config| { - assert!(matches!(media_type, deno_ast::MediaType::Html)); + external_formatter: Some(&|lang, _text, _config| { + assert!(matches!(lang, "html")); Err(anyhow::anyhow!("Syntax error from external formatter")) }), }); diff --git a/src/generation/context.rs b/src/generation/context.rs index 9a15b9d7..13b23f7f 100644 --- a/src/generation/context.rs +++ b/src/generation/context.rs @@ -18,9 +18,10 @@ use super::*; use crate::configuration::*; use crate::utils::Stack; -/// A callback that will be called when encountering certain tagged templates. +/// A callback that will be called when encountering tagged templates. /// -/// Currently supports `css`, `html` and `sql` tagged templated. +/// It is up to the caller to decide if a certain tagged template should be formatted +/// by the external formatter. /// /// Examples: /// ```ignore @@ -41,11 +42,11 @@ use crate::utils::Stack; /// active IS TRUE; /// ``` /// -/// External formatter should return `None` if it doesn't understand given `MediaType`, in such +/// External formatter should return `None` if it doesn't understand given language, in such /// cases the templates will be left as they are. /// /// Only templates with no interpolation are supported. -pub type ExternalFormatter = dyn Fn(MediaType, String, &Configuration) -> anyhow::Result>; +pub type ExternalFormatter = dyn Fn(&str, String, &Configuration) -> anyhow::Result>; pub(crate) struct GenerateDiagnostic { pub message: String, diff --git a/src/generation/generate.rs b/src/generation/generate.rs index 74af11cb..f978a04b 100644 --- a/src/generation/generate.rs +++ b/src/generation/generate.rs @@ -3016,13 +3016,13 @@ fn gen_spread_element<'a>(node: &SpreadElement<'a>, context: &mut Context<'a>) - /// Detects the type of embedded language automatically. fn maybe_gen_tagged_tpl_with_external_formatter<'a>(node: &TaggedTpl<'a>, context: &mut Context<'a>) -> Option { let external_formatter = context.external_formatter.as_ref()?; - let media_type = detect_embedded_language_type(node)?; + let embedded_lang = normalize_embedded_language_type(node)?; let placeholder_css = "@dpr1nt_"; let placeholder_other = "dpr1nt_"; // First creates text with placeholders for the expressions. - let placeholder_text = match media_type { - MediaType::Css => placeholder_css, + let placeholder_text = match embedded_lang { + "css" => placeholder_css, _ => placeholder_other, }; let text = capacity_builder::StringBuilder::::build(|builder| { @@ -3043,7 +3043,7 @@ 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(media_type, text.replace(r"\\", "\\"), context.config) { + let formatted_tpl = match external_formatter(embedded_lang, text.replace(r"\\", "\\"), context.config) { Ok(formatted_tpl) => formatted_tpl?.replace("\\", r"\\"), Err(err) => { context.diagnostics.push(context::GenerateDiagnostic { @@ -3102,21 +3102,14 @@ fn maybe_gen_tagged_tpl_with_external_formatter<'a>(node: &TaggedTpl<'a>, contex Some(items) } -/// Detects the type of embedded language in a tagged template literal. -fn detect_embedded_language_type<'a>(node: &TaggedTpl<'a>) -> Option { +/// Normalizes the type of embedded language in a tagged template literal. +fn normalize_embedded_language_type<'a>(node: &TaggedTpl<'a>) -> Option<&'a str> { match node.tag { - Expr::Ident(ident) => { - match ident.sym().as_str() { - "css" => Some(MediaType::Css), // css`...` - "html" => Some(MediaType::Html), // html`...` - "sql" => Some(MediaType::Sql), // sql`...` - _ => None, - } - } + Expr::Ident(ident) => return Some(ident.sym().as_str()), Expr::Member(member_expr) => { if let Expr::Ident(ident) = member_expr.obj { if ident.sym().as_str() == "styled" { - return Some(MediaType::Css); // styled.foo`...` + return Some("css"); // styled.foo`...` } } None @@ -3124,7 +3117,7 @@ fn detect_embedded_language_type<'a>(node: &TaggedTpl<'a>) -> Option Expr::Call(call_expr) => { if let Callee::Expr(Expr::Ident(ident)) = call_expr.callee { if ident.sym().as_str() == "styled" { - return Some(MediaType::Css); // styled(Button)`...` + return Some("css"); // styled(Button)`...` } } None From 94db921f0a09dbff9fae6591d46ddfedfdc05ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Mon, 23 Jun 2025 21:26:35 +0200 Subject: [PATCH 2/2] fix tests --- tests/spec_test.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/spec_test.rs b/tests/spec_test.rs index c928f5de..489284b1 100644 --- a/tests/spec_test.rs +++ b/tests/spec_test.rs @@ -2,18 +2,17 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use anyhow::Result; -use deno_ast::MediaType; use dprint_core::configuration::*; use dprint_development::*; use dprint_plugin_typescript::configuration::*; use dprint_plugin_typescript::*; -fn external_formatter(media_type: MediaType, text: String, config: &Configuration) -> Result> { - match media_type { - MediaType::Css => format_embedded_css(&text, config), - MediaType::Html => format_html(&text, config), - MediaType::Sql => format_sql(&text, config), - _ => unreachable!(), +fn external_formatter(lang: &str, text: String, config: &Configuration) -> Result> { + match lang { + "css" => format_embedded_css(&text, config), + "html" => format_html(&text, config), + "sql" => format_sql(&text, config), + _ => Ok(None), } }