Skip to content

Instantly share code, notes, and snippets.

@robozevel
Created February 10, 2020 15:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robozevel/7118ffa0ea1f0158ee782f867551f76c to your computer and use it in GitHub Desktop.
Save robozevel/7118ffa0ea1f0158ee782f867551f76c to your computer and use it in GitHub Desktop.
import { createElement } from '@vue/composition-api'
import htm from 'htm'
const acceptValue = ['input', 'textarea', 'option', 'select']
function getVNodeData (tag, attrs) {
const data = {}
const basics = ['slot', 'key', 'ref', 'refInFor', 'class', 'style']
for (const key of Object.keys(attrs)) {
if (key.substring(0, 2) === 'on') {
// OnClick => on: {click}
data.on = data.on || {}
const newKey = lowerCaseFirstLetter(key.substring(2))
data.on[newKey] = attrs[key]
} else if (key.substring(0, 8) === 'nativeOn') {
// NativeOnClick => nativeOn: {click}
data.nativeOn = data.nativeOn || {}
const newKey = lowerCaseFirstLetter(key.substring(8))
data.nativeOn[newKey] = attrs[key]
} else if (key.substring(0, 8) === 'domProps') {
// DomPropsInnerHTML => domProps: {innerHTML}
data.domProps = data.domProps || {}
const newKey = lowerCaseFirstLetter(key.substring(8))
data.domProps[newKey] = attrs[key]
} else if (key.substring(0, 2) === 'v-') {
data.directives = data.directives || []
const name = key.substring(2)
data.directives.push({
name,
value: attrs[key]
})
} else if (mustUseDomProp(tag, attrs.type, key)) {
data.domProps = data.domProps || {}
data.domProps[key] = attrs[key]
} else if (basics.indexOf(key) > -1) {
data[key] = attrs[key]
} else {
// All others props => {attrs: props}
data.attrs = data.attrs || {}
data.attrs[key] = attrs[key]
}
}
return data
}
function lowerCaseFirstLetter (string) {
return string.charAt(0).toLowerCase() + string.substring(1)
}
function mustUseDomProp (tag, type, attr) {
return (
(attr === 'value' && acceptValue.includes(tag) && type !== 'button') ||
(attr === 'selected' && tag === 'option') ||
(attr === 'checked' && tag === 'input') ||
(attr === 'muted' && tag === 'video')
)
}
const h = (tag, attrs, ...children) => {
return createElement(tag, attrs && getVNodeData(tag, attrs), children)
}
export default htm.bind(h)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment