Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSX emitter trims some text too eagerly #57298

Closed
Jym77 opened this issue Feb 5, 2024 · 4 comments
Closed

JSX emitter trims some text too eagerly #57298

Jym77 opened this issue Feb 5, 2024 · 4 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@Jym77
Copy link

Jym77 commented Feb 5, 2024

πŸ”Ž Search Terms

Typescript JSX trimming text

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried (3.3.3 and 5.3.3), and I reviewed the FAQ for entries about "JSX": only entry which seems unrelated.

⏯ Playground Link

https://www.typescriptlang.org/play?jsx=4&ts=5.3.3#code/MYewdgzgLgBAZiEMC8MAUAoGMA8AjAVyinAD4ttcIAHAQzFIBsQAnAUwFscB6G+8yvEQVsOPgwCW1CAS686DCj0LEyGAJQBuDBlCRYeWixTolKkosFiFTVpx7jSCENf5SZcx0u7m1WoA

πŸ’» Code

const foo = (
  <button>
    <span>lorem</span>
    foo
    <span>ipsum</span>
  </button>
);

const bar = (
  <button>
    <span>lorem</span>foo<span>ipsum</span>
  </button>
);

πŸ™ Actual behavior

With "jsx": "react-jsx", both variables get emitted in the .js file as:

const foo = (_jsxs("button", { children: [_jsx("span", { children: "lorem" }), "foo", _jsx("span", { children: "ipsum" })] }));
const bar = (_jsxs("button", { children: [_jsx("span", { children: "lorem" }), "foo", _jsx("span", { children: "ipsum" })] }));

Notably, the "foo" part is identical.
Similar behaviour happens for react-jsxdev and react (other emitters do not actually change the JSX).

πŸ™‚ Expected behavior

Given that the two HTML elements:

<button>
  <span>lorem</span>
  foo
  <span>ipsum</span>
</button>

<button>
  <span>lorem</span>foo<span>ipsum</span>
</button>

appear differently if used in an HTML file and rendered (the first one has spaces around the foo part of its text, the second doesn't), Iβ€―would expect the emitted code to be different also.
I can of course force spaces in the emitted code by using {" foo" } instead of foo, but that is somewhat contrived and make it harder to simply copy/paste HTML code into a JSX element.

Additional information about the issue

No response

@nmain
Copy link

nmain commented Feb 5, 2024

The current behavior is correct. The JSX specification does not trim whitespace in the same manner that HTML does; it's much more aggressive. You can often copy true HTML and paste it as JSX and get something that is pretty close to correct, but it's not guaranteed to be identical in behavior and this is one instance where they differ.

@nmain
Copy link

nmain commented Feb 5, 2024

Also see facebook/jsx#6 and linked issues from it. Note that Babel and other JSX transpilers behave the same as Typescript does here.

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Feb 5, 2024
@RyanCavanaugh
Copy link
Member

This matches all other JSX-for-React implementations. If you have a JSX variant that cares about leading whitespace, you'll need to use jsx: "preserve" and downlevel it using a variant-specific transpiler.

@Jym77
Copy link
Author

Jym77 commented Feb 6, 2024

Thanks for the answers and the pointer. I'm closing this, I guess this is more of an HTML poor design πŸ˜…

My use-case was to parse some strings containing HTML to extract it into JSX. I guess I'll have to make my parser a bit more clever…

@Jym77 Jym77 closed this as completed Feb 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

3 participants