-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Use babel-parse for import/export/jsx blocks #345
Comments
I really like this idea because that way we can finally gain the much needed stability. I brought it up before, but a concern for performance was raised, so I'm glad to see interest in it again. Other than the scenarios in your list, I wonder if we could also solve parsing inline JSX with this approach. (#222) My FUD is that we have to parse the content with two different parsers that are mutually incompatible, I'm not sure know how we can combine them in a stable way. E.g. if we're trying to solve the issue with newlines, how do we know how many lines to parse with Babel until we start parsing with remark again? |
Similarly to how we're extending the block parser currently, we'll be able to continue doing the same thing.
My first naive approach might be to continue walking the document until the babel parser doesn't error. When that occurs we know we either have a completed JSX block or we've reached the end of the document and there's a syntax error. This will become less of an issue after micromark, but that's in its very early stages so we can't really wait on it when we can get this stable now. Swapping out remark for micromark down the road won't require an API change for the end user. |
That's a great idea, we can split the file content based on two or more consecutive newlines and keep adding those chunks until we don't get an error. Works for me! |
Hey @johno I wrote an mdx-to-mdx-ast package here: https://github.com/devular/mdx-to-mdx-ast It uses the Acorn JS parser that powers babel to verify nodes are I'm not sure if it's of any use to you, I mostly wrote it for fun and to learn a bit about the MDX spec and ASTs. Thanks for all your work on MDX, there's so many opportunities around content authoring, an amazing library. 🙏 |
(Oh yes - I'd be happy to take this on, if people want to give me examples of:
or any other case the mdx-ast generator should handle. |
@silvenon @johno I remember @ChristopherBiscardi tweeting somewhere that neither babel nor |
This is amazing @jonsherrard! We'd love for you to take this on if you're interested. Perhaps you could coordinate a bit with @wooorm on how to merge work into
😞. I imagine that means we need to walk the AST to ensure that the JSX block is closed then? Even if it doesn't complain we can ensure that the block is closed/self-closing. |
This evening I can start a branch with failing tests that we can use for you to dev against. But for now, here are a few off the top of my head: 1. parsing out exportsThe following breaks because we don't find the export since we expect an empty newline before the export. import Foo from './bar'
export default Foo 2. allowing other types of exportsWe currently error when encountering exports like this, but we should really handle them properly: export { default } from './foo' 3. empty lines in JSX blocksThe following won't properly parse because of the empty line before the <Component>
{renderProps => {
const data = doStuffWith(renderProps)
return (
<Graph data={data} />
)
}
</Component> 4. JSX blocks that contain numbers are ignored<Component2 /> Related issues
|
Cheers!
Bonus. Supports variable declaration named exports as well: #341 export const meta = {
title: "Testing 123",
description: "This is a default description"
}; On bundlesize: Bundlephobia reports 95kb for Acorn and Acorn-JSX 🤔 |
@wooorm @johno Probably referring to these tests: ChristopherBiscardi/gatsby-mdx@97c4e36 where I was having trouble figuring out which combination of rehype, babel, etc would fail for different combinations of content with the intent of figuring out a way to differentiate jsx from html and convert html to jsx. If you look at the PR I switched to an approach that just touches attributes and handles capitalization/to-object on styles though babel after the entire mdx process runs rather than try to run on segments of code inside the AST. Not sure any of that will help here |
Update so far, I'm still in the playground phase over at: https://github.com/devular/mdx-to-mdx-ast
Remark
import Foo from './foo'
export default foo as a single MDAST node. Acorn
So now we have two solid solutions: -> Acorn parsing of strings to a JS AST You can see this handled here: https://github.com/devular/mdx-to-mdx-ast/blob/master/handle-multi-program-nodes.js ReservationsUsing https://github.com/zeit/ncc, the bundle is a whopping 287kb, now that we've added I'd like to use this in the browser at some point... that's pretty huge - but I was thinking for a CMS - slightly more palatable. There's now a lot going in here JS parsing, and JS codegen, Markdown parsing, and remark,rehype plugin execution.... it feels like a lot, but that's maybe how robust it needs to be. |
* Improve import and export parsing with babel This introduces babel for better handling import and export parsing. Anything that is an import/export block will be parsed by babel and split up ensuring that edge cases will no longer occur based on how the JS is grouped. It also makes parsing the export default nodes more robust. - #345 - #340 * Add multiline fixtures * Preserve positional information for AST nodes In order to maintain positional metadata for AST nodes that are parsed, we need to ensure that each import/export is eaten in order as a correct subvalue. Since the remark eat function requires the string to be consumed in order, with no missing characters, the babel plugin now returns the start value which is used to sort the nodes and partition the input string. They're then combined again and returned as nodes that can be eaten in order by the tokenizer. This also comes with the benefit of no longer changing the input code which occurs with the prior babel generator. * Remove unneeded babel generator dep * Simplify partition function * Make naming consistent * Add snapshot test to verify positional info
* Improve import and export parsing with babel This introduces babel for better handling import and export parsing. Anything that is an import/export block will be parsed by babel and split up ensuring that edge cases will no longer occur based on how the JS is grouped. It also makes parsing the export default nodes more robust. - #345 - #340 * Add multiline fixtures * Preserve positional information for AST nodes In order to maintain positional metadata for AST nodes that are parsed, we need to ensure that each import/export is eaten in order as a correct subvalue. Since the remark eat function requires the string to be consumed in order, with no missing characters, the babel plugin now returns the start value which is used to sort the nodes and partition the input string. They're then combined again and returned as nodes that can be eaten in order by the tokenizer. This also comes with the benefit of no longer changing the input code which occurs with the prior babel generator. * Remove unneeded babel generator dep * Simplify partition function * Make naming consistent * Add snapshot test to verify positional info
import/export parsing have landed in the alpha release so we can track block parsing in #195 |
This issue is intended to discuss bringing in @babel/parse to handle ES/JSX parsing.
I've discussed this a few times with @timneutkens and @ChristopherBiscardi in passing but it's something we haven't been prioritizing. Over the last week I've been thinking about it more heavily after @jescalan reported a bunch of new parse issues.
We've reached a point where most open issues with the bug label are related to parsing exports and JSX. So we ultimately need to be able to parse import/export/jsx nodes to handle the following scenarios:
default
export since that maps to the layoutThere might be a small performance hit, but since it's build time it's not something I'm personally worried about. The big bummer will be the heavier bundle, but that really only comes into play for browser runtimes (which isn't really our targeted env anyway).
The text was updated successfully, but these errors were encountered: