Skip to content

computed JSX member expression #1

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

Closed
4 tasks done
talatkuyuk opened this issue Mar 21, 2025 · 5 comments
Closed
4 tasks done

computed JSX member expression #1

talatkuyuk opened this issue Mar 21, 2025 · 5 comments
Labels
🤷 no/invalid This cannot be acted upon 👎 phase/no Post cannot or will not be acted on

Comments

@talatkuyuk
Copy link

Initial checklist

Problem

JsxMemberExpression should support computed member expression (with bracket notation) in opening tag names in jsx.

I opened an issue in facebook/jsx which explains the issue in specification.

I see that recma is super powerful more than I think. I've created a recma plugin recma-mdx-html-override to allow specific html raw elements overridable via mdx components. The only remaining gap is for the tag names with hypen like <custom-tag /> in mdx when jsx: true in the mdx options. Since the recma-mdx-html-override makes the tag callable via <_components.custom-tag />, actually should be <_components["custom-tag"] /> instead.

Current solutions

Currently, the jsxMemberExpression is:

function jsxMemberExpression(node, state) {
  this[node.object.type](node.object, state)
  state.write('.')
  this[node.property.type](node.property, state)
}

Proposed solutions

I suppose we need just to extend the JSXMemberExpression adding a computed property. Then,

function jsxMemberExpression(node, state) {
  this[node.object.type](node.object, state)
  if (!node.computed) state.write('.')
  if (node.computed) state.write('[')
  this[node.property.type](node.property, state)
  if (node.computed) state.write(']')
}

My intention was to create a custom handler for that, but compile of @mdx-js/mdx doesn't except any handler /or handlers option to be passed into recma-stringfy hence to estree-util-to-js.

@github-actions github-actions bot added 👋 phase/new Post is being triaged automatically 🤞 phase/open Post is being triaged manually and removed 👋 phase/new Post is being triaged automatically labels Mar 21, 2025
@remcohaszing
Copy link
Member

We need to emit valid JS(X). I see your point, but it’s handled correctly by MDX. The following content:

<a></a>
<a-b></a-b>

compiles to this in MDX mode:

/*@jsxRuntime automatic*/
/*@jsxImportSource react*/
function _createMdxContent(props) {
  return <><a />{"\n"}<a-b /></>;
}
export default function MDXContent(props = {}) {
  const {wrapper: MDXLayout} = props.components || ({});
  return MDXLayout ? <MDXLayout {...props}><_createMdxContent {...props} /></MDXLayout> : _createMdxContent(props);
}

or this in markdown mode (with rehype-raw):

/*@jsxRuntime automatic*/
/*@jsxImportSource react*/
function _createMdxContent(props) {
  const _components = {
    a: "a",
    "a-b": "a-b",
    p: "p",
    ...props.components
  }, _component0 = _components["a-b"];
  return <_components.p><_components.a />{"\n"}<_component0 /></_components.p>;
}
export default function MDXContent(props = {}) {
  const {wrapper: MDXLayout} = props.components || ({});
  return MDXLayout ? <MDXLayout {...props}><_createMdxContent {...props} /></MDXLayout> : _createMdxContent(props);
}

I think this shows the solution you’re after. If you want to support a custom lower case JSX tag with a custom component, you need to introduce an intermediate variable.

@talatkuyuk
Copy link
Author

talatkuyuk commented Mar 21, 2025

Thanks @remcohaszing,

I would not test the plugin recma-mdx-html-override against markdown mode! You opened my eyes:)

I've implemented intermediate variables for tag names that contain hypen in MDX mode and when jsx is true in new version of recma-mdx-html-override.

I've just realized also that html raw components are overridable by default in markdown mode via _components, but not MDX mode. I didn't catch it before. But, now I wonder why the difference exists?. Ahaa, the information comes from the Usage. Now, I understood.

This plugin takes HTML elements that refer to media content, and turns them into MDX expressions that use imports. This allows bundlers to resolve media you referenced from your code. Note that JSX elements are not HTML elements, so they are not processed. HTML elements can come from:

  • Markdown syntax in MDX files, such as images.
  • HTML in files parsed using the md format when using rehype-raw
  • Custom remark / rehype plugins.

Anyway, recma-mdx-html-override now covers it for MDX format and for jsx elements in MDX.

Nevertheless, the proposal for computed JSX member expression is still valid, it will ease the implementation of stringify and will extend the JSX specification.

compile of @mdx-js/mdx doesn't except any handler /or handlers option to be passed into recma-stringify hence to estree-util-to-js.

This is also another issue for future as recma gains power.

@remcohaszing
Copy link
Member

You can override HTML elements and JSX custom elements. In MDX you can write JSX, but not HTML. In markdown you cannot write JSX, but you can write HTML if you use rehype-raw. So in MDX you can write:

import { Component } from 'module'

<Component />

But there is no markdown equivalent.

Since the user has less control over HTML elements, whether it comes from markdown constructs or rehype plugins, it’s useful for users to customize what they look like. Note that this doesn’t just include rehype-raw, but all rehype plugins. In MDX, the user can just write JSX.

Some users like to render MDX using methods where imports can’t be resolved. For those use cases it’s useful to allow injecting custom JSX components. But for lower case JSX this is still not relevant: the user can just write the name of their custom component, so they can use for example <img /> and ` alongside each other.

As the MDX team we need to make these kind of trade-offs and we can never please everyone. Perhaps I changed your opinion, but it’s only human to disagree anyway. I really appreciate that you plugin makes things possible in MDX that aren’t possible by default 😄

As for your proposal to change JSX syntax: Personally I don’t see the need. But if your proposal does get merged into ESTree and supported by other tools, MDX should support it too.

@talatkuyuk
Copy link
Author

I really appreciate that recma-mdx-html-override makes things possible in MDX that aren’t possible by default 😄

Thank you for your appreciation, @remcohaszing.

I am closing the issue, for now.

This comment has been minimized.

@remcohaszing remcohaszing closed this as not planned Won't fix, can't repro, duplicate, stale Mar 22, 2025
@remcohaszing remcohaszing added 🤷 no/invalid This cannot be acted upon 👎 phase/no Post cannot or will not be acted on and removed 🤞 phase/open Post is being triaged manually labels Mar 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤷 no/invalid This cannot be acted upon 👎 phase/no Post cannot or will not be acted on
Development

No branches or pull requests

2 participants