"use strict" var Vnode = require("./vnode") var hyperscriptVnode = require("./hyperscriptVnode") var hasOwn = require("../util/hasOwn") var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g var selectorCache = {} 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(" ") 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 vnode.attrs = {} if (!isEmpty(state.attrs) && !isEmpty(attrs)) { var newAttrs = {} for (var key in attrs) { if (hasOwn.call(attrs, key)) newAttrs[key] = attrs[key] } attrs = newAttrs } for (var key in state.attrs) { if (hasOwn.call(state.attrs, key) && key !== "className" && !hasOwn.call(attrs, key)){ attrs[key] = state.attrs[key] } } 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 if (hasClass) attrs.class = null for (var key in attrs) { if (hasOwn.call(attrs, key) && key !== "key") { vnode.attrs = attrs break } } 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