@eslint-react/jsx
Advanced tools
+23
-9
@@ -218,7 +218,15 @@ import { TSESTreeJSXAttributeLike, TSESTreeJSXElementLike } from "@eslint-react/ast"; | ||
| * | ||
| * Filters out "padding spaces" — `JSXText` nodes that consist entirely of | ||
| * whitespace and contain at least one newline. These nodes are artefacts of | ||
| * source formatting that React trims away during rendering and are therefore | ||
| * not considered meaningful content. | ||
| * Filters out nodes that React will not render into the DOM: | ||
| * | ||
| * 1. "Padding spaces" — `JSXText` nodes that consist entirely of whitespace | ||
| * and contain at least one newline. These are code-formatting artefacts | ||
| * (indentation between tags). While React's client renderer preserves them | ||
| * as text nodes, browser HTML parsers may discard them during hydration, | ||
| * causing hydration mismatches. | ||
| * | ||
| * 2. Empty string expressions — `JSXExpressionContainer` nodes whose expression | ||
| * is a string literal with value `""`. React's reconciler and SSR renderer | ||
| * explicitly skip empty strings, producing no DOM node | ||
| * (see ReactChildFiber.js and ReactFizzConfigDOM.js). | ||
| * | ||
| * @param element - A `JSXElement` or `JSXFragment` node. | ||
@@ -324,9 +332,14 @@ * @returns An array of children nodes that contribute to rendered output. | ||
| * Check whether a JSX element (or fragment) has **meaningful** children — | ||
| * that is, at least one child that is not purely whitespace text. | ||
| * that is, at least one child that is not purely whitespace text or an empty | ||
| * string expression. | ||
| * | ||
| * A `JSXText` child whose `raw` content is empty after trimming is | ||
| * considered non-meaningful regardless of whether it contains a line break. | ||
| * This matches React's rendering behaviour where whitespace-only text nodes | ||
| * do not produce visible output. | ||
| * A `JSXText` child whose `raw` content is empty after trimming is considered | ||
| * non-meaningful because it is typically a code-formatting artefact | ||
| * (indentation between tags). While React's client renderer preserves these | ||
| * nodes as text nodes, they rarely represent intentionally rendered content. | ||
| * | ||
| * An empty string expression (`children={""}`) is also considered | ||
| * non-meaningful because React's reconciler and SSR renderer explicitly skip | ||
| * empty strings, producing no DOM node. | ||
| * | ||
| * @param element - A `JSXElement` or `JSXFragment` node. | ||
@@ -345,2 +358,3 @@ * @returns `true` when the element has at least one meaningful child. | ||
| * // <div></div> -> false (no children at all) | ||
| * // <div>{""}</div> -> false (empty string expression) | ||
| * | ||
@@ -347,0 +361,0 @@ * if (hasChildren(node)) { |
+64
-13
@@ -300,7 +300,15 @@ import { Extract, Traverse } from "@eslint-react/ast"; | ||
| * | ||
| * Filters out "padding spaces" — `JSXText` nodes that consist entirely of | ||
| * whitespace and contain at least one newline. These nodes are artefacts of | ||
| * source formatting that React trims away during rendering and are therefore | ||
| * not considered meaningful content. | ||
| * Filters out nodes that React will not render into the DOM: | ||
| * | ||
| * 1. "Padding spaces" — `JSXText` nodes that consist entirely of whitespace | ||
| * and contain at least one newline. These are code-formatting artefacts | ||
| * (indentation between tags). While React's client renderer preserves them | ||
| * as text nodes, browser HTML parsers may discard them during hydration, | ||
| * causing hydration mismatches. | ||
| * | ||
| * 2. Empty string expressions — `JSXExpressionContainer` nodes whose expression | ||
| * is a string literal with value `""`. React's reconciler and SSR renderer | ||
| * explicitly skip empty strings, producing no DOM node | ||
| * (see ReactChildFiber.js and ReactFizzConfigDOM.js). | ||
| * | ||
| * @param element - A `JSXElement` or `JSXFragment` node. | ||
@@ -324,3 +332,7 @@ * @returns An array of children nodes that contribute to rendered output. | ||
| function getChildren(element) { | ||
| return element.children.filter((child) => !isPaddingSpaces(child)); | ||
| return element.children.filter((child) => { | ||
| if (isPaddingSpaces(child)) return false; | ||
| if (isEmptyStringExpression$1(child)) return false; | ||
| return true; | ||
| }); | ||
| } | ||
@@ -331,4 +343,5 @@ /** | ||
| * | ||
| * These nodes are formatting artefacts (indentation between JSX tags) that | ||
| * React discards at render time. | ||
| * These nodes are code-formatting artefacts (indentation between JSX tags). | ||
| * While React's client renderer preserves them as text nodes, browser HTML | ||
| * parsers may discard them during hydration, leading to hydration mismatches. | ||
| * | ||
@@ -342,2 +355,20 @@ * @param node The JSX child node to check. | ||
| } | ||
| /** | ||
| * A `JSXExpressionContainer` node is considered an empty string expression | ||
| * when it wraps a string literal with value `""`. | ||
| * | ||
| * React's reconciler explicitly ignores empty strings | ||
| * (`typeof newChild === 'string' && newChild !== ''` in ReactChildFiber.js), | ||
| * and the SSR renderer skips them as well (`if (text === '') { return; }` | ||
| * in ReactFizzConfigDOM.js). They produce no DOM node. | ||
| * | ||
| * @param node The JSX child node to check. | ||
| * @internal | ||
| */ | ||
| function isEmptyStringExpression$1(node) { | ||
| if (node.type !== AST_NODE_TYPES.JSXExpressionContainer) return false; | ||
| const expr = node.expression; | ||
| if (expr.type !== AST_NODE_TYPES.Literal) return false; | ||
| return expr.value === ""; | ||
| } | ||
@@ -443,9 +474,14 @@ //#endregion | ||
| * Check whether a JSX element (or fragment) has **meaningful** children — | ||
| * that is, at least one child that is not purely whitespace text. | ||
| * that is, at least one child that is not purely whitespace text or an empty | ||
| * string expression. | ||
| * | ||
| * A `JSXText` child whose `raw` content is empty after trimming is | ||
| * considered non-meaningful regardless of whether it contains a line break. | ||
| * This matches React's rendering behaviour where whitespace-only text nodes | ||
| * do not produce visible output. | ||
| * A `JSXText` child whose `raw` content is empty after trimming is considered | ||
| * non-meaningful because it is typically a code-formatting artefact | ||
| * (indentation between tags). While React's client renderer preserves these | ||
| * nodes as text nodes, they rarely represent intentionally rendered content. | ||
| * | ||
| * An empty string expression (`children={""}`) is also considered | ||
| * non-meaningful because React's reconciler and SSR renderer explicitly skip | ||
| * empty strings, producing no DOM node. | ||
| * | ||
| * @param element - A `JSXElement` or `JSXFragment` node. | ||
@@ -464,2 +500,3 @@ * @returns `true` when the element has at least one meaningful child. | ||
| * // <div></div> -> false (no children at all) | ||
| * // <div>{""}</div> -> false (empty string expression) | ||
| * | ||
@@ -473,3 +510,3 @@ * if (hasChildren(node)) { | ||
| if (element.children.length === 0) return false; | ||
| return !element.children.every((child) => isWhitespaceText$1(child)); | ||
| return !element.children.every((child) => isWhitespaceText$1(child) || isEmptyStringExpression(child)); | ||
| } | ||
@@ -488,2 +525,16 @@ /** | ||
| } | ||
| /** | ||
| * Whether a JSX child node is an empty string expression (`{""}`). | ||
| * | ||
| * React's reconciler and SSR renderer skip empty strings, producing no DOM | ||
| * node. These expressions are therefore considered non-meaningful children. | ||
| * | ||
| * @param node The JSX child node to check. | ||
| */ | ||
| function isEmptyStringExpression(node) { | ||
| if (node.type !== AST_NODE_TYPES.JSXExpressionContainer) return false; | ||
| const expr = node.expression; | ||
| if (expr.type !== AST_NODE_TYPES.Literal) return false; | ||
| return expr.value === ""; | ||
| } | ||
@@ -490,0 +541,0 @@ //#endregion |
+7
-7
| { | ||
| "name": "@eslint-react/jsx", | ||
| "version": "5.8.6", | ||
| "version": "5.8.7-next.0", | ||
| "description": "ESLint React's TSESTree JSX utility module for static analysis of JSX patterns.", | ||
@@ -35,6 +35,6 @@ "homepage": "https://github.com/Rel1cx/eslint-react", | ||
| "ts-pattern": "^5.9.0", | ||
| "@eslint-react/ast": "5.8.6", | ||
| "@eslint-react/eslint": "5.8.6", | ||
| "@eslint-react/var": "5.8.6", | ||
| "@eslint-react/shared": "5.8.6" | ||
| "@eslint-react/shared": "5.8.7-next.0", | ||
| "@eslint-react/var": "5.8.7-next.0", | ||
| "@eslint-react/ast": "5.8.7-next.0", | ||
| "@eslint-react/eslint": "5.8.7-next.0" | ||
| }, | ||
@@ -45,4 +45,4 @@ "devDependencies": { | ||
| "typescript": "5.9.3", | ||
| "@local/eff": "3.0.0-beta.72", | ||
| "@local/configs": "0.0.0" | ||
| "@local/configs": "0.0.0", | ||
| "@local/eff": "3.0.0-beta.72" | ||
| }, | ||
@@ -49,0 +49,0 @@ "peerDependencies": { |
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
50159
6.31%1325
5.16%1
Infinity%4
100%+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed