-
-
Notifications
You must be signed in to change notification settings - Fork 924
Expand file tree
/
Copy pathhyperscript.js
More file actions
104 lines (84 loc) · 3.26 KB
/
hyperscript.js
File metadata and controls
104 lines (84 loc) · 3.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
"use strict"
var Vnode = require("../render/vnode")
var hyperscriptVnode = require("./hyperscriptVnode")
var hasOwn = require("../util/hasOwn")
var emptyAttrs = require("./emptyAttrs")
var cachedAttrsIsStaticMap = require("./cachedAttrsIsStaticMap")
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 isFormAttributeKey(key) {
return key === "value" || key === "checked" || key === "selectedIndex" || key === "selected"
}
function compileSelector(selector) {
var match, tag = "div", classes = [], attrs = {}, isStatic = true
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 (isFormAttributeKey(match[4])) isStatic = false
}
}
}
if (classes.length > 0) attrs.className = classes.join(" ")
if (isEmpty(attrs)) attrs = emptyAttrs
else cachedAttrsIsStaticMap.set(attrs, isStatic)
return selectorCache[selector] = {tag: tag, attrs: attrs, is: attrs.is}
}
function execSelector(state, vnode) {
vnode.tag = state.tag
var attrs = vnode.attrs
if (attrs == null) {
vnode.attrs = state.attrs
vnode.is = state.is
return vnode
}
var hasClass = hasOwn.call(attrs, "class")
var className = hasClass ? attrs.class : attrs.className
if (state.attrs !== emptyAttrs) {
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
} 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)
}
// This reduces the complexity of the evaluation of "is" within the render function.
vnode.is = attrs.is
vnode.attrs = attrs
return vnode
}
function hyperscript(selector, attrs, ...children) {
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(attrs, children)
if (typeof selector === "string") {
vnode.children = Vnode.normalizeChildren(vnode.children)
if (selector !== "[") return execSelector(selectorCache[selector] || compileSelector(selector), vnode)
}
if (vnode.attrs == null) vnode.attrs = {}
vnode.tag = selector
return vnode
}
module.exports = hyperscript