Skip to content

Commit 373e234

Browse files
committed
fix(rome_js_formatter): in JSX, some spaces are removed rome#3211
1 parent 3a007d4 commit 373e234

File tree

7 files changed

+129
-547
lines changed

7 files changed

+129
-547
lines changed

crates/rome_js_formatter/src/jsx/lists/child_list.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use crate::utils::jsx::{
66
use crate::JsFormatter;
77
use rome_formatter::{format_args, write, CstFormatContext, FormatRuleWithOptions, VecBuffer};
88
use rome_js_syntax::{JsxAnyChild, JsxChildList};
9-
use rome_rowan::TextSize;
109
use std::cell::RefCell;
1110

1211
#[derive(Debug, Clone, Default)]
@@ -185,7 +184,7 @@ impl FormatJsxChildList {
185184
// adefg
186185
// ```
187186
if matches!(non_text, JsxAnyChild::JsxSelfClosingElement(_))
188-
&& word.len() != TextSize::from(1)
187+
&& !word.is_ascii_punctuation()
189188
{
190189
Some(LineMode::Hard)
191190
} else {

crates/rome_js_formatter/src/utils/jsx.rs

+24-33
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ impl Format<JsFormatContext> for JsxSpace {
168168
write![
169169
formatter,
170170
[
171-
if_group_breaks(&format_args![JsxRawSpace, soft_line_break()]),
171+
if_group_breaks(&format_args![JsxRawSpace, hard_line_break()]),
172172
if_group_fits_on_line(&space())
173173
]
174174
]
@@ -223,7 +223,7 @@ pub(crate) fn jsx_split_children<I>(
223223
where
224224
I: IntoIterator<Item = JsxAnyChild>,
225225
{
226-
let mut builder = JsxSplitChildrenBuilder::default();
226+
let mut builder = JsxSplitChildrenBuilder::new();
227227

228228
for child in children.into_iter() {
229229
match child {
@@ -309,45 +309,31 @@ where
309309
Ok(builder.finish())
310310
}
311311

312-
#[derive(Debug, Default)]
312+
/// The builder removes [JsxChild::EmptyLine], [JsxChild::Newline], [JsxChild::Whitespace]
313+
/// if a next element is [JsxChild::Whitespace]
314+
/// [Prettier applies]: https://github.com/prettier/prettier/blob/b0d9387b95cdd4e9d50f5999d3be53b0b5d03a97/src/language-js/print/jsx.js#L144-L180
315+
#[derive(Debug)]
313316
struct JsxSplitChildrenBuilder {
314-
pending: Option<JsxChild>,
315317
buffer: Vec<JsxChild>,
316318
}
317319

318320
impl JsxSplitChildrenBuilder {
319-
fn is_last_whitespace(&self) -> bool {
320-
matches!(self.buffer.last(), Some(JsxChild::Whitespace))
321+
fn new() -> Self {
322+
JsxSplitChildrenBuilder { buffer: vec![] }
321323
}
322324

323325
fn entry(&mut self, child: JsxChild) {
324-
if let Some(pending) = self.pending.take() {
325-
if matches!(
326-
pending,
327-
JsxChild::EmptyLine | JsxChild::Newline | JsxChild::Whitespace
328-
) {
329-
if !matches!(child, JsxChild::Whitespace) && !self.is_last_whitespace() {
330-
self.buffer.push(pending)
331-
}
332-
} else {
333-
self.buffer.push(pending);
326+
match self.buffer.last_mut() {
327+
Some(last @ (JsxChild::EmptyLine | JsxChild::Newline | JsxChild::Whitespace))
328+
if matches!(child, JsxChild::Whitespace) =>
329+
{
330+
*last = child
334331
}
332+
_ => self.buffer.push(child),
335333
}
336-
337-
self.pending = Some(child);
338334
}
339335

340-
fn finish(mut self) -> Vec<JsxChild> {
341-
if let Some(pending) = self.pending.take() {
342-
if matches!(pending, JsxChild::Whitespace) {
343-
if !self.is_last_whitespace() {
344-
self.buffer.push(pending)
345-
}
346-
} else {
347-
self.buffer.push(pending);
348-
}
349-
}
350-
336+
fn finish(self) -> Vec<JsxChild> {
351337
self.buffer
352338
}
353339
}
@@ -417,8 +403,13 @@ pub(crate) struct JsxWord {
417403
}
418404

419405
impl JsxWord {
420-
pub fn len(&self) -> TextSize {
421-
self.text.len()
406+
pub fn is_ascii_punctuation(&self) -> bool {
407+
self.text.chars().count() == 1
408+
&& self
409+
.text
410+
.chars()
411+
.next()
412+
.map_or(false, |char| char.is_ascii_punctuation())
422413
}
423414
}
424415

@@ -693,7 +684,7 @@ mod tests {
693684
fn split_children_remove_in_row_jsx_whitespaces() {
694685
let child_list = parse_jsx_children(r#"a{' '}{' '}{' '}c{" "}{' '}{" "}"#);
695686

696-
let children = jsx_split_children(&child_list).unwrap();
687+
let children = jsx_split_children(&child_list, &Comments::default()).unwrap();
697688

698689
assert_eq!(
699690
4,
@@ -714,7 +705,7 @@ mod tests {
714705
"#,
715706
);
716707

717-
let children = jsx_split_children(&child_list).unwrap();
708+
let children = jsx_split_children(&child_list, &Comments::default()).unwrap();
718709

719710
assert_eq!(
720711
4,

crates/rome_js_formatter/tests/specs/jsx/element.jsx

+1-11
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,7 @@ b3 =
9393
1
9494
</>;
9595

96-
// one length text should insert soft line break
97-
b4 = <><pre />a</>;
98-
// longer than one length text should insert hard line break
99-
b5 = <><pre />ab</>;
100-
101-
// one length text should insert soft line break show last jsx whitespace
102-
b6 = <><b/>a{' '}bb{" "}cc{" "}dd{" "}ee{" "}{" "}{" "}{" "}{" "}{" "}</>;
103-
// longer than one length text should insert hard line break
104-
b7 = <><b/>longer{' '}bb{" "}cc{" "}dd{" "}ee{" "}{" "}{" "}{" "}{" "}{" "}</>;
105-
106-
const b8 = <div>
96+
const b4 = <div>
10797
Text <a data-very-long-prop-breakline-rome-playground data-other>
10898
some link
10999
</a>{' '}

crates/rome_js_formatter/tests/specs/jsx/element.jsx.snap

+16-48
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,7 @@ b3 =
9898
1
9999
</>;
100100

101-
// one length text should insert soft line break
102-
b4 = <><pre />a</>;
103-
// longer than one length text should insert hard line break
104-
b5 = <><pre />ab</>;
105-
106-
// one length text should insert soft line break show last jsx whitespace
107-
b6 = <><b/>a{' '}bb{" "}cc{" "}dd{" "}ee{" "}{" "}{" "}{" "}{" "}{" "}</>;
108-
// longer than one length text should insert hard line break
109-
b7 = <><b/>longer{' '}bb{" "}cc{" "}dd{" "}ee{" "}{" "}{" "}{" "}{" "}{" "}</>;
110-
111-
const b8 = <div>
101+
const b4 = <div>
112102
Text <a data-very-long-prop-breakline-rome-playground data-other>
113103
some link
114104
</a>{' '}
@@ -368,7 +358,10 @@ c2 = (
368358
// this group should fit one line jsx whitespaces are hidden
369359
b = (
370360
<div>
371-
<a></a> <a></a> 1
361+
<a></a>
362+
363+
<a></a>
364+
1
372365
</div>
373366
);
374367

@@ -381,14 +374,17 @@ b1 = (
381374
12312
382375
`}
383376
</a>{" "}
384-
<a></a> 1
377+
378+
<a></a>
379+
1
385380
</div>
386381
);
387382

388383
// this group fit one line and hide jsx whitespace
389384
b2 = (
390385
<>
391-
<a>123</a> 1
386+
<a>123</a>
387+
1
392388
</>
393389
);
394390

@@ -403,35 +399,7 @@ b3 = (
403399
</>
404400
);
405401

406-
// one length text should insert soft line break
407-
b4 = (
408-
<>
409-
<pre />a
410-
</>
411-
);
412-
// longer than one length text should insert hard line break
413-
b5 = (
414-
<>
415-
<pre />
416-
ab
417-
</>
418-
);
419-
420-
// one length text should insert soft line break show last jsx whitespace
421-
b6 = (
422-
<>
423-
<b />a bb cc dd ee{" "}
424-
</>
425-
);
426-
// longer than one length text should insert hard line break
427-
b7 = (
428-
<>
429-
<b />
430-
longer bb cc dd ee{" "}
431-
</>
432-
);
433-
434-
const b8 = (
402+
const b4 = (
435403
<div>
436404
Text <a data-very-long-prop-breakline-rome-playground data-other>
437405
some link
@@ -649,9 +617,9 @@ const breadcrumbItems = [
649617
2: <div tooltip="A very long tooltip text that would otherwise make the attribute break onto the same line but it is not because of the single string layout"></div>;
650618
7: tooltip="A very long tooltip text that would otherwise make the attribute break
651619
14: <ASuperLongComponentNameThatWouldBreakButDoesntSinceTheComponent></ASuperLongComponentNameThatWouldBreakButDoesntSinceTheComponent>
652-
201: "ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace",
653-
222: "ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace",
654-
235: "ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace",
655-
260: <pre className="h-screen overflow-y-scroll whitespace-pre-wrap text-red-500 text-xs">
656-
309: Uncle Boonmee Who Can Recall His Past Lives dir. Apichatpong Weerasethakul{" "}
620+
179: "ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace",
621+
200: "ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace",
622+
213: "ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace",
623+
238: <pre className="h-screen overflow-y-scroll whitespace-pre-wrap text-red-500 text-xs">
624+
287: Uncle Boonmee Who Can Recall His Past Lives dir. Apichatpong Weerasethakul{" "}
657625

crates/rome_js_formatter/tests/specs/prettier/jsx/significant-space/test.js.snap

+23-56
Original file line numberDiff line numberDiff line change
@@ -89,25 +89,18 @@ not_broken_begin =
8989
```diff
9090
--- Prettier
9191
+++ Rome
92-
@@ -12,7 +12,7 @@
92+
@@ -12,8 +12,7 @@
9393
9494
before_break1 = (
9595
<span>
9696
- <span barbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar />{" "}
97-
+ <span barbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar />
98-
foo
99-
</span>
100-
);
101-
@@ -21,15 +21,16 @@
102-
<span>
103-
<span
104-
barbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar
105-
- />{" "}
106-
+ />
107-
foo
97+
- foo
98+
+ <span barbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar /> foo
10899
</span>
109100
);
110101
102+
@@ -28,8 +27,9 @@
103+
111104
after_break = (
112105
<span>
113106
- foo{" "}
@@ -118,43 +111,15 @@ not_broken_begin =
118111
</span>
119112
);
120113
121-
@@ -79,7 +80,8 @@
122-
123-
regression_not_transformed_2 = (
124-
<span>
125-
- <Icon icon="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />{" "}
126-
+ <Icon icon="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />
127-
+ {" "}
128-
</span>
129-
);
130-
131-
@@ -92,13 +94,15 @@
132-
133-
similar_2 = (
134-
<span>
135-
- <Icon icon="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />{" "}
136-
+ <Icon icon="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />
137-
+ {" "}
138-
</span>
139-
);
140-
141-
similar_3 = (
142-
<span>
143-
- <Icon icon="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" /> <Icon icon="" />
144-
+ <Icon icon="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />
145-
+ <Icon icon="" />
146-
</span>
147-
);
148-
149-
@@ -111,7 +115,8 @@
114+
@@ -111,7 +111,8 @@
150115
151116
not_broken_begin = (
152117
<div>
153118
- <br /> long text long text long text long text long text long text long text
154119
- long text<link>url</link> long text long text
155-
+ <br />
156-
+ long text long text long text long text long text long text long text long
157-
+ text<link>url</link> long text long text
120+
+ <br /> long text long text long text long text long text long text long text long text<link>
121+
+ url
122+
+ </link> long text long text
158123
</div>
159124
);
160125
```
@@ -176,16 +141,15 @@ before = (
176141
177142
before_break1 = (
178143
<span>
179-
<span barbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar />
180-
foo
144+
<span barbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar /> foo
181145
</span>
182146
);
183147
184148
before_break2 = (
185149
<span>
186150
<span
187151
barbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar
188-
/>
152+
/>{" "}
189153
foo
190154
</span>
191155
);
@@ -244,8 +208,7 @@ regression_not_transformed_1 = (
244208
245209
regression_not_transformed_2 = (
246210
<span>
247-
<Icon icon="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />
248-
{" "}
211+
<Icon icon="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />{" "}
249212
</span>
250213
);
251214
@@ -258,15 +221,13 @@ similar_1 = (
258221
259222
similar_2 = (
260223
<span>
261-
<Icon icon="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />
262-
{" "}
224+
<Icon icon="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />{" "}
263225
</span>
264226
);
265227
266228
similar_3 = (
267229
<span>
268-
<Icon icon="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />
269-
<Icon icon="" />
230+
<Icon icon="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" /> <Icon icon="" />
270231
</span>
271232
);
272233
@@ -279,12 +240,18 @@ not_broken_end = (
279240
280241
not_broken_begin = (
281242
<div>
282-
<br />
283-
long text long text long text long text long text long text long text long
284-
text<link>url</link> long text long text
243+
<br /> long text long text long text long text long text long text long text long text<link>
244+
url
245+
</link> long text long text
285246
</div>
286247
);
287248
```
288249

289250

251+
# Lines exceeding max width of 80 characters
252+
```
253+
15: <span barbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbarbar /> foo
254+
95: <Icon icon="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" />{" "}
255+
114: <br /> long text long text long text long text long text long text long text long text<link>
256+
```
290257

0 commit comments

Comments
 (0)