Skip to content

Commit 1d5dbc8

Browse files
authored
fix: handle jsx ignore container followed by jsx text (#681)
1 parent d017389 commit 1d5dbc8

File tree

2 files changed

+69
-6
lines changed

2 files changed

+69
-6
lines changed

src/generation/generate.rs

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,19 @@ fn gen_node_with_inner_gen<'a>(node: Node<'a>, context: &mut Context<'a>, inner_
9696
// generate the node
9797
if has_ignore_comment {
9898
items.push_force_current_line_indentation();
99-
items.extend(inner_gen(ir_helpers::gen_from_raw_string(node.text_fast(context.program)), context));
99+
let node_text = if node_kind == NodeKind::JSXText {
100+
// keep the leading text, but leave the trailing text to be formatted if on a separate line
101+
let node_text = node.text_fast(context.program);
102+
let end_trim = node_text.trim_end();
103+
if node_text[end_trim.len()..].contains('\n') {
104+
end_trim
105+
} else {
106+
node_text
107+
}
108+
} else {
109+
node.text_fast(context.program)
110+
};
111+
items.extend(inner_gen(ir_helpers::gen_from_raw_string(node_text), context));
100112

101113
// mark any previous comments as handled
102114
for comment in context.comments.trailing_comments_with_previous(node_end) {
@@ -432,6 +444,20 @@ fn get_has_ignore_comment<'a>(leading_comments: &CommentsIterator<'a>, node: Nod
432444
}
433445
}
434446

447+
fn is_ignore_jsx_expr_container(node: Node, context: &Context) -> bool {
448+
if let Node::JSXExprContainer(expr_container) = node {
449+
if let JSXExpr::JSXEmptyExpr(empty_expr) = expr_container.expr {
450+
for comment in get_jsx_empty_expr_comments(empty_expr, context) {
451+
if ir_helpers::text_has_dprint_ignore(&comment.text, &context.config.ignore_node_comment_text) {
452+
return true;
453+
}
454+
}
455+
}
456+
}
457+
458+
false
459+
}
460+
435461
/* class */
436462

437463
fn gen_class_method<'a>(node: &'a ClassMethod<'a>, context: &mut Context<'a>) -> PrintItems {
@@ -6830,7 +6856,7 @@ fn get_trailing_comments_same_line<'a>(node: &SourceRange, trailing_comments: Co
68306856
trailing_comments_on_same_line
68316857
}
68326858

6833-
fn get_jsx_empty_expr_comments<'a>(node: &JSXEmptyExpr, context: &mut Context<'a>) -> CommentsIterator<'a> {
6859+
fn get_jsx_empty_expr_comments<'a>(node: &JSXEmptyExpr, context: &Context<'a>) -> CommentsIterator<'a> {
68346860
node.end().leading_comments_fast(context.program)
68356861
}
68366862

@@ -7210,12 +7236,16 @@ where
72107236
let mut items = PrintItems::new();
72117237
let children_len = opts.items.len();
72127238

7213-
for (i, (node, optional_print_items)) in opts.items.into_iter().enumerate() {
7239+
let mut member_items = opts.items.into_iter().enumerate().peekable();
7240+
7241+
while let Some((i, (node, optional_print_items))) = member_items.next() {
72147242
// class declarations may have empty statements
72157243
let is_empty_stmt = node.is::<EmptyStmt>();
72167244
if !is_empty_stmt {
72177245
if let Some(last_node) = last_node {
7218-
if should_use_new_line(&opts.should_use_new_line, last_node, node, context) {
7246+
if is_ignore_jsx_expr_container(last_node, context) && node.kind() == NodeKind::JSXText {
7247+
// ignore
7248+
} else if should_use_new_line(&opts.should_use_new_line, last_node, node, context) {
72197249
items.push_signal(Signal::NewLine);
72207250

72217251
if (opts.should_use_blank_line)(last_node, node, context) {
@@ -7232,11 +7262,12 @@ where
72327262
}
72337263
}
72347264

7265+
let next_node = member_items.peek().map(|(_, (n, _))| n);
72357266
let end_ln = LineNumber::new("endMember");
72367267
context.end_statement_or_member_lns.push(end_ln);
72377268
items.extend(if let Some(print_items) = optional_print_items {
72387269
print_items
7239-
} else if opts.separator.is_none() {
7270+
} else if opts.separator.is_none() || is_ignore_jsx_expr_container(node, context) && next_node.map(|n| n.kind() == NodeKind::JSXText).unwrap_or(false) {
72407271
gen_node(node, context)
72417272
} else {
72427273
let generated_separator = get_generated_separator(&opts.separator, i == children_len - 1, &condition_resolvers::true_resolver());
@@ -9021,7 +9052,9 @@ fn gen_jsx_children<'a>(opts: GenJsxChildrenOptions<'a>, context: &mut Context<'
90219052
}
90229053

90239054
fn jsx_space_separator<'a>(previous_node: Node<'a>, current_node: Node<'a>, context: &Context<'a>) -> PrintItems {
9024-
return if node_should_force_newline_if_multi_line(previous_node) || node_should_force_newline_if_multi_line(current_node) {
9055+
return if is_ignore_jsx_expr_container(previous_node, context) && current_node.kind() == NodeKind::JSXText {
9056+
PrintItems::new()
9057+
} else if node_should_force_newline_if_multi_line(previous_node) || node_should_force_newline_if_multi_line(current_node) {
90259058
jsx_force_space_with_newline_if_either_node_multi_line(previous_node, current_node, context)
90269059
} else {
90279060
jsx_space_or_newline_or_expr_space(previous_node, current_node, context)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
~~ deno: true ~~
2+
== should be stable at formatting ==
3+
<>
4+
<div>
5+
{/* deno-fmt-ignore */}
6+
foo
7+
</div>
8+
<div>
9+
{/* deno-fmt-ignore */} foo
10+
</div>
11+
<div>{/* deno-fmt-ignore */} foo </div>
12+
</>;
13+
14+
[expect]
15+
<>
16+
<div>
17+
{/* deno-fmt-ignore */}
18+
foo
19+
</div>
20+
<div>
21+
{/* deno-fmt-ignore */} foo
22+
</div>
23+
<div>{/* deno-fmt-ignore */} foo </div>
24+
</>;
25+
26+
== should be stable at formatting single line ==
27+
<div>{/* deno-fmt-ignore */} foo </div>;
28+
29+
[expect]
30+
<div>{/* deno-fmt-ignore */} foo </div>;

0 commit comments

Comments
 (0)