diff --git a/lib/core.mjs b/lib/core.mjs index e6cf064..072195b 100644 --- a/lib/core.mjs +++ b/lib/core.mjs @@ -4,7 +4,6 @@ import { transform } from 'sucrase' import { init, parse } from 'es-module-lexer' let esModuleLexerInit - const isRelative = s => s.startsWith('./') function transformCode(_code, getModuleUrl, externals) { @@ -25,13 +24,11 @@ function replaceImports(source, getModuleUrl, externals) { // start, end, statementStart, statementEnd, assertion, name imports.forEach(({ s, e, ss, se, a, n }) => { - let isCss = false code += source.slice(lastIndex, ss) // content from last import to beginning of this line // handle imports if (n.endsWith('.css')) { - isCss = true // Map './styles.css' -> '@styles.css', and collect it const cssPath = `${'@' + n.slice(2)}` cssImports.push(cssPath) @@ -85,12 +82,12 @@ function createRenderer(createModule_, getModuleUrl) { async function render(files) { const mod = await createModule_(files, { getModuleUrl }) - const React_ = await self.importShim('react') - const ReactDOM_ = await self.importShim('react-dom') + const ReactMod = await self.importShim('react') + const ReactDOMMod = await self.importShim('react-dom') - const _jsx = React_.createElement - const root = document.getElementById('root') - class ErrorBoundary extends React_.Component { + const _jsx = ReactMod.createElement + const root = document.getElementById('__reactRoot') + class ErrorBoundary extends ReactMod.Component { constructor(props) { super(props) this.state = { error: null } @@ -106,16 +103,16 @@ function createRenderer(createModule_, getModuleUrl) { } } - const isReact18 = !!ReactDOM_.createRoot + const isReact18 = !!ReactDOMMod.createRoot if (isReact18 && !reactRoot) { - reactRoot = ReactDOM_.createRoot(root) + reactRoot = ReactDOMMod.createRoot(root) } const Component = mod.default const element = _jsx(ErrorBoundary, null, _jsx(Component)) if (isReact18) { reactRoot.render(element) } else { - ReactDOM_.render(element, root) + ReactDOMMod.render(element, root) } } @@ -123,8 +120,8 @@ function createRenderer(createModule_, getModuleUrl) { } function createMainScript({ uid }) { - const code = ( -`'use strict'; + const code = (`\ +'use strict'; const _createModule = ${createModule.toString()}; const _createRenderer = ${createRenderer.toString()}; @@ -137,21 +134,27 @@ globalThis.__render__ = _createRenderer(_createModule, getModuleUrl); } function createEsShimOptionsScript() { - return `window.esmsInitOptions = { - polyfillEnable: ['css-modules', 'json-modules'], - onerror: error => console.log(error), - }` + return `\ +window.esmsInitOptions = { + polyfillEnable: ['css-modules', 'json-modules'], + onerror: error => console.log(error), +}` } function useScript() { return useRef(typeof window !== 'undefined' ? document.createElement('script') : null) } -function setScript(scriptRef, scriptContent, { type } = {}) { +function createScript(scriptRef, { content, src, type } = {}) { const script = scriptRef.current if (type) script.type = type - script.src = `data:text/javascript;utf-8,${encodeURIComponent(scriptContent)}` + if (content) { + script.src = `data:text/javascript;utf-8,${encodeURIComponent(content)}` + } + if (src) { + script.src = src + } return script } @@ -160,7 +163,8 @@ function useLiveCode({ getModuleUrl }) { const [error, setError] = useState() const rerender = useState({})[1] const appScriptRef = useScript() - const esShimOptionsScript = useScript() + const esShimOptionsScriptRef = useScript() + const tailwindcssScriptRef = useScript() const uid = useId() // Let getModuleUrl executed on parent window side since it might involve @@ -185,28 +189,28 @@ function useLiveCode({ getModuleUrl }) { if (!iframe || !iframe.contentDocument) return const doc = iframe.contentDocument + const body = doc.body const div = document.createElement('div') - div.id = 'root' + div.id = '__reactRoot' const appScriptContent = createMainScript({ uid }) const scriptOptionsContent = createEsShimOptionsScript() - const esmShimOptionsScript = setScript(esShimOptionsScript, scriptOptionsContent) - const appScript = setScript(appScriptRef, appScriptContent, { type: 'module' }) - // const script = scriptRef.current - // script.type = 'module' - // script.id = 'main' - // script.src = `data:text/javascript;utf-8,${encodeURIComponent(scriptContent)}` - - doc.body.appendChild(div) - doc.body.appendChild(esmShimOptionsScript) - doc.body.appendChild(appScript) + const esmShimOptionsScript = createScript(esShimOptionsScriptRef, { content: scriptOptionsContent }) + const appScript = createScript(appScriptRef, { content: appScriptContent, type: 'module' }) + const tailwindScript = createScript(tailwindcssScriptRef, { src: 'https://cdn.tailwindcss.com' }) + + body.appendChild(div) + body.appendChild(esmShimOptionsScript) + body.appendChild(appScript) + body.appendChild(tailwindScript) return () => { if (!iframe || !iframe.contentDocument) return - doc.body.removeChild(div) - doc.body.removeChild(esmShimOptionsScript) - doc.body.removeChild(appScript) + body.removeChild(div) + body.removeChild(esmShimOptionsScript) + body.removeChild(appScript) + body.removeChild(tailwindScript) } }, []) diff --git a/site/app/page.js b/site/app/page.js index a622dd5..60abac4 100644 --- a/site/app/page.js +++ b/site/app/page.js @@ -19,7 +19,10 @@ const defaultFiles = { const { data } = useSWR('world', key => key) return (
Volume {Array(num % 6).fill('●').join('')}