Created
May 14, 2025 05:11
-
-
Save lutfi-haslab/27652da5b9fc1cd31bec1ddad5ea7973 to your computer and use it in GitHub Desktop.
babel react compiler to html
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { availablePresets, registerPreset, transform } from "@babel/standalone"; | |
import { | |
type TailwindConfig, | |
createTailwindcss, | |
} from "@mhsdesign/jit-browser-tailwindcss"; | |
registerPreset("tsx", { | |
presets: [ | |
[availablePresets["typescript"], { allExtensions: true, isTSX: true }], | |
], | |
}); | |
export const compileTypescript = async (code: string) => { | |
const compiledComponent: any = babelCompile(code, `Section.tsx`); | |
const app = ` | |
import React, { useEffect } from 'react'; | |
import { createRoot } from 'react-dom'; | |
import Section from './Section.tsx'; | |
const App = () => { | |
return ( | |
<> | |
<Section /> | |
</> | |
) | |
} | |
createRoot(document.querySelector("#root")).render(<App />) | |
`; | |
// Transform the code from TSX to JS | |
const output = babelCompile(app, "index.tsx"); | |
// Have CSS generated from Tailwind | |
const tailwindConfig: TailwindConfig = { | |
theme: { | |
extend: { | |
colors: {}, | |
}, | |
}, | |
// plugins: [typography] | |
}; | |
const tailwindCss = createTailwindcss({ tailwindConfig }); | |
const css = await tailwindCss.generateStylesFromContent( | |
` | |
@tailwind base; | |
@tailwind components; | |
@tailwind utilities; | |
`, | |
[compiledComponent.code, output.code], | |
); | |
const html = `<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<style>${css}</style> | |
</head> | |
<body style="background-color:#fff"> | |
<div id="root"></div> | |
<script crossorigin defer src="https://unpkg.com/[email protected]/umd/react.production.min.js"></script> | |
<script crossorigin defer src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script> | |
<script defer>window.addEventListener("DOMContentLoaded", () => {${[ | |
compiledComponent.code, | |
output.code, | |
].join("\n")}});</script> | |
</body> | |
</html> | |
`; | |
return html; | |
}; | |
// Transforms the TSX code to JS | |
const babelCompile = (code: string, filename: string) => | |
transform(code, { | |
filename: filename, | |
plugins: [ | |
[ | |
"transform-modules-umd", | |
{ | |
globals: { react: "React", "react-dom": "ReactDOM" }, | |
}, | |
], | |
], | |
presets: ["tsx", "react"], | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useRef, useState } from "react"; | |
import { compileTypescript } from "~/utils/compiler"; | |
interface MyProps extends React.HTMLAttributes<HTMLDivElement> { | |
code: string; | |
} | |
export const PageEditor = ({ code }: MyProps) => { | |
const iframeRef = useRef<HTMLIFrameElement>(null); | |
const [dom, setDom] = useState<string | undefined>(undefined); | |
const svgRef = useRef<SVGSVGElement>(null); | |
const [dimensions, setDimensions] = useState({ width: 0, height: 0 }); | |
useEffect(() => { | |
// Compile and render the page | |
const compileCode = async () => { | |
const compiledCode = await compileTypescript(code); | |
setDom(compiledCode); | |
}; | |
// We resize the canvas to fit the screen. This is not ideal, but it works for now. | |
const handleResize = () => { | |
const iframe = iframeRef.current; | |
if (!iframe) return; | |
const { contentWindow } = iframeRef.current; | |
if (contentWindow) { | |
const { documentElement } = contentWindow.document; | |
const width = documentElement.clientWidth; | |
const height = documentElement.clientHeight; | |
setDimensions({ width, height }); | |
} | |
}; | |
handleResize(); | |
window.addEventListener("resize", handleResize); | |
// Compile the code | |
compileCode(); | |
return () => { | |
window.removeEventListener("resize", handleResize); | |
}; | |
}, [code]); | |
const handleScroll = (event: React.WheelEvent) => { | |
if (!iframeRef.current) return; | |
if (!iframeRef.current.contentWindow) return; | |
iframeRef.current.contentWindow.scrollBy(0, event.deltaY); | |
// scrollTop = iframeRef.current.scrollTop + event.deltaY; | |
}; | |
return ( | |
<div className="absolute inset-0 flex justify-center"> | |
<div | |
className="absolute inset-0 overflow-hidden rounded-b-lg" | |
onWheel={handleScroll} | |
> | |
<iframe | |
width="100%" | |
height="100%" | |
tabIndex={-1} | |
title="The editor's rendered HTML document" | |
srcDoc={dom} | |
ref={iframeRef} | |
className="pointer-events-none mx-auto my-0 block w-full min-w-[769] overflow-hidden border-0" | |
/> | |
<div className="pointer-events-none absolute inset-y-0 flex max-w-full"> | |
<svg | |
id="SVGOverlay" | |
className="overflow-visible" | |
width={dimensions.width} | |
height={dimensions.height} | |
ref={svgRef} | |
// style="transform: translate3d(0px, 0px, 0px);" | |
> | |
<rect id="SVGSelection"></rect> | |
<rect id="SVGHover"></rect> | |
</svg> | |
</div> | |
</div> | |
</div> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment