diff --git a/apps/oxfmt/conformance/run.ts b/apps/oxfmt/conformance/run.ts index bc1ae5d7ba617..d73a93dd2af66 100644 --- a/apps/oxfmt/conformance/run.ts +++ b/apps/oxfmt/conformance/run.ts @@ -95,8 +95,7 @@ const categories: Category[] = [ ], optionSets: [{ printWidth: 80 }], notes: { - "comment-inside.js": - "html embed expressions not yet implemented; css `${}` indentation bug (TODO)", + "comment-inside.js": "html embed expressions not yet implemented", }, }, ]; diff --git a/apps/oxfmt/conformance/snapshots/conformance.snap.md b/apps/oxfmt/conformance/snapshots/conformance.snap.md index 6abd6b80cdbd3..598710e1f4098 100644 --- a/apps/oxfmt/conformance/snapshots/conformance.snap.md +++ b/apps/oxfmt/conformance/snapshots/conformance.snap.md @@ -68,4 +68,4 @@ | File | Note | | :--- | :--- | -| [comment-inside.js](diffs/xxx-in-js-comment/comment-inside.js.md) | html embed expressions not yet implemented; css `${}` indentation bug (TODO) | +| [comment-inside.js](diffs/xxx-in-js-comment/comment-inside.js.md) | html embed expressions not yet implemented | diff --git a/apps/oxfmt/conformance/snapshots/diffs/xxx-in-js-comment/comment-inside.js.md b/apps/oxfmt/conformance/snapshots/diffs/xxx-in-js-comment/comment-inside.js.md index 818b5358b3535..96b466aebaeb6 100644 --- a/apps/oxfmt/conformance/snapshots/diffs/xxx-in-js-comment/comment-inside.js.md +++ b/apps/oxfmt/conformance/snapshots/diffs/xxx-in-js-comment/comment-inside.js.md @@ -1,6 +1,6 @@ # comment-inside.js -> html embed expressions not yet implemented; css `${}` indentation bug (TODO) +> html embed expressions not yet implemented ## Option 1 @@ -31,29 +31,7 @@ graphql` ${ -@@ -32,17 +32,15 @@ - } - `; - - css` -- ${ -- foo -- /* comment */ -+ ${foo -+ /* comment */ - } - `; - css` -- ${ -- foo -- /* comment */ -+ ${foo -+ /* comment */ - } - `; - - markdown`${ -@@ -61,7 +59,6 @@ +@@ -61,7 +61,6 @@
${x( foo, // fg @@ -103,13 +81,15 @@ graphql` `; css` - ${foo - /* comment */ + ${ + foo + /* comment */ } `; css` - ${foo - /* comment */ + ${ + foo + /* comment */ } `; diff --git a/crates/oxc_formatter/src/print/template/embed/css.rs b/crates/oxc_formatter/src/print/template/embed/css.rs index 47b29881da274..f8c7919f0868f 100644 --- a/crates/oxc_formatter/src/print/template/embed/css.rs +++ b/crates/oxc_formatter/src/print/template/embed/css.rs @@ -1,5 +1,6 @@ use oxc_allocator::{Allocator, StringBuilder}; use oxc_ast::ast::*; +use oxc_span::GetSpan; use crate::{ IndentWidth, @@ -102,19 +103,40 @@ pub(super) fn format_css_doc<'a>( write_text_with_line_breaks(f, part, allocator, indent_width); } } else if let Some(idx) = part.parse::().ok() - && let Some(expr) = expressions.get(idx) + && let Some(&expr) = expressions.get(idx) { - // Format `${expr}` directly to preserve soft line breaks - // so the printer can decide line breaks based on `printWidth`. - // (Regular template expressions use `RemoveSoftLinesBuffer` - // which forces single-line layout.) - // TODO: Expression indentation is incorrect — Prettier indents - // `${ expr }` with the surrounding CSS block, but we don't. - // See `multiparser-comments/comment-inside.js` css cases. - write!( - f, - [group(&format_args!("${", expr, line_suffix_boundary(), "}"))] - ); + // Prettier's `printTemplateExpression()` adds indent+softline when: + // - the original source has newlines in the interpolation + // - AND the expression is a comment-bearing node or Identifier/etc + // For CSS embed, the relevant case is comments inside `${...}`. + let has_newline = f.source_text().has_newline_before(expr.span().start) + || f.source_text().has_newline_after(expr.span().end); + let has_comment = has_newline && { + let comments = f.context().comments(); + let leading = comments.comments_before(expr.span().start); + let trailing = + comments.comments_before_character(expr.span().start, b'}'); + !leading.is_empty() || !trailing.is_empty() + }; + + let format_expr = format_with(|f| { + if has_comment { + write!( + f, + [ + indent(&format_args!( + soft_line_break(), + expr, + line_suffix_boundary() + )), + soft_line_break() + ] + ); + } else { + write!(f, [expr, line_suffix_boundary()]); + } + }); + write!(f, [group(&format_args!("${", format_expr, "}"))]); } } }