|
| 1 | +import React, { useRef, useEffect, useState } from "react"; |
| 2 | +import * as runtime from "react/jsx-runtime.js"; |
| 3 | +import { compile, run } from "@mdx-js/mdx"; |
| 4 | +import { remarkCodeHike } from "@code-hike/mdx"; |
| 5 | +import { CH } from "@code-hike/mdx/components"; |
| 6 | +import "@code-hike/mdx/styles.css"; |
| 7 | +import { ErrorBoundary } from "react-error-boundary"; |
| 8 | + |
| 9 | +export function Preview(props) { |
| 10 | + return ( |
| 11 | + <div className="preview"> |
| 12 | + <ErrorBoundary resetKeys={[props.code]} FallbackComponent={ErrorFallback}> |
| 13 | + <InnerPreview {...props} /> |
| 14 | + </ErrorBoundary> |
| 15 | + </div> |
| 16 | + ); |
| 17 | +} |
| 18 | +function ErrorFallback({ error }) { |
| 19 | + return ( |
| 20 | + <div className="preview-error"> |
| 21 | + <p>Something went wrong:</p> |
| 22 | + <pre>{String(error)}</pre> |
| 23 | + </div> |
| 24 | + ); |
| 25 | +} |
| 26 | + |
| 27 | +function InnerPreview({ code }) { |
| 28 | + const [Content, setContent] = useState(undefined); |
| 29 | + const [error, setError] = useState(undefined); |
| 30 | + useEffect(() => { |
| 31 | + compile(code, { |
| 32 | + outputFormat: "function-body", |
| 33 | + remarkPlugins: [[remarkCodeHike, { autoImport: false }]], |
| 34 | + }) |
| 35 | + .then((c) => { |
| 36 | + return run(String(c), runtime); |
| 37 | + }) |
| 38 | + .then((x) => { |
| 39 | + setContent(() => x.default); |
| 40 | + setError(undefined); |
| 41 | + }) |
| 42 | + .catch((e) => { |
| 43 | + setError(e.message); |
| 44 | + console.error({ e }); |
| 45 | + }); |
| 46 | + }, [code]); |
| 47 | + // console.log(error); |
| 48 | + return ( |
| 49 | + <> |
| 50 | + {Content ? Content({ components: { CH } }) : null} |
| 51 | + {error ? <div className="preview-error">{error}</div> : null} |
| 52 | + </> |
| 53 | + ); |
| 54 | +} |
0 commit comments