deku 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +5 -0
- data/LICENSE +25 -0
- data/README.md +28 -0
- data/Rakefile +1 -0
- data/deku.gemspec +23 -0
- data/deps/node_modules/deku.js +2 -0
- data/deps/node_modules/deku/.editorconfig +16 -0
- data/deps/node_modules/deku/.zuul.yml +15 -0
- data/deps/node_modules/deku/History.md +290 -0
- data/deps/node_modules/deku/LICENSE.md +7 -0
- data/deps/node_modules/deku/Makefile +91 -0
- data/deps/node_modules/deku/README.md +293 -0
- data/deps/node_modules/deku/index.js +4072 -0
- data/deps/node_modules/deku/lib/application.js +85 -0
- data/deps/node_modules/deku/lib/index.js +28 -0
- data/deps/node_modules/deku/lib/render.js +1300 -0
- data/deps/node_modules/deku/lib/stringify.js +105 -0
- data/deps/node_modules/deku/lib/svg.js +107 -0
- data/deps/node_modules/deku/lib/utils.js +18 -0
- data/deps/node_modules/deku/lib/virtual.js +247 -0
- data/deps/node_modules/deku/node_modules/array-flatten/LICENSE +21 -0
- data/deps/node_modules/deku/node_modules/array-flatten/README.md +43 -0
- data/deps/node_modules/deku/node_modules/array-flatten/array-flatten.js +57 -0
- data/deps/node_modules/deku/node_modules/array-flatten/package.json +62 -0
- data/deps/node_modules/deku/node_modules/component-emitter/History.md +63 -0
- data/deps/node_modules/deku/node_modules/component-emitter/LICENSE +24 -0
- data/deps/node_modules/deku/node_modules/component-emitter/Readme.md +74 -0
- data/deps/node_modules/deku/node_modules/component-emitter/index.js +161 -0
- data/deps/node_modules/deku/node_modules/component-emitter/package.json +174 -0
- data/deps/node_modules/deku/node_modules/component-raf/.npmignore +2 -0
- data/deps/node_modules/deku/node_modules/component-raf/History.md +26 -0
- data/deps/node_modules/deku/node_modules/component-raf/Makefile +11 -0
- data/deps/node_modules/deku/node_modules/component-raf/Readme.md +46 -0
- data/deps/node_modules/deku/node_modules/component-raf/component.json +16 -0
- data/deps/node_modules/deku/node_modules/component-raf/example.html +43 -0
- data/deps/node_modules/deku/node_modules/component-raf/index.js +34 -0
- data/deps/node_modules/deku/node_modules/component-raf/package.json +164 -0
- data/deps/node_modules/deku/node_modules/component-type/.npmignore +3 -0
- data/deps/node_modules/deku/node_modules/component-type/Makefile +14 -0
- data/deps/node_modules/deku/node_modules/component-type/Readme.md +37 -0
- data/deps/node_modules/deku/node_modules/component-type/component.json +13 -0
- data/deps/node_modules/deku/node_modules/component-type/index.js +34 -0
- data/deps/node_modules/deku/node_modules/component-type/package.json +120 -0
- data/deps/node_modules/deku/node_modules/component-type/test/index.html +17 -0
- data/deps/node_modules/deku/node_modules/component-type/test/mocha.css +231 -0
- data/deps/node_modules/deku/node_modules/component-type/test/mocha.js +5340 -0
- data/deps/node_modules/deku/node_modules/component-type/test/tests.js +72 -0
- data/deps/node_modules/deku/node_modules/dom-pool/.npmignore +1 -0
- data/deps/node_modules/deku/node_modules/dom-pool/Pool.js +52 -0
- data/deps/node_modules/deku/node_modules/dom-pool/README.md +42 -0
- data/deps/node_modules/deku/node_modules/dom-pool/authors.txt +4 -0
- data/deps/node_modules/deku/node_modules/dom-pool/bower.json +26 -0
- data/deps/node_modules/deku/node_modules/dom-pool/package.json +46 -0
- data/deps/node_modules/deku/node_modules/dom-pool/tests.html +16 -0
- data/deps/node_modules/deku/node_modules/dom-pool/tests.js +102 -0
- data/deps/node_modules/deku/node_modules/dom-walk/.npmignore +3 -0
- data/deps/node_modules/deku/node_modules/dom-walk/LICENCE +19 -0
- data/deps/node_modules/deku/node_modules/dom-walk/Makefile +2 -0
- data/deps/node_modules/deku/node_modules/dom-walk/README.md +23 -0
- data/deps/node_modules/deku/node_modules/dom-walk/example/index.js +5 -0
- data/deps/node_modules/deku/node_modules/dom-walk/example/static/bundle.js +211 -0
- data/deps/node_modules/deku/node_modules/dom-walk/example/static/index.html +16 -0
- data/deps/node_modules/deku/node_modules/dom-walk/index.js +24 -0
- data/deps/node_modules/deku/node_modules/dom-walk/package.json +57 -0
- data/deps/node_modules/deku/node_modules/fast.js/.jshintignore +7 -0
- data/deps/node_modules/deku/node_modules/fast.js/.jshintrc +80 -0
- data/deps/node_modules/deku/node_modules/fast.js/.npmignore +6 -0
- data/deps/node_modules/deku/node_modules/fast.js/.travis.yml +3 -0
- data/deps/node_modules/deku/node_modules/fast.js/LICENSE.md +21 -0
- data/deps/node_modules/deku/node_modules/fast.js/README.md +552 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/clone.js +21 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/concat.js +32 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/every.js +25 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/fill.js +29 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/filter.js +26 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/forEach.js +21 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/index.js +15 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/indexOf.js +33 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/lastIndexOf.js +29 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/map.js +24 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/pluck.js +24 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/reduce.js +35 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/reduceRight.js +35 -0
- data/deps/node_modules/deku/node_modules/fast.js/array/some.js +25 -0
- data/deps/node_modules/deku/node_modules/fast.js/bower.json +28 -0
- data/deps/node_modules/deku/node_modules/fast.js/clone.js +27 -0
- data/deps/node_modules/deku/node_modules/fast.js/dist/bench.html +15 -0
- data/deps/node_modules/deku/node_modules/fast.js/dist/bench.js +19900 -0
- data/deps/node_modules/deku/node_modules/fast.js/dist/fast.js +1450 -0
- data/deps/node_modules/deku/node_modules/fast.js/dist/fast.min.js +1 -0
- data/deps/node_modules/deku/node_modules/fast.js/filter.js +23 -0
- data/deps/node_modules/deku/node_modules/fast.js/forEach.js +22 -0
- data/deps/node_modules/deku/node_modules/fast.js/function/apply.js +19 -0
- data/deps/node_modules/deku/node_modules/fast.js/function/applyNoContext.js +29 -0
- data/deps/node_modules/deku/node_modules/fast.js/function/applyWithContext.js +29 -0
- data/deps/node_modules/deku/node_modules/fast.js/function/bind.js +71 -0
- data/deps/node_modules/deku/node_modules/fast.js/function/bindInternal3.js +11 -0
- data/deps/node_modules/deku/node_modules/fast.js/function/bindInternal4.js +11 -0
- data/deps/node_modules/deku/node_modules/fast.js/function/index.js +7 -0
- data/deps/node_modules/deku/node_modules/fast.js/function/partial.js +42 -0
- data/deps/node_modules/deku/node_modules/fast.js/function/partialConstructor.js +45 -0
- data/deps/node_modules/deku/node_modules/fast.js/function/try.js +35 -0
- data/deps/node_modules/deku/node_modules/fast.js/index.js +241 -0
- data/deps/node_modules/deku/node_modules/fast.js/map.js +23 -0
- data/deps/node_modules/deku/node_modules/fast.js/object/assign.js +34 -0
- data/deps/node_modules/deku/node_modules/fast.js/object/clone.js +25 -0
- data/deps/node_modules/deku/node_modules/fast.js/object/filter.js +28 -0
- data/deps/node_modules/deku/node_modules/fast.js/object/forEach.js +23 -0
- data/deps/node_modules/deku/node_modules/fast.js/object/index.js +11 -0
- data/deps/node_modules/deku/node_modules/fast.js/object/keys.js +17 -0
- data/deps/node_modules/deku/node_modules/fast.js/object/map.js +26 -0
- data/deps/node_modules/deku/node_modules/fast.js/object/reduce.js +37 -0
- data/deps/node_modules/deku/node_modules/fast.js/object/reduceRight.js +37 -0
- data/deps/node_modules/deku/node_modules/fast.js/object/values.js +20 -0
- data/deps/node_modules/deku/node_modules/fast.js/package.json +73 -0
- data/deps/node_modules/deku/node_modules/fast.js/reduce.js +24 -0
- data/deps/node_modules/deku/node_modules/fast.js/reduceRight.js +24 -0
- data/deps/node_modules/deku/node_modules/fast.js/string/index.js +3 -0
- data/deps/node_modules/deku/node_modules/fast.js/string/intern.js +56 -0
- data/deps/node_modules/deku/node_modules/get-uid/README.md +44 -0
- data/deps/node_modules/deku/node_modules/get-uid/index.js +6 -0
- data/deps/node_modules/deku/node_modules/get-uid/package.json +56 -0
- data/deps/node_modules/deku/node_modules/is-dom/HISTORY.md +2 -0
- data/deps/node_modules/deku/node_modules/is-dom/LICENSE +21 -0
- data/deps/node_modules/deku/node_modules/is-dom/README.md +32 -0
- data/deps/node_modules/deku/node_modules/is-dom/index.js +15 -0
- data/deps/node_modules/deku/node_modules/is-dom/package.json +62 -0
- data/deps/node_modules/deku/node_modules/object-path/.npmignore +7 -0
- data/deps/node_modules/deku/node_modules/object-path/.travis.yml +6 -0
- data/deps/node_modules/deku/node_modules/object-path/LICENSE +21 -0
- data/deps/node_modules/deku/node_modules/object-path/README.md +96 -0
- data/deps/node_modules/deku/node_modules/object-path/bower.json +17 -0
- data/deps/node_modules/deku/node_modules/object-path/component.json +22 -0
- data/deps/node_modules/deku/node_modules/object-path/index.js +269 -0
- data/deps/node_modules/deku/node_modules/object-path/package.json +89 -0
- data/deps/node_modules/deku/node_modules/object-path/test.js +510 -0
- data/deps/node_modules/deku/node_modules/per-frame/.npmignore +68 -0
- data/deps/node_modules/deku/node_modules/per-frame/History.md +32 -0
- data/deps/node_modules/deku/node_modules/per-frame/README.md +44 -0
- data/deps/node_modules/deku/node_modules/per-frame/component.json +13 -0
- data/deps/node_modules/deku/node_modules/per-frame/index.js +37 -0
- data/deps/node_modules/deku/node_modules/per-frame/package.json +143 -0
- data/deps/node_modules/deku/node_modules/per-frame/test/test.js +94 -0
- data/deps/node_modules/deku/node_modules/sliced/.npmignore +2 -0
- data/deps/node_modules/deku/node_modules/sliced/.travis.yml +4 -0
- data/deps/node_modules/deku/node_modules/sliced/History.md +30 -0
- data/deps/node_modules/deku/node_modules/sliced/LICENSE +22 -0
- data/deps/node_modules/deku/node_modules/sliced/Makefile +5 -0
- data/deps/node_modules/deku/node_modules/sliced/README.md +62 -0
- data/deps/node_modules/deku/node_modules/sliced/bench.js +95 -0
- data/deps/node_modules/deku/node_modules/sliced/component.json +14 -0
- data/deps/node_modules/deku/node_modules/sliced/index.js +1 -0
- data/deps/node_modules/deku/node_modules/sliced/lib/sliced.js +33 -0
- data/deps/node_modules/deku/node_modules/sliced/package.json +52 -0
- data/deps/node_modules/deku/node_modules/sliced/test/index.js +80 -0
- data/deps/node_modules/deku/package.json +67 -0
- data/lib/deku.rb +11 -0
- data/lib/deku/application.rb +16 -0
- data/lib/deku/component.rb +36 -0
- data/lib/deku/context.rb +38 -0
- data/lib/deku/element_node.rb +17 -0
- data/lib/deku/version.rb +4 -0
- metadata +278 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
var utils = require('./utils')
|
|
2
|
+
var defaults = utils.defaults
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Expose `stringify`.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
module.exports = function (app) {
|
|
9
|
+
if (!app.element) {
|
|
10
|
+
throw new Error('No element mounted')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Render to string.
|
|
15
|
+
*
|
|
16
|
+
* @param {Component} component
|
|
17
|
+
* @param {Object} [props]
|
|
18
|
+
* @return {String}
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
function stringify (component, optProps) {
|
|
22
|
+
var propTypes = component.propTypes || {}
|
|
23
|
+
var state = component.initialState ? component.initialState() : {}
|
|
24
|
+
var props = defaults(optProps, component.defaultProps || {})
|
|
25
|
+
|
|
26
|
+
for (var name in propTypes) {
|
|
27
|
+
var options = propTypes[name]
|
|
28
|
+
if (options.source) {
|
|
29
|
+
props[name] = app.sources[options.source]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (component.beforeMount) component.beforeMount({ props: props, state: state })
|
|
34
|
+
if (component.beforeRender) component.beforeRender({ props: props, state: state })
|
|
35
|
+
var node = component.render({ props: props, state: state })
|
|
36
|
+
return stringifyNode(node, '0')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Render a node to a string
|
|
41
|
+
*
|
|
42
|
+
* @param {Node} node
|
|
43
|
+
* @param {Tree} tree
|
|
44
|
+
*
|
|
45
|
+
* @return {String}
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
function stringifyNode (node, path) {
|
|
49
|
+
switch (node.type) {
|
|
50
|
+
case 'text': return node.data
|
|
51
|
+
case 'element':
|
|
52
|
+
var children = node.children
|
|
53
|
+
var attributes = node.attributes
|
|
54
|
+
var tagName = node.tagName
|
|
55
|
+
var innerHTML = attributes.innerHTML
|
|
56
|
+
var str = '<' + tagName + attrs(attributes) + '>'
|
|
57
|
+
|
|
58
|
+
if (innerHTML) {
|
|
59
|
+
str += innerHTML
|
|
60
|
+
} else {
|
|
61
|
+
for (var i = 0, n = children.length; i < n; i++) {
|
|
62
|
+
str += stringifyNode(children[i], path + '.' + i)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
str += '</' + tagName + '>'
|
|
67
|
+
return str
|
|
68
|
+
case 'component': return stringify(node.component, node.props)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
throw new Error('Invalid type')
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return stringifyNode(app.element, '0')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* HTML attributes to string.
|
|
79
|
+
*
|
|
80
|
+
* @param {Object} attributes
|
|
81
|
+
* @return {String}
|
|
82
|
+
* @api private
|
|
83
|
+
*/
|
|
84
|
+
|
|
85
|
+
function attrs (attributes) {
|
|
86
|
+
var str = ''
|
|
87
|
+
for (var key in attributes) {
|
|
88
|
+
if (key === 'innerHTML') continue
|
|
89
|
+
str += attr(key, attributes[key])
|
|
90
|
+
}
|
|
91
|
+
return str
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* HTML attribute to string.
|
|
96
|
+
*
|
|
97
|
+
* @param {String} key
|
|
98
|
+
* @param {String} val
|
|
99
|
+
* @return {String}
|
|
100
|
+
* @api private
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
function attr (key, val) {
|
|
104
|
+
return ' ' + key + '="' + val + '"'
|
|
105
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
var fast = require('fast.js')
|
|
2
|
+
var indexOf = fast.indexOf
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* This file lists the supported SVG elements used by the
|
|
6
|
+
* renderer. We may add better SVG support in the future
|
|
7
|
+
* that doesn't require whitelisting elements.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
exports.namespace = 'http://www.w3.org/2000/svg'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Supported SVG elements
|
|
14
|
+
*
|
|
15
|
+
* @type {Array}
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
exports.elements = [
|
|
19
|
+
'circle',
|
|
20
|
+
'defs',
|
|
21
|
+
'ellipse',
|
|
22
|
+
'g',
|
|
23
|
+
'line',
|
|
24
|
+
'linearGradient',
|
|
25
|
+
'mask',
|
|
26
|
+
'path',
|
|
27
|
+
'pattern',
|
|
28
|
+
'polygon',
|
|
29
|
+
'polyline',
|
|
30
|
+
'radialGradient',
|
|
31
|
+
'rect',
|
|
32
|
+
'stop',
|
|
33
|
+
'svg',
|
|
34
|
+
'text',
|
|
35
|
+
'tspan'
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Supported SVG attributes
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
exports.attributes = [
|
|
43
|
+
'cx',
|
|
44
|
+
'cy',
|
|
45
|
+
'd',
|
|
46
|
+
'dx',
|
|
47
|
+
'dy',
|
|
48
|
+
'fill',
|
|
49
|
+
'fillOpacity',
|
|
50
|
+
'fontFamily',
|
|
51
|
+
'fontSize',
|
|
52
|
+
'fx',
|
|
53
|
+
'fy',
|
|
54
|
+
'gradientTransform',
|
|
55
|
+
'gradientUnits',
|
|
56
|
+
'markerEnd',
|
|
57
|
+
'markerMid',
|
|
58
|
+
'markerStart',
|
|
59
|
+
'offset',
|
|
60
|
+
'opacity',
|
|
61
|
+
'patternContentUnits',
|
|
62
|
+
'patternUnits',
|
|
63
|
+
'points',
|
|
64
|
+
'preserveAspectRatio',
|
|
65
|
+
'r',
|
|
66
|
+
'rx',
|
|
67
|
+
'ry',
|
|
68
|
+
'spreadMethod',
|
|
69
|
+
'stopColor',
|
|
70
|
+
'stopOpacity',
|
|
71
|
+
'stroke',
|
|
72
|
+
'strokeDasharray',
|
|
73
|
+
'strokeLinecap',
|
|
74
|
+
'strokeOpacity',
|
|
75
|
+
'strokeWidth',
|
|
76
|
+
'textAnchor',
|
|
77
|
+
'transform',
|
|
78
|
+
'version',
|
|
79
|
+
'viewBox',
|
|
80
|
+
'x1',
|
|
81
|
+
'x2',
|
|
82
|
+
'x',
|
|
83
|
+
'y1',
|
|
84
|
+
'y2',
|
|
85
|
+
'y'
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Is element's namespace SVG?
|
|
90
|
+
*
|
|
91
|
+
* @param {String} name
|
|
92
|
+
*/
|
|
93
|
+
|
|
94
|
+
exports.isElement = function (name) {
|
|
95
|
+
return indexOf(exports.elements, name) !== -1
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Are element's attributes SVG?
|
|
100
|
+
*
|
|
101
|
+
* @param {String} attr
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
exports.isAttribute = function (attr) {
|
|
105
|
+
return indexOf(exports.attributes, attr) !== -1
|
|
106
|
+
}
|
|
107
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The npm 'defaults' module but without clone because
|
|
3
|
+
* it was requiring the 'Buffer' module which is huge.
|
|
4
|
+
*
|
|
5
|
+
* @param {Object} options
|
|
6
|
+
* @param {Object} defaults
|
|
7
|
+
*
|
|
8
|
+
* @return {Object}
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
exports.defaults = function(options, defaults) {
|
|
12
|
+
Object.keys(defaults).forEach(function(key) {
|
|
13
|
+
if (typeof options[key] === 'undefined') {
|
|
14
|
+
options[key] = defaults[key]
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
return options
|
|
18
|
+
}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module dependencies.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
var type = require('component-type')
|
|
6
|
+
var slice = require('sliced')
|
|
7
|
+
var flatten = require('array-flatten')
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* This function lets us create virtual nodes using a simple
|
|
11
|
+
* syntax. It is compatible with JSX transforms so you can use
|
|
12
|
+
* JSX to write nodes that will compile to this function.
|
|
13
|
+
*
|
|
14
|
+
* let node = virtual('div', { id: 'foo' }, [
|
|
15
|
+
* virtual('a', { href: 'http://google.com' }, 'Google')
|
|
16
|
+
* ])
|
|
17
|
+
*
|
|
18
|
+
* You can leave out the attributes or the children if either
|
|
19
|
+
* of them aren't needed and it will figure out what you're
|
|
20
|
+
* trying to do.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
module.exports = virtual
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Create virtual DOM trees.
|
|
27
|
+
*
|
|
28
|
+
* This creates the nicer API for the user.
|
|
29
|
+
* It translates that friendly API into an actual tree of nodes.
|
|
30
|
+
*
|
|
31
|
+
* @param {String|Function} type
|
|
32
|
+
* @param {Object} props
|
|
33
|
+
* @param {Array} children
|
|
34
|
+
* @return {Node}
|
|
35
|
+
* @api public
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
function virtual (type, props, children) {
|
|
39
|
+
// Default to div with no args
|
|
40
|
+
if (!type) {
|
|
41
|
+
throw new Error('Element needs a type. https://gist.github.com/anthonyshort/77ced43b5defe39908af')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Skipped adding attributes and we're passing
|
|
45
|
+
// in children instead.
|
|
46
|
+
if (arguments.length === 2 && (typeof props === 'string' || Array.isArray(props))) {
|
|
47
|
+
children = props
|
|
48
|
+
props = {}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Account for JSX putting the children as multiple arguments.
|
|
52
|
+
// This is essentially just the ES6 rest param
|
|
53
|
+
if (arguments.length > 2 && Array.isArray(arguments[2]) === false) {
|
|
54
|
+
children = slice(arguments, 2)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
children = children || []
|
|
58
|
+
props = props || {}
|
|
59
|
+
|
|
60
|
+
// passing in a single child, you can skip
|
|
61
|
+
// using the array
|
|
62
|
+
if (!Array.isArray(children)) {
|
|
63
|
+
children = [ children ]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
children = flatten(children, 1).reduce(normalize, [])
|
|
67
|
+
|
|
68
|
+
// pull the key out from the data.
|
|
69
|
+
var key = 'key' in props ? String(props.key) : null
|
|
70
|
+
delete props['key']
|
|
71
|
+
|
|
72
|
+
// if you pass in a function, it's a `Component` constructor.
|
|
73
|
+
// otherwise it's an element.
|
|
74
|
+
var node
|
|
75
|
+
if (typeof type === 'string') {
|
|
76
|
+
node = new ElementNode(type, props, key, children)
|
|
77
|
+
} else {
|
|
78
|
+
node = new ComponentNode(type, props, key, children)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// set the unique ID
|
|
82
|
+
node.index = 0
|
|
83
|
+
|
|
84
|
+
return node
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Parse nodes into real `Node` objects.
|
|
89
|
+
*
|
|
90
|
+
* @param {Mixed} node
|
|
91
|
+
* @param {Integer} index
|
|
92
|
+
* @return {Node}
|
|
93
|
+
* @api private
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
function normalize (acc, node) {
|
|
97
|
+
if (node == null) {
|
|
98
|
+
return acc
|
|
99
|
+
}
|
|
100
|
+
if (typeof node === 'string' || typeof node === 'number') {
|
|
101
|
+
var newNode = new TextNode(String(node))
|
|
102
|
+
newNode.index = acc.length
|
|
103
|
+
acc.push(newNode)
|
|
104
|
+
} else {
|
|
105
|
+
node.index = acc.length
|
|
106
|
+
acc.push(node)
|
|
107
|
+
}
|
|
108
|
+
return acc
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Initialize a new `ComponentNode`.
|
|
113
|
+
*
|
|
114
|
+
* @param {Component} component
|
|
115
|
+
* @param {Object} props
|
|
116
|
+
* @param {String} key Used for sorting/replacing during diffing.
|
|
117
|
+
* @param {Array} children Child virtual nodes
|
|
118
|
+
* @api public
|
|
119
|
+
*/
|
|
120
|
+
|
|
121
|
+
function ComponentNode (component, props, key, children) {
|
|
122
|
+
this.key = key
|
|
123
|
+
this.props = props
|
|
124
|
+
this.type = 'component'
|
|
125
|
+
this.component = component
|
|
126
|
+
this.props.children = children || []
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Initialize a new `ElementNode`.
|
|
131
|
+
*
|
|
132
|
+
* @param {String} tagName
|
|
133
|
+
* @param {Object} attributes
|
|
134
|
+
* @param {String} key Used for sorting/replacing during diffing.
|
|
135
|
+
* @param {Array} children Child virtual dom nodes.
|
|
136
|
+
* @api public
|
|
137
|
+
*/
|
|
138
|
+
|
|
139
|
+
function ElementNode (tagName, attributes, key, children) {
|
|
140
|
+
this.type = 'element'
|
|
141
|
+
this.attributes = parseAttributes(attributes)
|
|
142
|
+
this.tagName = tagName
|
|
143
|
+
this.children = children || []
|
|
144
|
+
this.key = key
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Initialize a new `TextNode`.
|
|
149
|
+
*
|
|
150
|
+
* This is just a virtual HTML text object.
|
|
151
|
+
*
|
|
152
|
+
* @param {String} text
|
|
153
|
+
* @api public
|
|
154
|
+
*/
|
|
155
|
+
|
|
156
|
+
function TextNode (text) {
|
|
157
|
+
this.type = 'text'
|
|
158
|
+
this.data = String(text)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Parse attributes for some special cases.
|
|
163
|
+
*
|
|
164
|
+
* TODO: This could be more functional and allow hooks
|
|
165
|
+
* into the processing of the attributes at a component-level
|
|
166
|
+
*
|
|
167
|
+
* @param {Object} attributes
|
|
168
|
+
*
|
|
169
|
+
* @return {Object}
|
|
170
|
+
*/
|
|
171
|
+
|
|
172
|
+
function parseAttributes (attributes) {
|
|
173
|
+
// style: { 'text-align': 'left' }
|
|
174
|
+
if (attributes.style) {
|
|
175
|
+
attributes.style = parseStyle(attributes.style)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// class: { foo: true, bar: false, baz: true }
|
|
179
|
+
// class: ['foo', 'bar', 'baz']
|
|
180
|
+
if (attributes.class) {
|
|
181
|
+
attributes.class = parseClass(attributes.class)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Remove attributes with false values
|
|
185
|
+
var filteredAttributes = {}
|
|
186
|
+
for (var key in attributes) {
|
|
187
|
+
var value = attributes[key]
|
|
188
|
+
if (value == null || value === false) continue
|
|
189
|
+
filteredAttributes[key] = value
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return filteredAttributes
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Parse a block of styles into a string.
|
|
197
|
+
*
|
|
198
|
+
* TODO: this could do a lot more with vendor prefixing,
|
|
199
|
+
* number values etc. Maybe there's a way to allow users
|
|
200
|
+
* to hook into this?
|
|
201
|
+
*
|
|
202
|
+
* @param {Object} styles
|
|
203
|
+
*
|
|
204
|
+
* @return {String}
|
|
205
|
+
*/
|
|
206
|
+
|
|
207
|
+
function parseStyle (styles) {
|
|
208
|
+
if (type(styles) === 'string') {
|
|
209
|
+
return styles
|
|
210
|
+
}
|
|
211
|
+
var str = ''
|
|
212
|
+
for (var name in styles) {
|
|
213
|
+
var value = styles[name]
|
|
214
|
+
str = str + name + ':' + value + ';'
|
|
215
|
+
}
|
|
216
|
+
return str;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Parse the class attribute so it's able to be
|
|
221
|
+
* set in a more user-friendly way
|
|
222
|
+
*
|
|
223
|
+
* @param {String|Object|Array} value
|
|
224
|
+
*
|
|
225
|
+
* @return {String}
|
|
226
|
+
*/
|
|
227
|
+
|
|
228
|
+
function parseClass (value) {
|
|
229
|
+
// { foo: true, bar: false, baz: true }
|
|
230
|
+
if (type(value) === 'object') {
|
|
231
|
+
var matched = []
|
|
232
|
+
for (var key in value) {
|
|
233
|
+
if (value[key]) matched.push(key)
|
|
234
|
+
}
|
|
235
|
+
value = matched
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// ['foo', 'bar', 'baz']
|
|
239
|
+
if (type(value) === 'array') {
|
|
240
|
+
if (value.length === 0) {
|
|
241
|
+
return
|
|
242
|
+
}
|
|
243
|
+
value = value.join(' ')
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return value
|
|
247
|
+
}
|