Skip to content

Instantly share code, notes, and snippets.

@usualoma
Created June 7, 2022 00:32
Show Gist options
  • Save usualoma/07b9dce3233f4b7af933e39268cc342e to your computer and use it in GitHub Desktop.
Save usualoma/07b9dce3233f4b7af933e39268cc342e 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>
}
}
}
// eslint-disable-next-line @typescript-eslint/ban-types
type EscapedString = String & { isEscaped: true }
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, any>,
...children: (string | EscapedString)[]
): EscapedString {
if (typeof tag === 'function') {
return tag.call(null, { ...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]])}"`
}
const res: any = new String(
`<${tag}${attrs}>${children
.flat()
.map((c) => ((c as any).isEscaped ? c : escape(c as string)))
.join('')}</${tag}>`
)
res.isEscaped = true
return res
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment