fix(es/transforms/react): Fix handling of whitespaces (#2638)

swc_ecma_transforms_react:
 - `jsx`: Preserve more whitespaces in input. (Closes #2208)
This commit is contained in:
RiESAEX 2021-11-09 14:10:23 +08:00 committed by GitHub
parent ca2338edbd
commit 7ab3b5b0b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 103 additions and 96 deletions

View File

@ -4,7 +4,7 @@ use dashmap::DashMap;
use once_cell::sync::Lazy;
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::{iter, iter::once, mem, sync::Arc};
use std::{borrow::Cow, iter, iter::once, mem, sync::Arc};
use string_enum::StringEnum;
use swc_atoms::{js_word, JsWord};
use swc_common::{
@ -1130,41 +1130,34 @@ fn to_prop_name(n: JSXAttrName) -> PropName {
#[inline]
fn jsx_text_to_str(t: JsWord) -> JsWord {
static SPACE_NL_START: Lazy<Regex> =
Lazy::new(|| Regex::new("^[\t'\n\x0C\r ]*\n[\t'\n\x0C\r ]*").unwrap());
static SPACE_NL_END: Lazy<Regex> =
Lazy::new(|| Regex::new("[\t'\n\x0C\r ]*\n[\t'\n\x0C\r ]*$").unwrap());
if t == *" " {
return t;
}
if !t.contains(' ') && !t.contains('\n') {
return t;
}
let s = SPACE_NL_START.replace_all(&t, "");
let s = SPACE_NL_END.replace_all(&s, "");
let need_leading_space = s.starts_with(' ');
let need_trailing_space = s.ends_with(' ');
let mut buf = String::from(if need_leading_space { " " } else { "" });
for (last, s) in s
.split(|c: char| c != '\u{a0}' && c.is_ascii_whitespace())
.filter(|s| !s.is_empty())
.identify_last()
{
buf.push_str(s);
if !last {
buf.push(' ');
static SPACE_START: Lazy<Regex> = Lazy::new(|| Regex::new("^[ ]+").unwrap());
static SPACE_END: Lazy<Regex> = Lazy::new(|| Regex::new("[ ]+$").unwrap());
let mut buf = String::new();
let replaced = t.replace('\t', " ");
let lines: Vec<&str> = replaced.lines().collect();
for (is_last, (i, line)) in lines.into_iter().enumerate().identify_last() {
if line.len() == 0 {
continue;
}
let line = Cow::from(line);
let line = if i != 0 {
SPACE_START.replace_all(&line, "")
} else {
line
};
let line = if is_last {
line
} else {
SPACE_END.replace_all(&line, "")
};
if line.len() == 0 {
continue;
}
if i != 0 && buf.len() != 0 {
buf.push_str(" ")
}
buf.push_str(&line);
}
if need_trailing_space && !buf.ends_with(' ') {
buf.push(' ');
}
buf.into()
}

View File

@ -0,0 +1,8 @@
{
"jsc": {
"parser": {
"syntax": "ecmascript",
"jsx": true
}
}
}

View File

@ -0,0 +1,3 @@
const Component = () => {
return <pre>| | |</pre>;
};

View File

@ -0,0 +1,3 @@
var Component = function() {
return(/*#__PURE__*/ React.createElement("pre", null, "| | |"));
};

View File

@ -19,13 +19,13 @@ function Comp(p) {
let k1 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, /*#__PURE__*/ React.createElement(Button, null), " ", /*#__PURE__*/ React.createElement(AnotherButton, null));
}, /*#__PURE__*/ React.createElement(Button, null), " ", /*#__PURE__*/ React.createElement(AnotherButton, null));
let k2 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null), " ");
}, /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null), " ");
let k3 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, " ", /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null));
}, " ", /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null));
export { };

View File

@ -13,11 +13,11 @@ function Comp(p) {
React.createElement(Comp, {
a: 10,
b: "hi"
}, React.createElement(Button, null), " ", React.createElement(AnotherButton, null)), React.createElement(Comp, {
}, React.createElement(Button, null), " ", React.createElement(AnotherButton, null)), React.createElement(Comp, {
a: 10,
b: "hi"
}, React.createElement(Button, null), React.createElement(AnotherButton, null), " "), React.createElement(Comp, {
}, React.createElement(Button, null), React.createElement(AnotherButton, null), " "), React.createElement(Comp, {
a: 10,
b: "hi"
}, " ", React.createElement(Button, null), React.createElement(AnotherButton, null));
}, " ", React.createElement(Button, null), React.createElement(AnotherButton, null));
export { };

View File

@ -91,13 +91,13 @@ function Comp(p) {
var k1 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, /*#__PURE__*/ React.createElement(Button, null), " ", /*#__PURE__*/ React.createElement(AnotherButton, null));
}, /*#__PURE__*/ React.createElement(Button, null), " ", /*#__PURE__*/ React.createElement(AnotherButton, null));
var k2 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null), " ");
}, /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null), " ");
var k3 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, " ", /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null));
}, " ", /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null));
export { };

View File

@ -53,11 +53,11 @@ function Comp(p) {
React.createElement(Comp, {
a: 10,
b: "hi"
}, React.createElement(Button, null), " ", React.createElement(AnotherButton, null)), React.createElement(Comp, {
}, React.createElement(Button, null), " ", React.createElement(AnotherButton, null)), React.createElement(Comp, {
a: 10,
b: "hi"
}, React.createElement(Button, null), React.createElement(AnotherButton, null), " "), React.createElement(Comp, {
}, React.createElement(Button, null), React.createElement(AnotherButton, null), " "), React.createElement(Comp, {
a: 10,
b: "hi"
}, " ", React.createElement(Button, null), React.createElement(AnotherButton, null));
}, " ", React.createElement(Button, null), React.createElement(AnotherButton, null));
export { };

View File

@ -19,17 +19,17 @@ function Comp(p) {
let k1 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, /*#__PURE__*/ React.createElement(Button, null), " ", /*#__PURE__*/ React.createElement(AnotherButton, null));
}, /*#__PURE__*/ React.createElement(Button, null), " ", /*#__PURE__*/ React.createElement(AnotherButton, null));
let k2 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null), " ");
}, /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null), " ");
let k3 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, " ", /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null));
}, " ", /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null));
let k4 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, /*#__PURE__*/ React.createElement(Button, null), " ");
}, /*#__PURE__*/ React.createElement(Button, null), " ");
export { };

View File

@ -13,14 +13,14 @@ function Comp(p) {
React.createElement(Comp, {
a: 10,
b: "hi"
}, React.createElement(Button, null), " ", React.createElement(AnotherButton, null)), React.createElement(Comp, {
}, React.createElement(Button, null), " ", React.createElement(AnotherButton, null)), React.createElement(Comp, {
a: 10,
b: "hi"
}, React.createElement(Button, null), React.createElement(AnotherButton, null), " "), React.createElement(Comp, {
}, React.createElement(Button, null), React.createElement(AnotherButton, null), " "), React.createElement(Comp, {
a: 10,
b: "hi"
}, " ", React.createElement(Button, null), React.createElement(AnotherButton, null)), React.createElement(Comp, {
}, " ", React.createElement(Button, null), React.createElement(AnotherButton, null)), React.createElement(Comp, {
a: 10,
b: "hi"
}, React.createElement(Button, null), " ");
}, React.createElement(Button, null), " ");
export { };

View File

@ -91,17 +91,17 @@ function Comp(p) {
var k1 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, /*#__PURE__*/ React.createElement(Button, null), " ", /*#__PURE__*/ React.createElement(AnotherButton, null));
}, /*#__PURE__*/ React.createElement(Button, null), " ", /*#__PURE__*/ React.createElement(AnotherButton, null));
var k2 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null), " ");
}, /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null), " ");
var k3 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, " ", /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null));
}, " ", /*#__PURE__*/ React.createElement(Button, null), /*#__PURE__*/ React.createElement(AnotherButton, null));
var k4 = /*#__PURE__*/ React.createElement(Comp, {
a: 10,
b: "hi"
}, /*#__PURE__*/ React.createElement(Button, null), " ");
}, /*#__PURE__*/ React.createElement(Button, null), " ");
export { };

View File

@ -53,14 +53,14 @@ function Comp(p) {
React.createElement(Comp, {
a: 10,
b: "hi"
}, React.createElement(Button, null), " ", React.createElement(AnotherButton, null)), React.createElement(Comp, {
}, React.createElement(Button, null), " ", React.createElement(AnotherButton, null)), React.createElement(Comp, {
a: 10,
b: "hi"
}, React.createElement(Button, null), React.createElement(AnotherButton, null), " "), React.createElement(Comp, {
}, React.createElement(Button, null), React.createElement(AnotherButton, null), " "), React.createElement(Comp, {
a: 10,
b: "hi"
}, " ", React.createElement(Button, null), React.createElement(AnotherButton, null)), React.createElement(Comp, {
}, " ", React.createElement(Button, null), React.createElement(AnotherButton, null)), React.createElement(Comp, {
a: 10,
b: "hi"
}, React.createElement(Button, null), " ");
}, React.createElement(Button, null), " ");
export { };

View File

@ -4,11 +4,11 @@ function VerticalNavMenuItem(prop) {
function VerticalNav() {
return(/*#__PURE__*/ React.createElement("div", null, /*#__PURE__*/ React.createElement(VerticalNavMenuItem, {
primaryText: 2
}), " // error", /*#__PURE__*/ React.createElement(VerticalNavMenuItem, {
}), " // error", /*#__PURE__*/ React.createElement(VerticalNavMenuItem, {
justRandomProp: 2,
primaryText: "hello"
}), " // ok", /*#__PURE__*/ React.createElement(VerticalNavMenuItem, {
}), " // ok", /*#__PURE__*/ React.createElement(VerticalNavMenuItem, {
justRandomProp1: true,
primaryText: "hello"
}), " // error"));
}), " // error"));
}

View File

@ -4,11 +4,11 @@ function VerticalNavMenuItem(prop) {
function VerticalNav() {
return(/*#__PURE__*/ React.createElement("div", null, /*#__PURE__*/ React.createElement(VerticalNavMenuItem, {
primaryText: 2
}), " // error", /*#__PURE__*/ React.createElement(VerticalNavMenuItem, {
}), " // error", /*#__PURE__*/ React.createElement(VerticalNavMenuItem, {
justRandomProp: 2,
primaryText: "hello"
}), " // ok", /*#__PURE__*/ React.createElement(VerticalNavMenuItem, {
}), " // ok", /*#__PURE__*/ React.createElement(VerticalNavMenuItem, {
justRandomProp1: true,
primaryText: "hello"
}), " // error"));
}), " // error"));
}

View File

@ -64,6 +64,6 @@ class SomeClass {
});
}
}
var whitespace1 = /*#__PURE__*/ React.createElement("div", null, " ");
var whitespace2 = /*#__PURE__*/ React.createElement("div", null, " ", p, " ");
var whitespace1 = /*#__PURE__*/ React.createElement("div", null, " ");
var whitespace2 = /*#__PURE__*/ React.createElement("div", null, " ", p, " ");
var whitespace3 = /*#__PURE__*/ React.createElement("div", null, p);

View File

@ -23,4 +23,4 @@ React.createElement("div", null), React.createElement("div", {
n: "m"
}, !1), React.createElement("div", {
n: "m"
}, !1), React.createElement("div", null, " "), React.createElement("div", null, " ", p, " "), React.createElement("div", null, p);
}, !1), React.createElement("div", null, " "), React.createElement("div", null, " ", p, " "), React.createElement("div", null, p);

View File

@ -114,6 +114,6 @@ var SomeClass = /*#__PURE__*/ function() {
]);
return SomeClass;
}();
var whitespace1 = /*#__PURE__*/ React.createElement("div", null, " ");
var whitespace2 = /*#__PURE__*/ React.createElement("div", null, " ", p, " ");
var whitespace1 = /*#__PURE__*/ React.createElement("div", null, " ");
var whitespace2 = /*#__PURE__*/ React.createElement("div", null, " ", p, " ");
var whitespace3 = /*#__PURE__*/ React.createElement("div", null, p);

View File

@ -81,4 +81,4 @@ var p, SomeClass = function() {
}
], _defineProperties(Constructor.prototype, protoProps), staticProps && _defineProperties(Constructor, staticProps), SomeClass;
}();
React.createElement("div", null, " "), React.createElement("div", null, " ", p, " "), React.createElement("div", null, p);
React.createElement("div", null, " "), React.createElement("div", null, " ", p, " "), React.createElement("div", null, p);

View File

@ -66,6 +66,6 @@ class SomeClass {
});
}
}
var whitespace1 = /*#__PURE__*/ React.createElement("div", null, " ");
var whitespace2 = /*#__PURE__*/ React.createElement("div", null, " ", p, " ");
var whitespace1 = /*#__PURE__*/ React.createElement("div", null, " ");
var whitespace2 = /*#__PURE__*/ React.createElement("div", null, " ", p, " ");
var whitespace3 = /*#__PURE__*/ React.createElement("div", null, p);

View File

@ -25,4 +25,4 @@ React.createElement("div", null), React.createElement("div", {
}, !1), React.createElement("div", {
n: "m",
b: !0
}, !1), React.createElement("div", null, " "), React.createElement("div", null, " ", p, " "), React.createElement("div", null, p);
}, !1), React.createElement("div", null, " "), React.createElement("div", null, " ", p, " "), React.createElement("div", null, p);

View File

@ -116,6 +116,6 @@ var SomeClass = /*#__PURE__*/ function() {
]);
return SomeClass;
}();
var whitespace1 = /*#__PURE__*/ React.createElement("div", null, " ");
var whitespace2 = /*#__PURE__*/ React.createElement("div", null, " ", p, " ");
var whitespace1 = /*#__PURE__*/ React.createElement("div", null, " ");
var whitespace2 = /*#__PURE__*/ React.createElement("div", null, " ", p, " ");
var whitespace3 = /*#__PURE__*/ React.createElement("div", null, p);

View File

@ -83,4 +83,4 @@ var p, SomeClass = function() {
}
], _defineProperties(Constructor.prototype, protoProps), staticProps && _defineProperties(Constructor, staticProps), SomeClass;
}();
React.createElement("div", null, " "), React.createElement("div", null, " ", p, " "), React.createElement("div", null, p);
React.createElement("div", null, " "), React.createElement("div", null, " ", p, " "), React.createElement("div", null, p);

View File

@ -1 +1 @@
/*#__PURE__*/ React.createElement(Foo, null, " ", /*#__PURE__*/ React.createElement(Bar, null, " q "), " ", /*#__PURE__*/ React.createElement(Bar, null), " s ", /*#__PURE__*/ React.createElement(Bar, null), /*#__PURE__*/ React.createElement(Bar, null));
/*#__PURE__*/ React.createElement(Foo, null, " ", /*#__PURE__*/ React.createElement(Bar, null, " q "), " ", /*#__PURE__*/ React.createElement(Bar, null), " s ", /*#__PURE__*/ React.createElement(Bar, null), /*#__PURE__*/ React.createElement(Bar, null));

View File

@ -1 +1 @@
React.createElement(Foo, null, " ", React.createElement(Bar, null, " q "), " ", React.createElement(Bar, null), " s ", React.createElement(Bar, null), React.createElement(Bar, null));
React.createElement(Foo, null, " ", React.createElement(Bar, null, " q "), " ", React.createElement(Bar, null), " s ", React.createElement(Bar, null), React.createElement(Bar, null));

View File

@ -1 +1 @@
/*#__PURE__*/ React.createElement(Foo, null, " ", /*#__PURE__*/ React.createElement(Bar, null, " q "), " ", /*#__PURE__*/ React.createElement(Bar, null), " s ", /*#__PURE__*/ React.createElement(Bar, null), /*#__PURE__*/ React.createElement(Bar, null));
/*#__PURE__*/ React.createElement(Foo, null, " ", /*#__PURE__*/ React.createElement(Bar, null, " q "), " ", /*#__PURE__*/ React.createElement(Bar, null), " s ", /*#__PURE__*/ React.createElement(Bar, null), /*#__PURE__*/ React.createElement(Bar, null));

View File

@ -1 +1 @@
React.createElement(Foo, null, " ", React.createElement(Bar, null, " q "), " ", React.createElement(Bar, null), " s ", React.createElement(Bar, null), React.createElement(Bar, null));
React.createElement(Foo, null, " ", React.createElement(Bar, null, " q "), " ", React.createElement(Bar, null), " s ", React.createElement(Bar, null), React.createElement(Bar, null));

View File

@ -2,17 +2,17 @@
// WHITESPACE, DO NOT RUN 'FORMAT DOCUMENT' ON IT
var p = 0;
// Emit " "
/*#__PURE__*/ React.createElement("div", null, " ");
/*#__PURE__*/ React.createElement("div", null, " ");
// Emit " ", p, " "
/*#__PURE__*/ React.createElement("div", null, " ", p, " ");
/*#__PURE__*/ React.createElement("div", null, " ", p, " ");
// Emit only p
/*#__PURE__*/ React.createElement("div", null, p);
// Emit only p
/*#__PURE__*/ React.createElement("div", null, p);
// Emit " 3"
/*#__PURE__*/ React.createElement("div", null, " 3");
/*#__PURE__*/ React.createElement("div", null, " 3");
// Emit " 3 "
/*#__PURE__*/ React.createElement("div", null, " 3 ");
/*#__PURE__*/ React.createElement("div", null, " 3 ");
// Emit "3"
/*#__PURE__*/ React.createElement("div", null, "3");
// Emit no args
@ -22,4 +22,4 @@ var p = 0;
// Emit "hello\\ world"
/*#__PURE__*/ React.createElement("div", null, "hello\\ world");
// Emit " a b c d "
/*#__PURE__*/ React.createElement("div", null, " a b c d ");
/*#__PURE__*/ React.createElement("div", null, " a b c d ");

View File

@ -1 +1 @@
React.createElement("div", null, " "), React.createElement("div", null, " ", 0, " "), React.createElement("div", null, 0), React.createElement("div", null, 0), React.createElement("div", null, " 3"), React.createElement("div", null, " 3 "), React.createElement("div", null, "3"), React.createElement("div", null), React.createElement("div", null, "foo bar"), React.createElement("div", null, "hello\\ world"), React.createElement("div", null, " a b c d ");
React.createElement("div", null, " "), React.createElement("div", null, " ", 0, " "), React.createElement("div", null, 0), React.createElement("div", null, 0), React.createElement("div", null, " 3"), React.createElement("div", null, " 3 "), React.createElement("div", null, "3"), React.createElement("div", null), React.createElement("div", null, "foo bar"), React.createElement("div", null, "hello\\ world"), React.createElement("div", null, " a b c d ");

View File

@ -2,17 +2,17 @@
// WHITESPACE, DO NOT RUN 'FORMAT DOCUMENT' ON IT
var p = 0;
// Emit " "
/*#__PURE__*/ React.createElement("div", null, " ");
/*#__PURE__*/ React.createElement("div", null, " ");
// Emit " ", p, " "
/*#__PURE__*/ React.createElement("div", null, " ", p, " ");
/*#__PURE__*/ React.createElement("div", null, " ", p, " ");
// Emit only p
/*#__PURE__*/ React.createElement("div", null, p);
// Emit only p
/*#__PURE__*/ React.createElement("div", null, p);
// Emit " 3"
/*#__PURE__*/ React.createElement("div", null, " 3");
/*#__PURE__*/ React.createElement("div", null, " 3");
// Emit " 3 "
/*#__PURE__*/ React.createElement("div", null, " 3 ");
/*#__PURE__*/ React.createElement("div", null, " 3 ");
// Emit "3"
/*#__PURE__*/ React.createElement("div", null, "3");
// Emit no args
@ -22,4 +22,4 @@ var p = 0;
// Emit "hello\\ world"
/*#__PURE__*/ React.createElement("div", null, "hello\\ world");
// Emit " a b c d "
/*#__PURE__*/ React.createElement("div", null, " a b c d ");
/*#__PURE__*/ React.createElement("div", null, " a b c d ");

View File

@ -1 +1 @@
React.createElement("div", null, " "), React.createElement("div", null, " ", 0, " "), React.createElement("div", null, 0), React.createElement("div", null, 0), React.createElement("div", null, " 3"), React.createElement("div", null, " 3 "), React.createElement("div", null, "3"), React.createElement("div", null), React.createElement("div", null, "foo bar"), React.createElement("div", null, "hello\\ world"), React.createElement("div", null, " a b c d ");
React.createElement("div", null, " "), React.createElement("div", null, " ", 0, " "), React.createElement("div", null, 0), React.createElement("div", null, 0), React.createElement("div", null, " 3"), React.createElement("div", null, " 3 "), React.createElement("div", null, "3"), React.createElement("div", null), React.createElement("div", null, "foo bar"), React.createElement("div", null, "hello\\ world"), React.createElement("div", null, " a b c d ");