Skip to content

fix: preserve whitespace around empty JSX expressions - #4032

Open
raisulchowdhury wants to merge 4 commits into
jsx-eslint:masterfrom
raisulchowdhury:codex-3995-preserve-jsx-whitespace
Open

fix: preserve whitespace around empty JSX expressions#4032
raisulchowdhury wants to merge 4 commits into
jsx-eslint:masterfrom
raisulchowdhury:codex-3995-preserve-jsx-whitespace

Conversation

@raisulchowdhury

Copy link
Copy Markdown

Summary

  • Preserve an empty JSX expression when removing it would change whitespace across a multiline JSX boundary.
  • Keep the existing removal behavior for inline empty expressions where no rendered whitespace is lost.
  • Add the reported regression and a safe inline control case.

Fixes #3995.

Validation

  • npx mocha tests/lib/rules/jsx-curly-brace-presence.js --grep 'The braces' (2 passing)
  • Direct ESLint Linter verification of the reported case and inline control
  • npx eslint lib/rules/jsx-curly-brace-presence.js tests/lib/rules/jsx-curly-brace-presence.js (0 errors; 7 pre-existing warnings in the test file)
  • git diff --check

The full legacy parser matrix is not a reliable signal in this environment because its TypeScript 3.9 parser stack is incompatible with the installed Node 25 runtime; the focused rule tests and direct behavior checks pass.

Assisted-by: OpenAI Codex. The contributor reviewed the implementation and validation before publication.

Do not remove an empty JSX expression when the surrounding multiline text and JSX elements rely on it to preserve rendered whitespace. Add the reported regression and a safe inline control.

Assisted-by: OpenAI Codex
Signed-off-by: raisulchowdhury <34920788+raisulchowdhury@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 1, 2026 15:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@haimuhaimu haimuhaimu left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whitespace-preservation guard misses the equivalent empty no-substitution template literal case.

I reproduced this on head 178859e73e3c81165b73696a363e00fa9f314ed6 with ESLint 9.39.5 and verifyAndFix:

<span>
  <span>The braces</span>
  {``} matter here.
</span>

The rule still reports/fixes the empty template expression and produces:

<span>
  <span>The braces</span>
   matter here.
</span>

That is the same whitespace-sensitive output shape as #3995. lintUnnecessaryCurly explicitly handles a TemplateLiteral with zero expressions and the fixer replaces it with its empty cooked value, but isEmptyStringExpression only checks child.expression.value === ""; a TemplateLiteral has no value, so the new bailout never runs.

Could isEmptyStringExpression also recognize a zero-expression template whose sole quasi has an empty cooked/raw value? A multiline valid regression using {``} plus the existing safe inline invalid/control case would cover both branches.

@haimuhaimu haimuhaimu left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified the follow-up on d0a5dedeff02e86ba09b089e877e192c4f292a82 with ESLint 9.39.4. The multiline empty-template reproducer now remains unchanged with no diagnostic, the inline control still fixes to plain text, and the existing empty-string multiline case remains protected. The added regression file is included by the project unit-test glob, and all four reported checks pass. My previous concern is resolved; thanks for covering both branches.

@haimuhaimu haimuhaimu left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-verified the latest head 3e26b04c39cde640062ec5719434abf488f2cf74, including the new no-children guard added after my previous approval. With ESLint 9.39.4, the JSX attribute control now fixes <App prop={foo} /> to <App prop="foo" /> without throwing; the multiline empty-template and empty-string cases remain protected, and the inline template control still fixes normally. All four reported checks pass. This approval covers the current head.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: jsx-curly-brace-presence incorrectly removes {""} used for whitespace preservation

4 participants