Skip to content

Instantly share code, notes, and snippets.

@usualoma
Last active June 6, 2022 20:50
Show Gist options
  • Save usualoma/26e17a61fab123adcc7408eb00279e6a to your computer and use it in GitHub Desktop.
Save usualoma/26e17a61fab123adcc7408eb00279e6a to your computer and use it in GitHub Desktop.
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace jsx.JSX {
interface IntrinsicElements {
[tagName: string]: Record<string, string>;
}
}
}
class EscapedString {
private content: string;
constructor(content: string) {
this.content = content;
}
public toString() {
return this.content;
}
}
function escape(str: string): string {
return str
.replace(/&/g, "&amp;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
}
export function jsx(
tag: string | Function,
props: Record<string, string | EscapedString>,
...children: (string | EscapedString)[]
): EscapedString {
if (typeof tag === "function") {
props ||= {};
props["children"] = children[0];
return tag(props, children);
}
let attrs = "";
const propsKeys = Object.keys(props || {});
for (let i = 0, len = propsKeys.length; i < len; i++) {
attrs += ` ${propsKeys[i]}="${escape(props[propsKeys[i]])}"`;
}
return new EscapedString(
`<${tag}${attrs}>${children
.map((c) => (c instanceof EscapedString ? c.toString() : escape(c)))
.join("")}</${tag}>`
);
}
export function render(content: EscapedString): string {
return content.toString();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment