type NodeReactLike = {
tag: string;
attrs: Record<string, string>;
children: NodeReactLike[];
text: string | null;
};
const El = (
tag: string,
attrs: Record<string, string>,
children: NodeReactLike[],
text: string | null,
): NodeReactLike => {
return {
tag,
attrs,
children,
text,
};
};
const Txt = (text: string): NodeReactLike => {
return {
tag: "",
attrs: {},
children: [],
text,
};
};
const render = (node: NodeReactLike): string => {
if (node.tag === "" && node.text !== null) return escapeHtml(node.text);
let html = `<${node.tag}`;
for (const [key, value] of Object.entries(node.attrs)) {
html += ` ${key}="${escapeHtml(value)}"`;
}
html += ">";
for (const child of node.children) {
html += render(child);
}
html += `</${node.tag}>`;
return html;
};
const escapeHtml = (text: string): string => {
return text
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
};
const Button = (label: string, onClick: () => void): NodeReactLike => {
return El("button", { onClick: onClick.toString() }, [Txt(label)], null);
};
const Page = El(
"div",
{ className: "page" },
[
El(
"header",
{ className: "header" },
[Txt("🌟 Bienvenue sur notre site 🌟")],
null,
),
El(
"main",
{ className: "main-content" },
[
El("h1", { className: "title" }, [Txt("Découvrez nos services")], null),
El(
"p",
{ className: "description" },
[Txt("Une expérience incroyable vous attend")],
null,
),
El(
"div",
{ className: "button-container" },
[
Button("🚀 Commencer", () => alert("Aventure commencée !")),
Button("📖 En savoir plus", () =>
alert("Plus d'informations bientôt !"),
),
],
null,
),
],
null,
),
El(
"footer",
{ className: "footer" },
[Txt("© 2024 - Tous droits réservés")],
null,
),
],
null,
);
const renderPage = (): string => {
return render(Page);
};
console.log(renderPage());
/*
<div className="page">
<header className="header">🌟 Bienvenue sur notre site 🌟</header>
<main className="main-content">
<h1 className="title">Découvrez nos services</h1>
<p className="description">Une expérience incroyable vous attend</p>
<div className="button-container"><button onClick="() => alert("Aventure commencée !")">🚀 Commencer</button><button onClick="() => alert("Plus d'informations bientôt !")">📖 En savoir plus</button></div>
</main>
<footer className="footer">© 2024 - Tous droits réservés</footer>
</div>
*/
Last active
June 24, 2025 20:41
-
-
Save axelhamil/d68f74b44b5b2827a89ae0094f9e9a44 to your computer and use it in GitHub Desktop.
Mini ReactTree in TypeScript: Typed Components to Render HTML
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment