-
-
Notifications
You must be signed in to change notification settings - Fork 20
/
base.js
123 lines (120 loc) · 4.3 KB
/
base.js
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
'use strict';
var getDomjs = require('es5-ext/function/pluck')('_domjs')
, assign = require('es5-ext/object/assign')
, forEach = require('es5-ext/object/for-each')
, d = require('d')
, autoBind = require('d/auto-bind')
, lazy = require('d/lazy')
, memoizeMethods = require('memoizee/methods-plain')
, validDocument = require('dom-ext/document/valid-document')
, normalize = require('dom-ext/document/#/normalize')
, normalizeRaw = require('dom-ext/document/#/normalize-raw')
, validNode = require('dom-ext/node/valid-node')
, ext = require('./ext')
, construct = require('./_construct-element')
, isArray = Array.isArray, slice = Array.prototype.slice
, create = Object.create, defineProperty = Object.defineProperty
, defineProperties = Object.defineProperties
, getPrototypeOf = Object.getPrototypeOf, Base;
module.exports = Base = function (document) {
if (!(this instanceof Base)) return new Base(document);
this.document = validDocument(document);
defineProperties(this, {
_current: d(document.createDocumentFragment()),
_directives: d(create(null, {
_element: d(create(null))
})),
ns: d(create(this.ns, { _domjs: d(this) }))
});
};
Object.defineProperties(Base.prototype, assign({
collect: d(function (fn) {
var previous = this._current
, current = (this._current = this.document.createDocumentFragment());
fn();
this._current = previous;
return current;
}),
safeCollect: d(function (fn) { return normalize.call(this.document, this.safeCollectRaw(fn)); }),
safeCollectRaw: d(function (fn) {
var direct, result;
result = this.collect(function () { direct = fn(); });
return normalizeRaw.call(this.document, (direct === undefined) ? result : direct);
})
}, lazy({
_commentProto: d(function self() {
var proto = create(getPrototypeOf(this.document.createComment('')), {
domjs: d(this)
});
forEach(ext._comment, function (value, name) {
defineProperty(proto, name, d(value));
});
return proto;
}),
_textProto: d(function () {
var proto = create(getPrototypeOf(this.document.createTextNode('')), {
domjs: d(this)
});
forEach(ext._text, function (value, name) {
defineProperty(proto, name, d(value));
});
return proto;
})
}), memoizeMethods({
_elementProto: d(function (name) {
var proto = create(getPrototypeOf(this.document.createElement(name)));
if (ext[name]) {
forEach(ext[name], function (value, name) {
if (name in proto) return;
defineProperty(proto, name, d(value));
});
}
forEach(ext._element, function (value, name) {
if (name in proto) return;
defineProperty(proto, name, d(value));
});
defineProperties(proto, {
domjs: d(this),
_directives: d(this.getDirectives(name))
});
return proto;
}),
getDirectives: d(function (name) {
return (this._directives[name] = create(this._directives._element));
})
}), {
ns: d(create(null, autoBind({
comment: d('cew', function (data) {
var el = this._current.appendChild(this.document.createComment(data));
el.__proto__ = this._commentProto;
if (el._construct) el._construct.apply(el, slice.call(arguments, 1));
return el;
}),
text: d('cew', function (data/* …data*/) {
var el = this._current.appendChild(this.document.createTextNode(data));
el.__proto__ = this._textProto;
if (el._construct) el._construct.apply(el, slice.call(arguments, 1));
return el;
}),
element: d('cew', function (name/*[, attributes], …content*/) {
var el = this._current.appendChild(this.document.createElement(name));
el.__proto__ = this._elementProto(name);
construct(el, slice.call(arguments, 1));
return el;
}),
normalize: d('cew', function (node) {
var name = validNode(node).nodeName.toLowerCase();
if (name === '#text') node.__proto__ = this._textProto;
else if (name === '#comment') node.__proto__ = this._commentProto;
else if (name[0] !== '#') node.__proto__ = this._elementProto(name);
else throw new TypeError("Unsupported node type");
return node;
}),
insert: d('cew', function (node/*, …nodes*/) {
var dom = normalize.apply(this.document, arguments);
if (isArray(dom)) dom.forEach(this._current.appendChild, this._current);
else if (dom != null) this._current.appendChild(dom);
return dom;
})
}, { resolveContext: getDomjs })))
}));