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

creating an XDM equivelent to the MDX playground #48

Closed
Adam-Collier opened this issue Apr 23, 2021 · 7 comments
Closed

creating an XDM equivelent to the MDX playground #48

Adam-Collier opened this issue Apr 23, 2021 · 7 comments

Comments

@Adam-Collier
Copy link

Hey, so I was looking to create an MDX playground and came across the one on the main MDXjs site (https://mdxjs.com/playground/) and I wondered if it would be possible to create one using XDM. So looking at https://github.com/mdx-js/mdx/blob/5169bf1f5d7b730b6f20a5eecee0b9ea0d977e56/packages/gatsby-theme-mdx/src/components/playground-editor.js and Chris Biscardi's post https://www.christopherbiscardi.com/post/using-mdxprovider-host-elements-in-react-live-scope I thought I'd give it a go. However, I think I may be misunderstanding how to use XDM in this instance because compileSync doesn't seem to output what the transformCode prop expects. Also, I was under the impression that we didn't need to use @mdx-js/react and the MDXProvider (which the MDX examples use) to render the content but this could be wrong?

Here's some code:

import React, { useState } from 'react';
import { LiveProvider, LiveEditor, LiveError, LivePreview } from 'react-live';
import { compileSync } from 'xdm';
import './App.css';

const transformCode = (mdx) => {
  let code = compileSync(mdx);

  // I know this is wrong but I'm wondering how we correctly render this
  return `render(${code.contents})`;
};

function App(props) {
  const [code, setCode] = useState('# Hello, world!\n\n This is some markup!');

  return (
    <div className="App">
      <LiveProvider
        code={code}
        transformCode={(code) => transformCode(code)}
      >
        <LiveEditor />
        <LiveError />
        <LivePreview />
      </LiveProvider>
    </div>
  );
}

export default App;

Any help on this will be greatly appreciated and help me to understand how to use XDM more

@wooorm
Copy link
Owner

wooorm commented Apr 23, 2021

  • Why do you want an MDX live editor?
  • Why use compileSync, and not compile? This could probably be async
  • Why use compile at all, and not evaluate?
  • evaluate supports exports, and can support imports too
  • evaluate gives you a React node back — that’s what you’re looking for, right?

@Adam-Collier
Copy link
Author

Adam-Collier commented Apr 23, 2021

It's potentially going to live within a CMS so we can preview the content and save it. I tried compile rather than compileSync to begin with but LiveProvider's transformCode just seems to ignore async functions. Ahh evaluate seems more like it! So now I have:

import React, { useState } from 'react';
import * as runtime from 'react/jsx-runtime.js';
import { LiveProvider, LiveEditor, LiveError, LivePreview } from 'react-live';
import { evaluateSync } from 'xdm';

import './App.css';

function App(props) {
  const [code, setCode] = useState('# Hello, world!\n\n This is some markup!');

  return (
    <div className="App">
      <LiveProvider
        code={code}
        transformCode={(code) => {
          let { default: Content } = evaluateSync(code, {
            ...runtime,
          });
          console.log(Content);
          return String(Content);
        }}
        scope={{}}
      >
        <LiveEditor />
        <LiveError />
        <LivePreview />
      </LiveProvider>
    </div>
  );
}

export default App;

but now _jsxs is not defined so I'm assuming something needs to be added in scope?

@wooorm
Copy link
Owner

wooorm commented Apr 23, 2021

OK, getting closer.

The next thing: the package react-live is doing work that xdm is already doing.
You don’t need it at all (it’s already done).
(And in fact serializing String(Content) doesn‘t work)

The readme of react-live explains what it’s doing and using under the hood. That might help to point you in the right direction.

@wooorm
Copy link
Owner

wooorm commented Apr 23, 2021

Here’s a tiny, bad, example, of how it can be done: https://codesandbox.io/s/romantic-shannon-k1goq?file=/src/App.js.

You could use compileSync, if you really want to use react-live, it might work, but they duplicate several things: Bublé is packed at 130kb — the size of the whole of xdm.

@Adam-Collier
Copy link
Author

Thanks for sending over the example, it made sense after looking at it that react-live isn't needed when it handles so much of it itself. I've managed to get something working with async here: https://github.com/Adam-Collier/vite-mdx-playground/tree/evaluate_async however there are a couple of problems I'm coming across when it comes to handling errors. For example if I was to do something like <Row>some content here</Row> (where Row isn't imported) the error bounces back to the Error Boundary rather than being handled in the try catch and gets logged to the console as an uncaught error. But if I remove the try catch and just start writing an opening tag < the error isn't caught by the ErrorBoundary and goes straight to console (I think this is promise related and the Error Boundary doesn't handle those cases). So I'm wondering if there is a way of handling the errors that I may be missing here? so they are caught and shown in the UI rather than logging to the console

@wooorm
Copy link
Owner

wooorm commented Apr 27, 2021

@wooorm
Copy link
Owner

wooorm commented May 7, 2021

Closing this for now. I think it has garnered enough conversation to be useful for future readers. Feel free to comment with more Qs tho!

@wooorm wooorm closed this as completed May 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants