computed JSX member expression
Closed this issue · 5 comments
Initial checklist
- I read the support docs
- I read the contributing guide
- I agree to follow the code of conduct
- I searched issues and discussions and couldn’t find anything (or linked relevant results below)
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.
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.
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.
compileof@mdx-js/mdxdoesn't except anyhandler/orhandlersoption to be passed intorecma-stringifyhence toestree-util-to-js.
This is also another issue for future as recma gains power.
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.
I really appreciate that
recma-mdx-html-overridemakes things possible in MDX that aren’t possible by default 😄
Thank you for your appreciation, @remcohaszing.
I am closing the issue, for now.
Hi! This was closed. Team: If this was fixed, please add phase/solved. Otherwise, please add one of the no/* labels.