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

MDX support including components and data #20

Closed
6 tasks done
rufuspollock opened this issue Jul 5, 2022 · 17 comments · Fixed by #89
Closed
6 tasks done

MDX support including components and data #20

rufuspollock opened this issue Jul 5, 2022 · 17 comments · Fixed by #89
Assignees
Labels
enhancement New feature or request Roadmap

Comments

@rufuspollock
Copy link
Member

rufuspollock commented Jul 5, 2022

To make richer markdown pages we want MDX and be able to use components and data in the page e.g.

import MyComponent from '@components/MyComponent'

const orgs = [ 'abc' ]

# Hello world

Acceptance

  • Research if we really can import components and hero - see [Rufus comment below] ✅ 2022-08-22 (olayway:) yes, we can(MDX support including components and data #20 (comment))
    • Report on whether it works or not by trying out a demo in our case (key will probably be getting import path right) ✅ 2022-08-22 (olayway:) currently you can see it working here

BONUS: find out if contentlayer supports direct imports in the MDX file e.g.

import MyComponent from '@components/MyComponent'

# Hello world

🚫 tried but not working and could not find, but next-mdx-remote does so I may be missing something ? ✅ 2022-08-22 (olayway:) yes, tested and works -> Contentlayer supports MDX and ESM import/export statements are part of MDX standard syntax, currently you can see it working here

Tasks

  • [ ] Demo page of component with props @ /demo 2022-08-11 (olayway:) we're no longer using demo pages
  • Documentation at notes/howto-use-components-in-your-markdown 🚧 2022-08-11 (olayway:) 80% done; my idea is to put it in /docs/mdx cuz I'm adding a bit context about MDX + it will include sections about: 1) how you can import custom components 2) how you can define components within markdown file (no importing) 3) how you can import data 4) how you can define data(variables) directly in your markdown | 2022-08-15 done in PR Docs page on using custom components and data (and more broadly MDX) #89

Using components

https://github.com/contentlayerdev/website/blob/main/src/pages/docs/%5B%5B...slug%5D%5D.tsx

Options:

  • 🚫 add component in components/MDX.js and use it in markdown eg. <MyComponent /> 2022-08-11 (olayway:) no, you don't have to do that, but of course, you can - e.g. for the component you use across a lot of your md files so it makes sense to make them available globally
  • import components directly in mdx not working. (tried with .mdx file too) 2022-08-11 (olayway:) works but you have to change React components' file extension from .js to .jsx (for reference, see comments from Contentlayer team on the issue we've submitted)

Passing props

Can pass arguments to MDX renderer and access as props? ✅ YES

❕2022-08-11 (olayway:) You can also define data directly in your markdown files or import them from JSON file into your markdown files and then pass it as props to your components

Add as global props ...

// in pages/[[...slug]].js

...
const Component = useMDXComponent(body.code, { globalProps })
...

See https://spectrum.chat/mdx/general/resolved-how-to-use-props-or-variables-with-mdx-files~3cd95635-1d93-440e-9802-7571cacfd578 - gatsbyjs/gatsby#17551

@olayway olayway added documentation Improvements or additions to documentation enhancement New feature or request and removed documentation Improvements or additions to documentation labels Jul 5, 2022
@rufuspollock
Copy link
Member Author

@khalilcodes it's a pretty big issue that we have to modify [[...slug]].js to pass data in. Are you absolutely sure there is no other option and could you document your research here in a bit of detail.

@rufuspollock
Copy link
Member Author

@khalilcodes also if this is complete can you move to in review in board?

@rufuspollock
Copy link
Member Author

rufuspollock commented Jul 11, 2022

Based on further research into contentlayer it does look like you are supposed to be able to import components and assets. The key point is the that import directory is set to contentDirPath i.e. content in our case. See contentlayerdev/contentlayer#8 and contentlayerdev/contentlayer#11 and especially contentlayerdev/contentlayer#266

Upon investigating, I found that the cwd given to mdx-bundler is the same as contentDirPath. However, if the MDX file is deeply nested, resolving images and components in the same directory will not work. For example if contentDirPath is /content, but the MDX file is under /content/some-subdir/some-post/index.mdx, any references in the MDX file will be looked in /content.

More precisely: if the MDX file references or import Component from './Component, those files will try to be resolved from /content, and not /content/some-subdir/some-post where they actually are.

@olayway
Copy link
Member

olayway commented Jul 14, 2022

@rufuspollock, @khalilcodes I've just tested another way to pass data to components, that doesn't require modifications to [[...slug].js by the user and enables per-page data passing. This was just a quick test, so I wouldn't consider it ready to merge, but please take a look: #32

@rufuspollock
Copy link
Member Author

@olayway

  • 👏 for having a go … (and great PR summary). And it is a good approach
  • What’s good: creates a level of indirection/separate that we can store data in
  • And … I think it would be useful to propose a solution and discuss before we go ahead to avoid wasted effort and find the best approach (E.g. we can discuss pros and cons of a given approach)
  • My question here would be things like
  • this seems similar to config and we already have userConfig.js so couldn't we just use that (if we went with this approach)
  • More generally, i'm not sure i want page content ending up in a special js/json file. Best would be if this data can be in the MDX page (or imported there) somehow. Why? Because it is one place for all that stuff so easier to reason about and understand. Plus we leverage the MDX ecosystem rather than building something new (and people are familiar with MDX)

Overall, the next step here is some more research on MDX based approach

@khalilcodes
Copy link
Contributor

@rufuspollock @olayway

when importing a component in md, it throws an error - unexpected "<"

For example the import statement as below:

import { Button } from "../components/Button"

gives the following error:

 > ../../templates/default/components/Button.js:14:4: error: Unexpected "<"
    14 │     <Link href={href}>
       ╵     ^

Error: Found 1 problems in 1 documents.

 └── Encountered unexpected errors while processing of 1 documents. This is possibly a bug in Contentlayer. Please open an issue.

     • "index.md": UnexpectedMDXError: Error: Build failed with 1 error:
     ../../templates/default/components/Button.js:14:4: error: Unexpected "<"


SourceFetchDataError: {
  "_tag": "HandledFetchDataError"
}

Further investigation

If the return statement of the component is a string, then it renders without any errors.

for example if the following is the component:

export function Button () {
  return "This is a button component"
}

and we import it in md like below:

Screen Shot 2022-07-20 at 5 08 58 PM

The result is as follows:

Screen Shot 2022-07-20 at 5 08 09 PM

@rufuspollock
Copy link
Member Author

@khalilcodes this looks like something on contentlayer - have you opened an issue yet in their issue tracker? That's the quickest way i think to get insight here. The issue would be something like:

"How do import contents and data into my mdx documents"

You should reference other relevant issues to indicate you have read them and made an effort to "read the docs" before asking. Then someone will likely answer even if to point to an existing issue.

@khalilcodes
Copy link
Contributor

khalilcodes commented Jul 22, 2022

As per the suggestion i've opened an issue: contentlayerdev/contentlayer#273 yesterday. No response yet.

@rufuspollock
Copy link
Member Author

@khalilcodes as next step can we commit two test pages (can be in site/content) showing it working and not working as per your notes with some sample component in the /site/components/

@khalilcodes
Copy link
Contributor

@rufuspollock would it be best if we commit these to a separate branch ?

@rufuspollock
Copy link
Member Author

@khalilcodes don't think it is worth it and it would be good to have them deployed. Just put them in e.g. /test/{some name}

@khalilcodes
Copy link
Contributor

@rufuspollock added the test commits and commented on the issue with steps to reproduce.

@khalilcodes
Copy link
Contributor

khalilcodes commented Aug 8, 2022

@rufuspollock based on the comment in the open issue, it has been suggested that the issue lies in our project setup and to rather use .jsx or .tsx extensions instead (tried). I will test out a new bare project (ie., without any symlinks etc) and see if this is the case.

@rufuspollock
Copy link
Member Author

Can you wait for me to review before we do another trial.

@olayway
Copy link
Member

olayway commented Aug 10, 2022

@rufuspollock, @khalilcodes I couldn't resist trying out (¯_(ツ)_/¯ 😄) so I'll share what I've found out

  1. Changing files extension from .js to .jsx does seem to work. You can see a flash of the button on the page, but another error pops up:

image

  1. I've created a separate testing page page-3 to see if the problem will persist if we import other components than Button.jsx, that don't include Next.js Link (I suspect this may be the cause of an error).
    Here I'm importing a Test2.jsx component, which has a child Test.jsx and uses some basic props. And it works just fine:

See: https://flowershow.app/test/page-3

image

@olayway olayway self-assigned this Aug 11, 2022
@olayway
Copy link
Member

olayway commented Aug 11, 2022

@rufuspollock, @khalilcodes I've added a bunch of comments to the issue description. Please take a look.

@olayway
Copy link
Member

olayway commented Aug 11, 2022

I'm also almost done with creating a doc page so I'm not writing everything I've found while researching and testing MDX capabilities here. But basically importing custom components/data, defining custom components/data(variables) locally (directly within markdown), passing it then by props or evaluating JS expressions - all works. I'll submit a PR tomorrow.

@khalilcodes khalilcodes mentioned this issue Sep 6, 2022
44 tasks
@rufuspollock rufuspollock changed the title MDX try-out and tutorial with components and data MDX support including components and data Dec 3, 2022
rufuspollock pushed a commit to rufuspollock/flowershow that referenced this issue Oct 27, 2023
nyejon pushed a commit to nyejon/flowershow_blog that referenced this issue Nov 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Roadmap
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants