It's midnight and I'm waiting for a surgery on 01:00, and I've got exams to read for, but.. hacking things together is more fun.
Let's see if this works
^ This one doesn't work; Babel tags won't get called if script is appended later..
^ Works!
^ Try again for good measure (in case react conflicts, etc) >> Works!
Here's the working code
<div>
<script>
(function() {
// Generate a unique ID for this instance's mount point.
var instanceId = Math.random().toString(36).substr(2, 9);
var mountId = "ghost-react-root-" + instanceId;
// Get the container element (the parent of this <script> tag).
var blockContainer = document.currentScript.parentElement;
// Create and append a new <div> that will serve as the React mount point.
var mountDiv = document.createElement("div");
mountDiv.id = mountId;
blockContainer.appendChild(mountDiv);
// Helper to load an external script and return a Promise.
function loadScript(url) {
return new Promise(function(resolve, reject) {
var script = document.createElement("script");
script.src = url;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
// If React, ReactDOM, and Babel haven't been loaded yet, load them once and store a global promise.
if (!window.__ghostReactPromise) {
window.__ghostReactPromise = (function() {
var promises = [];
if (!window.React) {
promises.push(loadScript("https://unpkg.com/react@17/umd/react.development.js"));
}
if (!window.ReactDOM) {
promises.push(loadScript("https://unpkg.com/react-dom@17/umd/react-dom.development.js"));
}
if (!window.Babel) {
promises.push(loadScript("https://unpkg.com/@babel/standalone/babel.min.js"));
}
return Promise.all(promises);
})();
}
// Once everything is loaded, compile and inject the React code.
window.__ghostReactPromise.then(function() {
// Replace this entire string with your JSX-based React code:
var jsxCode = `
class GhostCustomComponent extends React.Component {
render() {
return (
<div>
<h1>Hello from your custom React component!</h1>
<p>Edit this JSX to build your own UI.</p>
</div>
);
}
}
ReactDOM.render(<GhostCustomComponent />, document.getElementById('${mountId}'));
`;
// 1) Use Babel.transform to compile the JSX into plain JavaScript
var transformed = Babel.transform(jsxCode, {
presets: ["env", "react"] // You can adjust these presets if needed
}).code;
// 2) Create a normal <script> tag with the compiled code and inject it
var compiledScript = document.createElement("script");
compiledScript.text = transformed;
document.body.appendChild(compiledScript);
}).catch(function(error) {
console.error("Error loading React libraries:", error);
});
})();
</script>
</div>
And for good measure, play around with some hooks stuff
Source
<div>
<script>
(function() {
// Generate a unique ID for this instance's mount point.
var instanceId = Math.random().toString(36).substr(2, 9);
var mountId = "ghost-react-root-" + instanceId;
// Get the container element (the parent of this <script> tag).
var blockContainer = document.currentScript.parentElement;
// Create and append a new <div> that will serve as the React mount point.
var mountDiv = document.createElement("div");
mountDiv.id = mountId;
blockContainer.appendChild(mountDiv);
// Helper to load an external script and return a Promise.
function loadScript(url) {
return new Promise(function(resolve, reject) {
var script = document.createElement("script");
script.src = url;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
// If React, ReactDOM, and Babel haven't been loaded yet, load them once and store a global promise.
if (!window.__ghostReactPromise) {
window.__ghostReactPromise = (function() {
var promises = [];
if (!window.React) {
promises.push(loadScript("https://unpkg.com/react@17/umd/react.development.js"));
}
if (!window.ReactDOM) {
promises.push(loadScript("https://unpkg.com/react-dom@17/umd/react-dom.development.js"));
}
if (!window.Babel) {
promises.push(loadScript("https://unpkg.com/@babel/standalone/babel.min.js"));
}
return Promise.all(promises);
})();
}
// Once everything is loaded, compile and inject the React code.
window.__ghostReactPromise.then(function() {
// Replace this entire string with your JSX-based React code:
var jsxCode = `
function Calculator() {
const [num1, setNum1] = React.useState("");
const [num2, setNum2] = React.useState("");
const [operation, setOperation] = React.useState("+");
const [result, setResult] = React.useState(null);
function calculate() {
const n1 = parseFloat(num1);
const n2 = parseFloat(num2);
if (isNaN(n1) || isNaN(n2)) {
setResult("Please enter valid numbers!");
return;
}
let res;
switch (operation) {
case "+":
res = n1 + n2;
break;
case "-":
res = n1 - n2;
break;
case "*":
res = n1 * n2;
break;
case "/":
res = n2 === 0 ? "Cannot divide by zero!" : n1 / n2;
break;
default:
res = "Unknown operation";
}
setResult(res);
}
return (
<div style={{ border: "1px solid #ccc", padding: "1em", width: "250px" }}>
<h2>Simple React Calculator</h2>
<div style={{ marginBottom: "0.5em" }}>
<label>Number 1: </label>
<input
type="text"
value={num1}
onChange={e => setNum1(e.target.value)}
style={{ marginLeft: "0.5em" }}
/>
</div>
<div style={{ marginBottom: "0.5em" }}>
<label>Number 2: </label>
<input
type="text"
value={num2}
onChange={e => setNum2(e.target.value)}
style={{ marginLeft: "0.5em" }}
/>
</div>
<div style={{ marginBottom: "0.5em" }}>
<label>Operation: </label>
<select
value={operation}
onChange={e => setOperation(e.target.value)}
style={{ marginLeft: "0.5em" }}
>
<option value="+">+</option>
<option value="-">-</option>
<option value="*">*</option>
<option value="/">/</option>
</select>
</div>
<button onClick={calculate}>Calculate</button>
<div style={{ marginTop: "1em" }}>
<strong>Result: </strong>
<span>{result !== null ? result : "N/A"}</span>
</div>
</div>
);
}
ReactDOM.render(<Calculator />, document.getElementById('${mountId}'));
`;
// 1) Use Babel.transform to compile the JSX into plain JavaScript
var transformed = Babel.transform(jsxCode, {
presets: ["env", "react"] // You can adjust these presets if needed
}).code;
// 2) Create a normal <script> tag with the compiled code and inject it
var compiledScript = document.createElement("script");
compiledScript.text = transformed;
document.body.appendChild(compiledScript);
}).catch(function(error) {
console.error("Error loading React libraries:", error);
});
})();
</script>
</div>
V0.Dev
DeepSeek