mdx-js / mdx

Markdown for the component era
https://mdxjs.com
MIT License
17.43k stars 1.14k forks source link

New keyword for non-exported ES syntax #713

Closed axdg closed 4 years ago

axdg commented 5 years ago

Problem

Currently (please correct me if I'm wrong), the only way to include JS syntax inside an MDX file is to preface that code with either the import or export keywords - and as such, to use their functionality. What if we don't need that functionality?

If I want to declare variables in my MDX, I have to use export const = <my_variable>, this is true even when I don't want to / shouldn't export that variable.

My typical usecase for local (to the file) variables would be to declare props that I can later pass as props, or to define JSX components (that wouldn't be used outside of the file).

Suggestion

Why not include an extra keyword that can preface JS statements / blocks? I would suggest embed or inline.

This is what that might look like;

// NOTE: This is exported.
export const ExportedComponent = ({ text }) => <p>{text}</p>

// NOTE: This is local.
embed const LocalComponent = ({ text }) => <p>{text}</p>

I've taken a quick look at the implementation of remark-mdx, and it looks like this would be quite trivial to add there... the compiler would just need a new handler, which would be no different to the import or export handlers (although it would strip the embed || inline keyword) - happy to PR.

Alternatives

The excellent idea of inlining fenced code blocks (proposed in #701) could do the same thing (allowing non exported JS statements) - I'd love it if both were implemented and the user was able to choose.

johno commented 5 years ago

Rather than introducing a new keyword I kind of lean towards what's proposed in #701 since it introduces one more bit of API surface area that can be a viable escape hatch for all of these (understandable) needs for additional JS syntax.

Though, for something like variable declarations this won't exactly work as proposed in #701 since we'd have to differentiate where the contents of the inline/eval-ed code block would be embedded since imports/exports/variable declarations would need to live outside the component while JSX syntax would need to be embedded where it is.

johno commented 4 years ago

I'm going to go ahead and close this since #701 and an RFC for local vars (#1046) has been opened. The latter has been directly inspired by this issue, thank you for opening @axdg!