UNPKG

mithril

Version:

A framework for building brilliant applications

87 lines (69 loc) 2.73 kB
"use strict" var Vnode = require("../render/vnode") var hyperscriptVnode = require("./hyperscriptVnode") var hasOwn = require("../util/hasOwn") var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g var selectorCache = Object.create(null) function isEmpty(object) { for (var key in object) if (hasOwn.call(object, key)) return false return true } function compileSelector(selector) { var match, tag = "div", classes = [], attrs = {} while (match = selectorParser.exec(selector)) { var type = match[1], value = match[2] if (type === "" && value !== "") tag = value else if (type === "#") attrs.id = value else if (type === ".") classes.push(value) else if (match[3][0] === "[") { var attrValue = match[6] if (attrValue) attrValue = attrValue.replace(/\\(["'])/g, "$1").replace(/\\\\/g, "\\") if (match[4] === "class") classes.push(attrValue) else attrs[match[4]] = attrValue === "" ? attrValue : attrValue || true } } if (classes.length > 0) attrs.className = classes.join(" ") if (isEmpty(attrs)) attrs = null return selectorCache[selector] = {tag: tag, attrs: attrs} } function execSelector(state, vnode) { var attrs = vnode.attrs var hasClass = hasOwn.call(attrs, "class") var className = hasClass ? attrs.class : attrs.className vnode.tag = state.tag if (state.attrs != null) { attrs = Object.assign({}, state.attrs, attrs) if (className != null || state.attrs.className != null) attrs.className = className != null ? state.attrs.className != null ? String(state.attrs.className) + " " + String(className) : className : state.attrs.className != null ? state.attrs.className : null } else { if (className != null) attrs.className = className } if (hasClass) attrs.class = null // workaround for #2622 (reorder keys in attrs to set "type" first) // The DOM does things to inputs based on the "type", so it needs set first. // See: https://github.com/MithrilJS/mithril.js/issues/2622 if (state.tag === "input" && hasOwn.call(attrs, "type")) { attrs = Object.assign({type: attrs.type}, attrs) } vnode.attrs = attrs return vnode } function hyperscript(selector) { if (selector == null || typeof selector !== "string" && typeof selector !== "function" && typeof selector.view !== "function") { throw Error("The selector must be either a string or a component."); } var vnode = hyperscriptVnode.apply(1, arguments) if (typeof selector === "string") { vnode.children = Vnode.normalizeChildren(vnode.children) if (selector !== "[") return execSelector(selectorCache[selector] || compileSelector(selector), vnode) } vnode.tag = selector return vnode } module.exports = hyperscript