-
Notifications
You must be signed in to change notification settings - Fork 1
/
wut.js
180 lines (164 loc) · 5.73 KB
/
wut.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
(function() {
// Creating a shim to replace underscore.js:
var _ = {};
_.first = function(collection) { return collection[0]; };
_.isNull = function(obj) { return obj === null; };
_.isObject = function(obj) { return obj === Object(obj); };
_.isUndefined = function(obj) { return obj === void 0; };
_.isFunction = function(obj) { return typeof obj === 'function'; };
var ObjProto = Object.prototype;
var hasOwnProperty = ObjProto.hasOwnProperty;
_.has = function(obj, key) {
return hasOwnProperty.call(obj, key);
};
var ArrayProto = Array.prototype;
var nativeMap = ArrayProto.map;
_.map = function(obj, iterator) {
var results = [];
if (obj == null) return results;
if (nativeMap && obj.map === nativeMap) return obj.map(iterator);
each(obj, function(value, index, list) {
results.push(iterator.call(value, index, list));
});
return results;
};
var slice = ArrayProto.slice;
_.rest = function(array) {
return slice.call(array, 1);
};
_.last = function(array) {
if (array == null) return void 0;
return array[array.length - 1];
};
var nativeKeys = Object.keys;
_.keys = nativeKeys || function(obj) {
if (obj !== Object(obj)) throw new TypeError('Invalid object');
var keys = [];
for (var key in obj) if (_.has(obj, key)) keys.push(key);
return keys;
};
var nativeForEach = ArrayProto.forEach;
_.each = function(obj, iterator) {
if (obj == null) return;
if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator);
} else if (obj.length === +obj.length) {
for (var i = 0, length = obj.length; i < length; i++) {
if (iterator.call(obj[i], i, obj) === breaker) return;
}
} else {
var keys = _.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) {
if (iterator.call(obj[keys[i]], keys[i], obj) === breaker) return;
}
}
};
// end shim
// Returns a templating function that's sort of curried.
// Rather than take an object with multiple keys and values,
// the returned function takes a single argument.
//var t = function(template, value) {
var t = function(template) {
return function(value) {
return template.split("<%= v %>").join(value);
};
};
// Returns functions that build "key='value'" pairs for HTML attributes.
var makeAttr = function(key) {
return function(value) {
if (_.isNull(value)) {
return t(" <%= v %>")(key);
} else {
var keyString = t(" <%= v %>=")(key);
return t(keyString + "\"<%= v %>\"")(value);
}
};
};
// Creates opening tags, e.g. "<p>" or "<a href='foo'>".
var openTag = function(name, attributes, selfClosing) {
var left = t("<<%= v %>")(name);
var middle = "";
if (!_.isUndefined(attributes)) {
middle = _.map(_.keys(attributes), function(key) {
return makeAttr(key)(attributes[key]);
}).join("");
}
//var right = ">";
var right = (selfClosing) ? "/>" : ">";
return left + middle + right;
};
// Creates closing tags, e.g. "</p>" or "</a>".
var closeTag = function(name) {
return t("</<%= v %>>")(name);
};
// Returns functions that create HTML/XML tags.
// The returned function takes an optional first argument object for the HTML/XML attributes.
// All or the rest of the arguments are concatenated into a single string.
var makeTag = function(name) {
return function() {
var args, value, attributes, selfClosing;
args = Array.prototype.slice.call(arguments);
if (_.isObject(_.first(args))) {
attributes = _.first(args);
selfClosing = (_.rest(args).length === 0);
value = _.rest(args).join("");
if(_.isFunction(_.last(args))) value = value + "();";
} else {
selfClosing = (args.length === 0);
value = args.join("");
};
if(selfClosing) {
return t(openTag(name, attributes, true))(value) + "\n";
} else {
return t(openTag(name, attributes, false) + "\n<%= v %>\n" + closeTag(name))(value) + "\n";
}
};
};
var htmlElements = [
"a","abbr","address","area","article","aside","audio",
"b","base","bdi","bdo","blockquote","body","br","button",
"canvas","caption","cite","code","col","colgroup","command",
"data","datagrid","datalist","dd","del","details","dfn","div","dl","dt",
"em","embed","eventsource",
"fieldset","figcaption","figure","footer","form",
"h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html",
"i","iframe","img","input","ins",
"kbd","keygen","label","legend","li","link",
"mark","map","menu","meta","meter",
"nav","noscript",
"object","ol","optgroup","option","output",
"p","param","pre","progress",
"q",
"ruby","rp","rt",
"s","samp","script","section","select","small","source","span","strong","style","sub","summary","sup",
"table","tbody","td","textarea","tfoot","th","thead","time","title","tr","track",
"u","ul",
"var","video",
"wbr"
];
var doctype = function(type) {
type = type || "html";
return "<!DOCTYPE " + type + ">\n";
}
var pollute = function(scope) {
_.each(htmlElements, function(e) {
scope[e] = makeTag(e);
});
scope.doctype = doctype;
return htmlElements;
}
var isServer = (typeof window === 'undefined');
if (isServer) {
var fs = require('fs');
var minified = fs.readFileSync(__dirname+'/wut.min.js').toString();
var maxified = fs.readFileSync(__dirname+'/wut.js').toString();
module.exports.makeTag = makeTag;
module.exports.pollute = pollute
module.exports.minified = minified;
module.exports.maxified = maxified;
} else {
window.wut = {};
window.wut.makeTag = makeTag;
window.wut.pollute = pollute
}
})();