1 | (function() {
|
2 | var isEqual, macModifierKeyMap, nonMacModifierKeyMap, plus, shiftKeyMap, splitKeyPath, _,
|
3 | __slice = [].slice;
|
4 |
|
5 | _ = require('underscore');
|
6 |
|
7 | macModifierKeyMap = {
|
8 | cmd: '\u2318',
|
9 | ctrl: '\u2303',
|
10 | alt: '\u2325',
|
11 | option: '\u2325',
|
12 | shift: '\u21e7',
|
13 | enter: '\u23ce',
|
14 | left: '\u2190',
|
15 | right: '\u2192',
|
16 | up: '\u2191',
|
17 | down: '\u2193'
|
18 | };
|
19 |
|
20 | nonMacModifierKeyMap = {
|
21 | cmd: 'Cmd',
|
22 | ctrl: 'Ctrl',
|
23 | alt: 'Alt',
|
24 | option: 'Alt',
|
25 | shift: 'Shift',
|
26 | enter: 'Enter',
|
27 | left: 'Left',
|
28 | right: 'Right',
|
29 | up: 'Up',
|
30 | down: 'Down'
|
31 | };
|
32 |
|
33 | shiftKeyMap = {
|
34 | '~': '`',
|
35 | '_': '-',
|
36 | '+': '=',
|
37 | '|': '\\',
|
38 | '{': '[',
|
39 | '}': ']',
|
40 | ':': ';',
|
41 | '"': '\'',
|
42 | '<': ',',
|
43 | '>': '.',
|
44 | '?': '/'
|
45 | };
|
46 |
|
47 | splitKeyPath = function(keyPath) {
|
48 | var char, i, keyPathArray, startIndex, _i, _len;
|
49 | startIndex = 0;
|
50 | keyPathArray = [];
|
51 | for (i = _i = 0, _len = keyPath.length; _i < _len; i = ++_i) {
|
52 | char = keyPath[i];
|
53 | if (char === '.' && (i === 0 || keyPath[i - 1] !== '\\')) {
|
54 | keyPathArray.push(keyPath.substring(startIndex, i));
|
55 | startIndex = i + 1;
|
56 | }
|
57 | }
|
58 | keyPathArray.push(keyPath.substr(startIndex, keyPath.length));
|
59 | return keyPathArray;
|
60 | };
|
61 |
|
62 | plus = {
|
63 | adviseBefore: function(object, methodName, advice) {
|
64 | var original;
|
65 | original = object[methodName];
|
66 | return object[methodName] = function() {
|
67 | var args;
|
68 | args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
69 | if (advice.apply(this, args) !== false) {
|
70 | return original.apply(this, args);
|
71 | }
|
72 | };
|
73 | },
|
74 | camelize: function(string) {
|
75 | if (string) {
|
76 | return string.replace(/[_-]+(\w)/g, function(m) {
|
77 | return m[1].toUpperCase();
|
78 | });
|
79 | } else {
|
80 | return '';
|
81 | }
|
82 | },
|
83 | capitalize: function(word) {
|
84 | if (!word) {
|
85 | return '';
|
86 | }
|
87 | if (word.toLowerCase() === 'github') {
|
88 | return 'GitHub';
|
89 | } else {
|
90 | return word[0].toUpperCase() + word.slice(1);
|
91 | }
|
92 | },
|
93 | compactObject: function(object) {
|
94 | var key, newObject, value;
|
95 | newObject = {};
|
96 | for (key in object) {
|
97 | value = object[key];
|
98 | if (value != null) {
|
99 | newObject[key] = value;
|
100 | }
|
101 | }
|
102 | return newObject;
|
103 | },
|
104 | dasherize: function(string) {
|
105 | if (!string) {
|
106 | return '';
|
107 | }
|
108 | string = string[0].toLowerCase() + string.slice(1);
|
109 | return string.replace(/([A-Z])|(_)/g, function(m, letter) {
|
110 | if (letter) {
|
111 | return "-" + letter.toLowerCase();
|
112 | } else {
|
113 | return "-";
|
114 | }
|
115 | });
|
116 | },
|
117 | deepClone: function(object) {
|
118 | if (_.isArray(object)) {
|
119 | return object.map(function(value) {
|
120 | return plus.deepClone(value);
|
121 | });
|
122 | } else if (_.isObject(object)) {
|
123 | return plus.mapObject(object, (function(_this) {
|
124 | return function(key, value) {
|
125 | return [key, plus.deepClone(value)];
|
126 | };
|
127 | })(this));
|
128 | } else {
|
129 | return object;
|
130 | }
|
131 | },
|
132 | deepExtend: function() {
|
133 | var key, object, objects, result, value, _i, _len;
|
134 | objects = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
|
135 | result = {};
|
136 | for (_i = 0, _len = objects.length; _i < _len; _i++) {
|
137 | object = objects[_i];
|
138 | for (key in object) {
|
139 | value = object[key];
|
140 | if (_.isObject(value) && !_.isArray(value)) {
|
141 | result[key] = plus.deepExtend(result[key], value);
|
142 | } else {
|
143 | if (result[key] == null) {
|
144 | result[key] = value;
|
145 | }
|
146 | }
|
147 | }
|
148 | }
|
149 | return result;
|
150 | },
|
151 | deepContains: function(array, target) {
|
152 | var object, _i, _len;
|
153 | if (array == null) {
|
154 | return false;
|
155 | }
|
156 | for (_i = 0, _len = array.length; _i < _len; _i++) {
|
157 | object = array[_i];
|
158 | if (_.isEqual(object, target)) {
|
159 | return true;
|
160 | }
|
161 | }
|
162 | return false;
|
163 | },
|
164 | endsWith: function(string, suffix) {
|
165 | if (suffix == null) {
|
166 | suffix = '';
|
167 | }
|
168 | if (string) {
|
169 | return string.indexOf(suffix, string.length - suffix.length) !== -1;
|
170 | } else {
|
171 | return false;
|
172 | }
|
173 | },
|
174 | escapeAttribute: function(string) {
|
175 | if (string) {
|
176 | return string.replace(/"/g, '"').replace(/\n/g, '').replace(/\\/g, '-');
|
177 | } else {
|
178 | return '';
|
179 | }
|
180 | },
|
181 | escapeRegExp: function(string) {
|
182 | if (string) {
|
183 | return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
184 | } else {
|
185 | return '';
|
186 | }
|
187 | },
|
188 | humanizeEventName: function(eventName, eventDoc) {
|
189 | var event, namespace, namespaceDoc, _ref;
|
190 | _ref = eventName.split(':'), namespace = _ref[0], event = _ref[1];
|
191 | if (event == null) {
|
192 | return plus.undasherize(namespace);
|
193 | }
|
194 | namespaceDoc = plus.undasherize(namespace);
|
195 | if (eventDoc == null) {
|
196 | eventDoc = plus.undasherize(event);
|
197 | }
|
198 | return "" + namespaceDoc + ": " + eventDoc;
|
199 | },
|
200 | humanizeKey: function(key, platform) {
|
201 | var modifierKeyMap;
|
202 | if (platform == null) {
|
203 | platform = process.platform;
|
204 | }
|
205 | if (!key) {
|
206 | return key;
|
207 | }
|
208 | modifierKeyMap = platform === 'darwin' ? macModifierKeyMap : nonMacModifierKeyMap;
|
209 | if (modifierKeyMap[key]) {
|
210 | return modifierKeyMap[key];
|
211 | } else if (key.length === 1 && (shiftKeyMap[key] != null)) {
|
212 | return [modifierKeyMap.shift, shiftKeyMap[key]];
|
213 | } else if (key.length === 1 && key === key.toUpperCase() && key.toUpperCase() !== key.toLowerCase()) {
|
214 | return [modifierKeyMap.shift, key.toUpperCase()];
|
215 | } else if (key.length === 1 || /f[0-9]{1,2}/.test(key)) {
|
216 | return key.toUpperCase();
|
217 | } else {
|
218 | if (platform === 'darwin') {
|
219 | return key;
|
220 | } else {
|
221 | return plus.capitalize(key);
|
222 | }
|
223 | }
|
224 | },
|
225 | humanizeKeystroke: function(keystroke, platform) {
|
226 | var humanizedKeystrokes, index, key, keys, keystrokes, splitKeystroke, _i, _j, _len, _len1;
|
227 | if (platform == null) {
|
228 | platform = process.platform;
|
229 | }
|
230 | if (!keystroke) {
|
231 | return keystroke;
|
232 | }
|
233 | keystrokes = keystroke.split(' ');
|
234 | humanizedKeystrokes = [];
|
235 | for (_i = 0, _len = keystrokes.length; _i < _len; _i++) {
|
236 | keystroke = keystrokes[_i];
|
237 | keys = [];
|
238 | splitKeystroke = keystroke.split('-');
|
239 | for (index = _j = 0, _len1 = splitKeystroke.length; _j < _len1; index = ++_j) {
|
240 | key = splitKeystroke[index];
|
241 | if (key === '' && splitKeystroke[index - 1] === '') {
|
242 | key = '-';
|
243 | }
|
244 | if (key) {
|
245 | keys.push(plus.humanizeKey(key, platform));
|
246 | }
|
247 | }
|
248 | keys = _.uniq(_.flatten(keys));
|
249 | if (platform === 'darwin') {
|
250 | keys = keys.join('');
|
251 | } else {
|
252 | keys = keys.join('+');
|
253 | }
|
254 | humanizedKeystrokes.push(keys);
|
255 | }
|
256 | return humanizedKeystrokes.join(' ');
|
257 | },
|
258 | isSubset: function(potentialSubset, potentialSuperset) {
|
259 | return _.every(potentialSubset, function(element) {
|
260 | return _.include(potentialSuperset, element);
|
261 | });
|
262 | },
|
263 | losslessInvert: function(hash) {
|
264 | var inverted, key, value;
|
265 | inverted = {};
|
266 | for (key in hash) {
|
267 | value = hash[key];
|
268 | if (inverted[value] == null) {
|
269 | inverted[value] = [];
|
270 | }
|
271 | inverted[value].push(key);
|
272 | }
|
273 | return inverted;
|
274 | },
|
275 | mapObject: function(object, iterator) {
|
276 | var key, newObject, value, _ref;
|
277 | newObject = {};
|
278 | for (key in object) {
|
279 | value = object[key];
|
280 | _ref = iterator(key, value), key = _ref[0], value = _ref[1];
|
281 | newObject[key] = value;
|
282 | }
|
283 | return newObject;
|
284 | },
|
285 | multiplyString: function(string, n) {
|
286 | var finalString, i;
|
287 | finalString = "";
|
288 | i = 0;
|
289 | while (i < n) {
|
290 | finalString += string;
|
291 | i++;
|
292 | }
|
293 | return finalString;
|
294 | },
|
295 | pluralize: function(count, singular, plural) {
|
296 | if (count == null) {
|
297 | count = 0;
|
298 | }
|
299 | if (plural == null) {
|
300 | plural = singular + 's';
|
301 | }
|
302 | if (count === 1) {
|
303 | return "" + count + " " + singular;
|
304 | } else {
|
305 | return "" + count + " " + plural;
|
306 | }
|
307 | },
|
308 | remove: function(array, element) {
|
309 | var index;
|
310 | index = array.indexOf(element);
|
311 | if (index >= 0) {
|
312 | array.splice(index, 1);
|
313 | }
|
314 | return array;
|
315 | },
|
316 | setValueForKeyPath: function(object, keyPath, value) {
|
317 | var key, keys;
|
318 | keys = splitKeyPath(keyPath);
|
319 | while (keys.length > 1) {
|
320 | key = keys.shift();
|
321 | if (object[key] == null) {
|
322 | object[key] = {};
|
323 | }
|
324 | object = object[key];
|
325 | }
|
326 | if (value != null) {
|
327 | return object[keys.shift()] = value;
|
328 | } else {
|
329 | return delete object[keys.shift()];
|
330 | }
|
331 | },
|
332 | hasKeyPath: function(object, keyPath) {
|
333 | var key, keys, _i, _len;
|
334 | keys = splitKeyPath(keyPath);
|
335 | for (_i = 0, _len = keys.length; _i < _len; _i++) {
|
336 | key = keys[_i];
|
337 | if (!object.hasOwnProperty(key)) {
|
338 | return false;
|
339 | }
|
340 | object = object[key];
|
341 | }
|
342 | return true;
|
343 | },
|
344 | spliceWithArray: function(originalArray, start, length, insertedArray, chunkSize) {
|
345 | var chunkStart, _i, _ref, _results;
|
346 | if (chunkSize == null) {
|
347 | chunkSize = 100000;
|
348 | }
|
349 | if (insertedArray.length < chunkSize) {
|
350 | return originalArray.splice.apply(originalArray, [start, length].concat(__slice.call(insertedArray)));
|
351 | } else {
|
352 | originalArray.splice(start, length);
|
353 | _results = [];
|
354 | for (chunkStart = _i = 0, _ref = insertedArray.length; chunkSize > 0 ? _i <= _ref : _i >= _ref; chunkStart = _i += chunkSize) {
|
355 | _results.push(originalArray.splice.apply(originalArray, [start + chunkStart, 0].concat(__slice.call(insertedArray.slice(chunkStart, chunkStart + chunkSize)))));
|
356 | }
|
357 | return _results;
|
358 | }
|
359 | },
|
360 | sum: function(array) {
|
361 | var elt, sum, _i, _len;
|
362 | sum = 0;
|
363 | for (_i = 0, _len = array.length; _i < _len; _i++) {
|
364 | elt = array[_i];
|
365 | sum += elt;
|
366 | }
|
367 | return sum;
|
368 | },
|
369 | uncamelcase: function(string) {
|
370 | var result;
|
371 | if (!string) {
|
372 | return '';
|
373 | }
|
374 | result = string.replace(/([A-Z])|_+/g, function(match, letter) {
|
375 | if (letter == null) {
|
376 | letter = '';
|
377 | }
|
378 | return " " + letter;
|
379 | });
|
380 | return plus.capitalize(result.trim());
|
381 | },
|
382 | undasherize: function(string) {
|
383 | if (string) {
|
384 | return string.split('-').map(plus.capitalize).join(' ');
|
385 | } else {
|
386 | return '';
|
387 | }
|
388 | },
|
389 | underscore: function(string) {
|
390 | if (!string) {
|
391 | return '';
|
392 | }
|
393 | string = string[0].toLowerCase() + string.slice(1);
|
394 | return string.replace(/([A-Z])|-+/g, function(match, letter) {
|
395 | if (letter == null) {
|
396 | letter = '';
|
397 | }
|
398 | return "_" + (letter.toLowerCase());
|
399 | });
|
400 | },
|
401 | valueForKeyPath: function(object, keyPath) {
|
402 | var key, keys, _i, _len;
|
403 | keys = splitKeyPath(keyPath);
|
404 | for (_i = 0, _len = keys.length; _i < _len; _i++) {
|
405 | key = keys[_i];
|
406 | object = object[key];
|
407 | if (object == null) {
|
408 | return;
|
409 | }
|
410 | }
|
411 | return object;
|
412 | },
|
413 | isEqual: function(a, b, aStack, bStack) {
|
414 | if (_.isArray(aStack) && _.isArray(bStack)) {
|
415 | return isEqual(a, b, aStack, bStack);
|
416 | } else {
|
417 | return isEqual(a, b);
|
418 | }
|
419 | },
|
420 | isEqualForProperties: function() {
|
421 | var a, b, properties, property, _i, _len;
|
422 | a = arguments[0], b = arguments[1], properties = 3 <= arguments.length ? __slice.call(arguments, 2) : [];
|
423 | for (_i = 0, _len = properties.length; _i < _len; _i++) {
|
424 | property = properties[_i];
|
425 | if (!_.isEqual(a[property], b[property])) {
|
426 | return false;
|
427 | }
|
428 | }
|
429 | return true;
|
430 | }
|
431 | };
|
432 |
|
433 | isEqual = function(a, b, aStack, bStack) {
|
434 | var aCtor, aCtorValid, aElement, aKeyCount, aValue, bCtor, bCtorValid, bKeyCount, bValue, equal, i, key, stackIndex, _i, _len;
|
435 | if (aStack == null) {
|
436 | aStack = [];
|
437 | }
|
438 | if (bStack == null) {
|
439 | bStack = [];
|
440 | }
|
441 | if (a === b) {
|
442 | return _.isEqual(a, b);
|
443 | }
|
444 | if (_.isFunction(a) || _.isFunction(b)) {
|
445 | return _.isEqual(a, b);
|
446 | }
|
447 | stackIndex = aStack.length;
|
448 | while (stackIndex--) {
|
449 | if (aStack[stackIndex] === a) {
|
450 | return bStack[stackIndex] === b;
|
451 | }
|
452 | }
|
453 | aStack.push(a);
|
454 | bStack.push(b);
|
455 | equal = false;
|
456 | if (_.isFunction(a != null ? a.isEqual : void 0)) {
|
457 | equal = a.isEqual(b, aStack, bStack);
|
458 | } else if (_.isFunction(b != null ? b.isEqual : void 0)) {
|
459 | equal = b.isEqual(a, bStack, aStack);
|
460 | } else if (_.isArray(a) && _.isArray(b) && a.length === b.length) {
|
461 | equal = true;
|
462 | for (i = _i = 0, _len = a.length; _i < _len; i = ++_i) {
|
463 | aElement = a[i];
|
464 | if (!isEqual(aElement, b[i], aStack, bStack)) {
|
465 | equal = false;
|
466 | break;
|
467 | }
|
468 | }
|
469 | } else if (_.isRegExp(a) && _.isRegExp(b)) {
|
470 | equal = _.isEqual(a, b);
|
471 | } else if (_.isElement(a) && _.isElement(b)) {
|
472 | equal = a === b;
|
473 | } else if (_.isObject(a) && _.isObject(b)) {
|
474 | aCtor = a.constructor;
|
475 | bCtor = b.constructor;
|
476 | aCtorValid = _.isFunction(aCtor) && aCtor instanceof aCtor;
|
477 | bCtorValid = _.isFunction(bCtor) && bCtor instanceof bCtor;
|
478 | if (aCtor !== bCtor && !(aCtorValid && bCtorValid)) {
|
479 | equal = false;
|
480 | } else {
|
481 | aKeyCount = 0;
|
482 | equal = true;
|
483 | for (key in a) {
|
484 | aValue = a[key];
|
485 | if (!_.has(a, key)) {
|
486 | continue;
|
487 | }
|
488 | aKeyCount++;
|
489 | if (!(_.has(b, key) && isEqual(aValue, b[key], aStack, bStack))) {
|
490 | equal = false;
|
491 | break;
|
492 | }
|
493 | }
|
494 | if (equal) {
|
495 | bKeyCount = 0;
|
496 | for (key in b) {
|
497 | bValue = b[key];
|
498 | if (_.has(b, key)) {
|
499 | bKeyCount++;
|
500 | }
|
501 | }
|
502 | equal = aKeyCount === bKeyCount;
|
503 | }
|
504 | }
|
505 | } else {
|
506 | equal = _.isEqual(a, b);
|
507 | }
|
508 | aStack.pop();
|
509 | bStack.pop();
|
510 | return equal;
|
511 | };
|
512 |
|
513 | module.exports = _.extend({}, _, plus);
|
514 |
|
515 | }).call(this);
|