import { useUpdatedEffect } from '@/util/hooks'
import '@/components/Playground/Output/Preview/preview.scss'
import { IFiles, IImportMap } from '@/components/Playground/shared'
import Compiler from '@/components/Playground/compiler'
import iframeRaw from '@/components/Playground/Output/Preview/iframe.html?raw'
interface PreviewProps {
iframeKey: string
files: IFiles
importMap: IImportMap
}
interface IMessage {
type: 'LOADED' | 'ERROR' | 'UPDATE' | 'DONE'
msg: string
data: {
compiledCode: string
}
}
const getIframeUrl = (iframeRaw: string) => {
const shimsUrl = '//unpkg.com/es-module-shims@1.8.0/dist/es-module-shims.js'
// 判断浏览器是否支持esm ,不支持esm就引入es-module-shims
const newIframeRaw =
typeof import.meta === 'undefined'
? iframeRaw.replace(
'',
``
)
: iframeRaw
return URL.createObjectURL(new Blob([newIframeRaw], { type: 'text/html' }))
}
const iframeUrl = getIframeUrl(iframeRaw)
const Preview = ({ iframeKey, files, importMap }: PreviewProps) => {
const iframeRef = useRef(null)
const [errorMsg, setErrorMsg] = useState('')
const [loaded, setLoaded] = useState(false)
const handleMessage = ({ data }: { data: IMessage }) => {
const { type, msg } = data
switch (type) {
case 'LOADED':
setLoaded(true)
break
case 'ERROR':
setErrorMsg(msg)
break
case 'DONE':
setErrorMsg('')
}
}
useUpdatedEffect(() => {
window.addEventListener('message', handleMessage)
return () => {
window.removeEventListener('message', handleMessage)
}
}, [])
useUpdatedEffect(() => {
Compiler.compile(files, importMap)
.then((result) => {
if (loaded) {
iframeRef.current?.contentWindow?.postMessage({
type: 'UPDATE',
data: { compiledCode: result.outputFiles[0].text }
} as IMessage)
}
})
.catch((e) => {
setErrorMsg(`编译失败:${e.message}`)
})
}, [files, Compiler, loaded])
return (
)
}
export default Preview