diff --git a/lib/rules/jsx-no-useless-fragment.js b/lib/rules/jsx-no-useless-fragment.js
index 6b131a5ad2..8489aeb1bf 100644
--- a/lib/rules/jsx-no-useless-fragment.js
+++ b/lib/rules/jsx-no-useless-fragment.js
@@ -12,6 +12,13 @@ function isJSXText(node) {
return !!node && (node.type === 'JSXText' || node.type === 'Literal');
}
+/**
+ * @param {string} text
+ */
+function isOnlyWhitespace(text) {
+ return text.trim().length === 0;
+}
+
/**
* Test if node is like `_`
* @param {JSXElement} node
@@ -55,7 +62,7 @@ module.exports = {
*/
function isPaddingSpaces(node) {
return isJSXText(node) &&
- /^\s*$/.test(node.raw) &&
+ isOnlyWhitespace(node.raw) &&
node.raw.includes('\n');
}
@@ -86,7 +93,7 @@ module.exports = {
}
/**
- * Avoid fixing case like:
+ * Avoid fixing cases that involve tricky whitespaces changes like:
* ```jsx
*
* pine<>
@@ -94,6 +101,7 @@ module.exports = {
* >
*
* ```
+ * Give up fixing if one neighboring node is JSXText and is not only whitespaces
* @param {JSXElement|JSXFragment} node
* @returns {boolean}
*/
@@ -106,10 +114,14 @@ module.exports = {
const previousChild = node.parent.children[i - 1];
const nextChild = node.parent.children[i + 1];
- return (
- (!isJSXText(previousChild) || /\s$/.test(previousChild.value)) &&
- (!isJSXText(nextChild) || /^\s/.test(nextChild.value))
- );
+ if (
+ (isJSXText(previousChild) && !isOnlyWhitespace(previousChild.value)) ||
+ (isJSXText(nextChild) && !isOnlyWhitespace(nextChild.value))
+ ) {
+ return false;
+ }
+
+ return true;
}
function fix(node, fixer) {
diff --git a/tests/lib/rules/jsx-no-useless-fragment.js b/tests/lib/rules/jsx-no-useless-fragment.js
index 1dd5c84e8d..2c572d9aac 100644
--- a/tests/lib/rules/jsx-no-useless-fragment.js
+++ b/tests/lib/rules/jsx-no-useless-fragment.js
@@ -164,7 +164,7 @@ ruleTester.run('jsx-no-uselses-fragment', rule, {
},
{
code: 'a <>{""}{""}> a
',
- output: 'a {""}{""} a
',
+ output: null,
errors: [{messageId: 'ChildOfHtmlElement'}],
parser: parsers.BABEL_ESLINT
}