diff --git a/packages/babel-generator/src/generators/jsx.js b/packages/babel-generator/src/generators/jsx.js
index 521b479ae0..32db95c327 100644
--- a/packages/babel-generator/src/generators/jsx.js
+++ b/packages/babel-generator/src/generators/jsx.js
@@ -43,7 +43,13 @@ export function JSXSpreadChild(node: Object) {
}
export function JSXText(node: Object) {
- this.token(node.value);
+ const raw = this.getPossibleRaw(node);
+
+ if (raw != null) {
+ this.token(raw);
+ } else {
+ this.token(node.value);
+ }
}
export function JSXElement(node: Object) {
diff --git a/packages/babel-generator/test/fixtures/types/XJSAttribute/actual.js b/packages/babel-generator/test/fixtures/types/XJSAttribute/actual.js
index ff8711dc2f..4243c8a6d1 100644
--- a/packages/babel-generator/test/fixtures/types/XJSAttribute/actual.js
+++ b/packages/babel-generator/test/fixtures/types/XJSAttribute/actual.js
@@ -5,3 +5,7 @@
;
text
;
+
+;
+;
+;
diff --git a/packages/babel-generator/test/fixtures/types/XJSAttribute/expected.js b/packages/babel-generator/test/fixtures/types/XJSAttribute/expected.js
index ff8711dc2f..4243c8a6d1 100644
--- a/packages/babel-generator/test/fixtures/types/XJSAttribute/expected.js
+++ b/packages/babel-generator/test/fixtures/types/XJSAttribute/expected.js
@@ -5,3 +5,7 @@
;
text
;
+
+;
+;
+;
diff --git a/packages/babel-generator/test/fixtures/types/XJSText/actual.js b/packages/babel-generator/test/fixtures/types/XJSText/actual.js
new file mode 100644
index 0000000000..2104766109
--- /dev/null
+++ b/packages/babel-generator/test/fixtures/types/XJSText/actual.js
@@ -0,0 +1,12 @@
+wow
;
+wôw
;
+
+w & w
;
+w & w
;
+
+w w
;
+this should not parse as unicode: \u00a0
;
+this should parse as nbsp:
;
+this should parse as unicode: {'\u00a0 '}
;
+
+w < w
;
diff --git a/packages/babel-generator/test/fixtures/types/XJSText/expected.js b/packages/babel-generator/test/fixtures/types/XJSText/expected.js
new file mode 100644
index 0000000000..2104766109
--- /dev/null
+++ b/packages/babel-generator/test/fixtures/types/XJSText/expected.js
@@ -0,0 +1,12 @@
+wow
;
+wôw
;
+
+w & w
;
+w & w
;
+
+w w
;
+this should not parse as unicode: \u00a0
;
+this should parse as nbsp:
;
+this should parse as unicode: {'\u00a0 '}
;
+
+w < w
;
diff --git a/packages/babel-helper-builder-react-jsx/src/index.js b/packages/babel-helper-builder-react-jsx/src/index.js
index 13d205fd4b..fb495d1c88 100644
--- a/packages/babel-helper-builder-react-jsx/src/index.js
+++ b/packages/babel-helper-builder-react-jsx/src/index.js
@@ -65,6 +65,11 @@ export default function (opts) {
if (t.isStringLiteral(value) && !t.isJSXExpressionContainer(node.value)) {
value.value = value.value.replace(/\n\s+/g, " ");
+
+ // "raw" JSXText should not be used from a StringLiteral because it needs to be escaped.
+ if (value.extra && value.extra.raw) {
+ delete value.extra.raw;
+ }
}
if (t.isValidIdentifier(node.name.name)) {
diff --git a/packages/babel-plugin-transform-react-jsx/test/fixtures/react/should-escape-xhtml-jsxattribute/actual.js b/packages/babel-plugin-transform-react-jsx/test/fixtures/react/should-escape-xhtml-jsxattribute/actual.js
new file mode 100644
index 0000000000..addae3b9f8
--- /dev/null
+++ b/packages/babel-plugin-transform-react-jsx/test/fixtures/react/should-escape-xhtml-jsxattribute/actual.js
@@ -0,0 +1,3 @@
+;
+;
+;
diff --git a/packages/babel-plugin-transform-react-jsx/test/fixtures/react/should-escape-xhtml-jsxattribute/expected.js b/packages/babel-plugin-transform-react-jsx/test/fixtures/react/should-escape-xhtml-jsxattribute/expected.js
new file mode 100644
index 0000000000..be7bcc32a3
--- /dev/null
+++ b/packages/babel-plugin-transform-react-jsx/test/fixtures/react/should-escape-xhtml-jsxattribute/expected.js
@@ -0,0 +1,3 @@
+React.createElement("div", { id: "w\xF4w" });
+React.createElement("div", { id: "\\w" });
+React.createElement("div", { id: "w < w" });
diff --git a/packages/babel-plugin-transform-react-jsx/test/fixtures/react/should-escape-xhtml-jsxtext/actual.js b/packages/babel-plugin-transform-react-jsx/test/fixtures/react/should-escape-xhtml-jsxtext/actual.js
new file mode 100644
index 0000000000..2104766109
--- /dev/null
+++ b/packages/babel-plugin-transform-react-jsx/test/fixtures/react/should-escape-xhtml-jsxtext/actual.js
@@ -0,0 +1,12 @@
+wow
;
+wôw
;
+
+w & w
;
+w & w
;
+
+w w
;
+this should not parse as unicode: \u00a0
;
+this should parse as nbsp:
;
+this should parse as unicode: {'\u00a0 '}
;
+
+w < w
;
diff --git a/packages/babel-plugin-transform-react-jsx/test/fixtures/react/should-escape-xhtml-jsxtext/expected.js b/packages/babel-plugin-transform-react-jsx/test/fixtures/react/should-escape-xhtml-jsxtext/expected.js
new file mode 100644
index 0000000000..68835afba9
--- /dev/null
+++ b/packages/babel-plugin-transform-react-jsx/test/fixtures/react/should-escape-xhtml-jsxtext/expected.js
@@ -0,0 +1,50 @@
+React.createElement(
+ 'div',
+ null,
+ 'wow'
+);
+React.createElement(
+ 'div',
+ null,
+ 'w\xF4w'
+);
+
+React.createElement(
+ 'div',
+ null,
+ 'w & w'
+);
+React.createElement(
+ 'div',
+ null,
+ 'w & w'
+);
+
+React.createElement(
+ 'div',
+ null,
+ 'w \xA0 w'
+);
+React.createElement(
+ 'div',
+ null,
+ 'this should not parse as unicode: \\u00a0'
+);
+React.createElement(
+ 'div',
+ null,
+ 'this should parse as nbsp: \xA0 '
+);
+React.createElement(
+ 'div',
+ null,
+ 'this should parse as unicode: ',
+ '\u00a0 '
+);
+
+React.createElement(
+ 'div',
+ null,
+ 'w < w'
+);
+