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

Using whyframe in Astro with Markdown & MDX files #21

Open
paularmstrong opened this issue Mar 24, 2023 · 5 comments
Open

Using whyframe in Astro with Markdown & MDX files #21

paularmstrong opened this issue Mar 24, 2023 · 5 comments
Labels
enhancement New feature or request

Comments

@paularmstrong
Copy link

Use case: I don't want to use Storybook, but instead Astro, like storybook. I have a bunch of MDX "stories" that have components in them. However, I'm going to need them in iframes, so Whyframe seems like a great choice.

Problem:

Nothing gets written to the iframe

Is this just not possible at all? Am I doing something horribly wrong?

@bluwy
Copy link
Owner

bluwy commented Mar 26, 2023

Hey! Yeah this is not supported currently. The Astro integration only works in .astro files. For .md and .mdx, they need a remark and rehype plugin which I've not written one yet. (And I haven't look into whether it's possible)

But you can workaround this by writing the examples in components instead, and use them in MDX. Here's how I do it for the docs currently:

# @whyframe/jsx
<SolidDemo />
<PreactDemo />
<ReactDemo />
`@whyframe/jsx` exports a [Vite](https://vitejs.dev) plugin, while `@whyframe/jsx/loader` exports a [Webpack](https://webpack.js.org) loader. They share the same options below, except `include` and `exclude` being Vite specific:

Depending on the framework you use for the components, you can install the respective whyframe plugin to work too. Here's the doc's vite config:

vite: {
plugins: [
cloudflareRedirect(),
inspect(),
whyframe({
defaultSrc: '/frames/default'
}),
whyframeAstro({
defaultFramework: 'svelte'
}),
whyframeSvelte(),
whyframeVue(),
whyframeJsx()
],

It's a bit cumbersome, but I believe this should be supported one day so I'll leave this open.

@bluwy bluwy added the enhancement New feature or request label Mar 26, 2023
@paularmstrong
Copy link
Author

paularmstrong commented Mar 27, 2023

What about being able to have a JSX component that then has the iframe in it? This would be a nice workaround:

import { Example } from '@/components/Example';

# Button

<Example>
  <Button />
</Example>
import { useId } from 'react';

type Props = {
  children: React.ReactNode;
};

export function Example(props: Props) {
  return (
    <iframe title="Example" data-why>
      <div>{props.children}</div>
    </iframe>
  );
}

The resulting built component seems to have args/props stripped:

import __vite__cjsImport0_react from "/node_modules/.vite/deps/react.js?v=8dac57f3"; const useId = __vite__cjsImport0_react["useId"];
import __vite__cjsImport1_react_jsxRuntime from "/node_modules/.vite/deps/react_jsx-runtime.js?v=8dac57f3"; const _jsx = __vite__cjsImport1_react_jsxRuntime["jsx"];
import __vite__cjsImport2_react_jsxRuntime from "/node_modules/.vite/deps/react_jsx-runtime.js?v=8dac57f3"; const _Fragment = __vite__cjsImport2_react_jsxRuntime["Fragment"];
function Example() {
}
export function WhyframeApp() {
  const uid = useId();
  return /* @__PURE__ */ _jsx(_Fragment, {
    children: /* @__PURE__ */ _jsx("div", {
      children: props.children
    })
  });
}

@bluwy
Copy link
Owner

bluwy commented Mar 27, 2023

That would be similar to the abstracting components concept, but unfortunately it needs a bit more work too. Since we need to extract the <Button /> inside the <Example> as a separate virtual module, which the iframe would load that module.

Imperatively passing it to the component can't guarantee the isolation that we want, since it's created within the context of the parent in the first place, so it needs a fresh virtual module. (If that makes sense 😅)

I actually find this quite interesting to tackle, maybe I'll take a look at it this weekend. Having preliminary support for MDX would be great.

@paularmstrong
Copy link
Author

Really cool, let me know if I can help out in some way. Might take a bit to get spun up on the code, but I'm happy to assist if you've got ideas to get started.

@bluwy
Copy link
Owner

bluwy commented Apr 2, 2023

I made a prototype at https://github.com/bluwy/whyframe/tree/astro-mdx, which is a separate Vite plugin at @astrojs/astro-mdx that does very similar things to @astrojs/astro. Unfortunately, it looks like Astro's MDX completely bypasses the Vite plugin's code transformation here, so it's not working now.

I might look into fixing the core issue soon if that's possible, but another idea is to introduce a remark/rehype plugin through an Astro integration, that internally creates a Vite plugin to intercept the Vite pipeline to make transformation work. But I think this could be the last resort as it's a bit clunky to have some APIs be a Vite plugin, and an Astro integration. Plus a remark/rehype plugin that can access the Vite pipeline is also fragile.

So there's not anything you can use for now, until I find some time to continue on it 😬 If you're interested in continuing the effort, I'm happy to discuss it on Discord too if it's more convenient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants