Skip to content

Instantly share code, notes, and snippets.

@borestad
Created October 10, 2017 07:11
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save borestad/eac42120613bc67a3714f115e8b485a7 to your computer and use it in GitHub Desktop.
Save borestad/eac42120613bc67a3714f115e8b485a7 to your computer and use it in GitHub Desktop.
JSX/TSX without React
/*
* Custom jsx parser
* See: tsconfig.json
*
* {
* "jsx": "react",
* "jsxFactory": "h"
* }
*
*/
export const entityMap = { '&': 'amp', '<': 'lt', '>': 'gt', '"': 'quot', '\'': '#39', '/': '#x2F' }
export const escapeHtml = str => String(str).replace(/[&<>"'\/\\]/g, s => `&${entityMap[s]};`)
// To keep some consistency with React DOM, lets use a mapper
// https://reactjs.org/docs/dom-elements.html
export const AttributeMapper = val => ({
tabIndex: 'tabindex',
className: 'class',
readOnly: 'readonly'
}[val] || val)
// tslint:disable-next-line:no-default-export
export default function h (
tag: Function | string,
attrs?: {[key: string]: any},
...children: (HTMLElement | string)[]
): HTMLElement {
attrs = attrs || {}
const stack: any[] = [...children]
// Support for components(ish)
if (typeof tag === 'function') {
attrs.children = stack
return tag(attrs)
}
const elm = document.createElement(tag)
// Add attributes
for (let [ name, val ] of Object.entries(attrs)) {
name = escapeHtml(AttributeMapper(name))
if (val === true) {
elm.setAttribute(name, name)
} else if (val !== false && val != null) {
elm.setAttribute(name, escapeHtml(val))
} else if (val === false) {
elm.removeAttribute(name)
}
}
// Append children
while (stack.length) {
const child = stack.shift()
// Is child a leaf?
if (!Array.isArray(child)) {
elm.appendChild((child as HTMLElement).nodeType == null ?
document.createTextNode(child.toString()) :
child
)
} else {
stack.push(...child)
}
}
return elm
}
@JakubKoralewski
Copy link

Hey it's great! I've added being able to add styles in this fork https://gist.github.com/JakubKoralewski/ab20c250ff826f3314474650ecaaeb17

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment