UNPKG

213 kBJavaScriptView Raw
1/*!
2 * Copyright (c) 2013 Sune Simonsen <sune@we-knowhow.dk>
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the 'Software'), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var o;"undefined"!=typeof window?o=window:"undefined"!=typeof global?o=global:"undefined"!=typeof self&&(o=self),(o.weknowhow||(o.weknowhow={})).expect=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
25function Assertion(expect, subject, testDescription, flags, alternations, args) {
26 this.expect = expect;
27 this.subject = subject;
28 this.testDescription = testDescription;
29 this.flags = flags;
30 this.alternations = alternations;
31 this.args = args;
32 this.errorMode = 'default';
33}
34
35Assertion.prototype.standardErrorMessage = function () {
36 var expect = this.expect;
37 var output = expect.output.clone();
38
39 var preamble = 'expected';
40
41 var subjectOutput = expect.inspect(this.subject);
42
43 var argsOutput = output.clone();
44 if (this.args.length > 0) {
45 var previousArgWasMagicPen = false;
46 this.args.forEach(function (arg, index) {
47 var isMagicPen = arg && arg.isMagicPen;
48 if (0 < index) {
49 if (!isMagicPen && !previousArgWasMagicPen) {
50 argsOutput.text(',');
51 }
52 argsOutput.text(' ');
53 }
54 if (isMagicPen) {
55 argsOutput.append(arg);
56 } else {
57 argsOutput.append(expect.inspect(arg));
58 }
59 previousArgWasMagicPen = isMagicPen;
60 }, this);
61 }
62
63 var subjectSize = subjectOutput.size();
64 var argsSize = argsOutput.size();
65 var width = preamble.length + subjectSize.width + argsSize.width + this.testDescription.length;
66 var height = Math.max(subjectSize.height, argsSize.height);
67
68 output.error(preamble);
69
70 if (subjectSize.height > 1) {
71 output.nl();
72 } else {
73 output.sp();
74 }
75
76 output.append(subjectOutput);
77
78 if (subjectSize.height > 1 || (height === 1 && width > 120)) {
79 output.nl();
80 } else {
81 output.sp();
82 }
83
84 output.error(this.testDescription);
85
86 if (argsSize.height > 1) {
87 output.nl();
88 } else if (argsSize.width > 0) {
89 output.sp();
90 }
91
92 output.append(argsOutput);
93
94 return output;
95};
96
97Assertion.prototype.shift = function (expect, subject, assertionIndex) {
98 var rest = this.args.slice(assertionIndex);
99 this.args[assertionIndex] = expect.output.clone().error(this.args[assertionIndex]);
100 expect.apply(expect, [subject].concat(rest));
101};
102
103Assertion.prototype.throwStandardError = function () {
104 var err = new Error();
105 err.output = this.standardErrorMessage();
106 err._isUnexpected = true;
107 throw err;
108};
109
110module.exports = Assertion;
111
112},{}],2:[function(require,module,exports){
113/*global setTimeout*/
114var Assertion = require(1);
115var utils = require(6);
116var magicpen = require(19);
117var truncateStack = utils.truncateStack;
118var extend = utils.extend;
119var leven = require(15);
120var cloneError = utils.cloneError;
121
122var anyType = {
123 name: 'any',
124 identify: function () {
125 return true;
126 },
127 equal: function (a, b) {
128 return a === b;
129 },
130 inspect: function (value, depth, output) {
131 return output.text(value);
132 },
133 diff: function (actual, expected, output, diff, inspect) {
134 return null;
135 },
136 is: function (typeOrTypeName) {
137 var typeName;
138 if (typeof typeOrTypeName === 'string') {
139 typeName = typeOrTypeName;
140 } else {
141 typeName = typeOrTypeName.name;
142 }
143 if (this.name === typeName) {
144 return true;
145 } else if (this.baseType) {
146 return this.baseType.is(typeName);
147 } else {
148 return false;
149 }
150 }
151};
152
153function Unexpected(options) {
154 options = options || {};
155 this.assertions = options.assertions || {any: {}};
156 this.typeByName = options.typeByName || {};
157 this.types = options.types || [anyType];
158 this.output = options.output || magicpen();
159 this._outputFormat = options.format || magicpen.defaultFormat;
160 this.installedPlugins = options.installedPlugins || [];
161}
162
163var OR = {};
164function getOrGroups(expectations) {
165 var orGroups = [[]];
166 expectations.forEach(function (expectation) {
167 if (expectation === OR) {
168 orGroups.push([]);
169 } else {
170 orGroups[orGroups.length - 1].push(expectation);
171 }
172 });
173 return orGroups;
174}
175
176function evaluateGroup(expect, subject, orGroup) {
177 var failedGroup = false;
178 return orGroup.map(function (expectation) {
179 var args = Array.prototype.slice.call(expectation);
180 args.unshift(subject);
181 var evaluation = { expectation: args };
182 if (!failedGroup) {
183 evaluation.evaluated = true;
184 try {
185 expect.apply(expect, args);
186 } catch (e) {
187 if (!e._isUnexpected) {
188 throw e;
189 }
190 failedGroup = true;
191 evaluation.failure = e;
192 }
193 }
194
195 return evaluation;
196 });
197}
198
199function writeGroupEvaluationsToOutput(expect, output, groupEvaluations) {
200 var hasOrClauses = groupEvaluations.length > 1;
201 var hasAndClauses = groupEvaluations.some(function (groupEvaluation) {
202 return groupEvaluation.length > 1;
203 });
204 groupEvaluations.forEach(function (groupEvaluation, i) {
205 if (i > 0) {
206 if (hasAndClauses) {
207 output.nl();
208 } else {
209 output.sp();
210 }
211 output.comment('or').nl();
212 }
213
214 groupEvaluation.forEach(function (evaluation, j) {
215 if (j > 0) {
216 output.comment(' and').nl();
217 }
218
219 if (evaluation.failure) {
220 if (hasAndClauses || hasOrClauses) {
221 output.error('⨯ ');
222 }
223
224
225 output.append(evaluation.failure.output);
226 if (!evaluation.failure._hasSerializedErrorMessage) {
227 var comparison = buildDiff(expect, evaluation.failure);
228 if (comparison) {
229 output.nl(2).append(comparison.diff);
230 }
231 }
232 } else {
233 var style = evaluation.evaluated ? 'success' : 'text';
234 var expectation = evaluation.expectation;
235 if (evaluation.evaluated) {
236 output.success('✓ ');
237 } else {
238 output.sp(2);
239 }
240
241 output[style]('expected ');
242 output.text(expect.inspect(expectation[0])).sp();
243 output[style](expectation[1]);
244 expectation.slice(2).forEach(function (v) {
245 output.sp().append(expect.inspect(v));
246 });
247 }
248 });
249 });
250}
251
252function createExpectIt(expect, expectations) {
253 var orGroups = getOrGroups(expectations);
254
255 function expectIt(subject) {
256 var groupEvaluations = orGroups.map(function (orGroup) {
257 return evaluateGroup(expect, subject, orGroup);
258 });
259
260 var failed = groupEvaluations.every(function (groupEvaluation) {
261 return groupEvaluation.some(function (evaluation) {
262 return evaluation.failure;
263 });
264 });
265
266 if (failed) {
267 expect.fail(function (output) {
268 writeGroupEvaluationsToOutput(expect, output, groupEvaluations);
269 });
270 }
271 }
272 expectIt._expectIt = true;
273 expectIt._expectations = expectations;
274 expectIt._OR = OR;
275 expectIt.and = function () {
276 var copiedExpectations = expectations.slice();
277 copiedExpectations.push(arguments);
278 return createExpectIt(expect, copiedExpectations);
279 };
280 expectIt.or = function () {
281 var copiedExpectations = expectations.slice();
282 copiedExpectations.push(OR, arguments);
283 return createExpectIt(expect, copiedExpectations);
284 };
285 return expectIt;
286}
287
288Unexpected.prototype.it = function () { // ...
289 return createExpectIt(this.expect, [arguments]);
290};
291
292Unexpected.prototype.equal = function (actual, expected, depth, seen) {
293 var that = this;
294
295 depth = depth || 0;
296 if (depth > 500) {
297 // detect recursive loops in the structure
298 seen = seen || [];
299 if (seen.indexOf(actual) !== -1) {
300 throw new Error('Cannot compare circular structures');
301 }
302 seen.push(actual);
303 }
304
305 return this.findTypeOf(actual, expected).equal(actual, expected, function (a, b) {
306 return that.equal(a, b, depth + 1, seen);
307 });
308};
309
310Unexpected.prototype.findTypeOf = function () { // ...
311 var objs = Array.prototype.slice.call(arguments);
312 return utils.findFirst(this.types || [], function (type) {
313 return objs.every(function (obj) {
314 return type.identify(obj);
315 });
316 });
317};
318
319Unexpected.prototype.inspect = function (obj, depth) {
320 var seen = [];
321 var that = this;
322 var printOutput = function (obj, currentDepth, output) {
323 if (currentDepth === 0 && typeof obj === 'object') {
324 return output.text('...');
325 }
326
327 seen = seen || [];
328 if (seen.indexOf(obj) !== -1) {
329 return output.text('[Circular]');
330 }
331
332 return that.findTypeOf(obj).inspect(obj, currentDepth, output, function (v, childDepth) {
333 output = output.clone();
334 seen.push(obj);
335 if (typeof childDepth === 'undefined') {
336 childDepth = currentDepth - 1;
337 }
338 return printOutput(v, childDepth, output) || output;
339 });
340 };
341
342 var output = this.output.clone();
343 return printOutput(obj, depth || 3, output) || output;
344};
345
346var placeholderSplitRegexp = /(\{(?:\d+)\})/g;
347var placeholderRegexp = /\{(\d+)\}/;
348Unexpected.prototype.fail = function (arg) {
349 if (utils.isError(arg)) {
350 throw arg;
351 }
352 var output = this.output.clone();
353 if (typeof arg === 'function') {
354 arg.call(this, output);
355 } else {
356 var message = arg || "explicit failure";
357 var args = Array.prototype.slice.call(arguments, 1);
358 var tokens = message.split(placeholderSplitRegexp);
359 tokens.forEach(function (token) {
360 var match = placeholderRegexp.exec(token);
361 if (match) {
362 var index = match[1];
363 var placeholderArg = index in args ? args[index] : match[0];
364 if (placeholderArg.isMagicPen) {
365 output.append(placeholderArg);
366 } else {
367 output.text(placeholderArg);
368 }
369 } else {
370 output.text(token);
371 }
372 });
373 }
374
375 var error = new Error();
376 error._isUnexpected = true;
377 error.output = output;
378 if (nestingLevel === 0) {
379 this.setErrorMessage(error);
380 }
381 throw error;
382};
383
384// addAssertion(pattern, handler)
385// addAssertion([pattern, ...]], handler)
386// addAssertion(typeName, pattern, handler)
387// addAssertion([typeName, ...], pattern, handler)
388// addAssertion([typeName, ...], [pattern, pattern...], handler)
389Unexpected.prototype.addAssertion = function (types, patterns, handler) {
390 if (arguments.length !== 2 && arguments.length !== 3) {
391 throw new Error('addAssertion: Needs 2 or 3 arguments');
392 }
393 if (typeof patterns === 'function') {
394 handler = patterns;
395 patterns = types;
396 types = [anyType];
397 } else {
398 var typeByName = this.typeByName;
399 // Normalize to an array of types, but allow types to be specified by name:
400 types = (Array.isArray(types) ? types : [types]).map(function (type) {
401 if (typeof type === 'string') {
402 if (type in typeByName) {
403 return typeByName[type];
404 } else {
405 throw new Error('No such type: ' + type);
406 }
407 } else {
408 return type;
409 }
410 });
411 }
412 patterns = utils.isArray(patterns) ? patterns : [patterns];
413 var assertions = this.assertions;
414 types.forEach(function (type) {
415 var typeName = type.name;
416 var assertionsForType = assertions[typeName];
417 if (!assertionsForType) {
418 throw new Error('No such type: ' + typeName);
419 }
420 var isSeenByExpandedPattern = {};
421 patterns.forEach(function (pattern) {
422 ensureValidPattern(pattern);
423 expandPattern(pattern).forEach(function (expandedPattern) {
424 if (expandedPattern.text in assertionsForType) {
425 if (!isSeenByExpandedPattern[expandedPattern.text]) {
426 throw new Error('Cannot redefine assertion: ' + expandedPattern.text + (typeName === 'any' ? '' : ' for type ' + typeName));
427 }
428 } else {
429 isSeenByExpandedPattern[expandedPattern.text] = true;
430 assertionsForType[expandedPattern.text] = {
431 handler: handler,
432 flags: expandedPattern.flags,
433 alternations: expandedPattern.alternations
434 };
435 }
436 });
437 });
438 });
439
440 return this.expect; // for chaining
441};
442
443Unexpected.prototype.getType = function (typeName) {
444 return utils.findFirst(this.typeNames, function (type) {
445 return type.name === typeName;
446 });
447};
448
449Unexpected.prototype.addType = function (type) {
450 var that = this;
451 var baseType;
452 if (typeof type.name !== 'string' || type.name.trim() === '') {
453 throw new Error('A type must be given a non-empty name');
454 }
455
456 this.assertions[type.name] = {};
457 this.typeByName[type.name] = type;
458
459 if (type.base) {
460 baseType = utils.findFirst(this.types, function (t) {
461 return t.name === type.base;
462 });
463
464 if (!baseType) {
465 throw new Error('Unknown base type: ' + type.base);
466 }
467 } else {
468 baseType = anyType;
469 }
470
471 var output = this.expect.output;
472 var extendedBaseType = Object.create(baseType);
473 extendedBaseType.inspect = function (value, depth) {
474 return baseType.inspect(value, depth, output.clone(), that.inspect.bind(that));
475 };
476
477 extendedBaseType.diff = function (actual, expected) {
478 return baseType.diff(actual, expected,
479 output.clone(),
480 that.diff.bind(that),
481 that.inspect.bind(that),
482 that.equal.bind(that));
483 };
484
485 extendedBaseType.equal = function (actual, expected) {
486 return baseType.equal(actual, expected, that.equal.bind(that));
487 };
488
489 var extendedType = extend({}, baseType, type, { baseType: extendedBaseType });
490 var inspect = extendedType.inspect;
491
492 extendedType.inspect = function () {
493 if (arguments.length < 2) {
494 return 'type: ' + type.name;
495 } else {
496 return inspect.apply(this, arguments);
497 }
498 };
499 if (extendedType.identify === false) {
500 extendedType.identify = function () {
501 return false;
502 };
503 this.types.push(extendedType);
504 } else {
505 this.types.unshift(extendedType);
506 }
507
508 return this.expect;
509};
510
511Unexpected.prototype.addStyle = function () { // ...
512 return this.output.addStyle.apply(this.output, arguments);
513};
514
515Unexpected.prototype.installPlugin = function (plugin) {
516 var alreadyInstalled = this.installedPlugins.some(function (installedPlugin) {
517 return installedPlugin === plugin.name;
518 });
519
520 if (alreadyInstalled) {
521 return;
522 }
523
524 if (typeof plugin !== 'object' ||
525 typeof plugin.name !== 'string' ||
526 typeof plugin.installInto !== 'function' ||
527 (plugin.dependencies && !Array.isArray(plugin.dependencies))) {
528 throw new Error('Plugins must adhere to the following interface\n' +
529 '{\n' +
530 ' name: <plugin name>,\n' +
531 ' dependencies: <an optional list of dependencies>,\n' +
532 ' installInto: <a function that will update the given expect instance>\n' +
533 '}');
534 }
535
536 if (plugin.dependencies) {
537 var installedPlugins = this.installedPlugins;
538 var unfulfilledDependencies = plugin.dependencies.filter(function (dependency) {
539 return !installedPlugins.some(function (plugin) {
540 return plugin === dependency;
541 });
542 });
543
544 if (unfulfilledDependencies.length === 1) {
545 throw new Error(plugin.name + ' requires plugin ' + unfulfilledDependencies[0]);
546 } else if (unfulfilledDependencies.length > 1) {
547 throw new Error(plugin.name + ' requires plugins ' +
548 unfulfilledDependencies.slice(0, -1).join(', ') +
549 ' and ' + unfulfilledDependencies[unfulfilledDependencies.length - 1]);
550 }
551 }
552
553 this.installedPlugins.push(plugin.name);
554 plugin.installInto(this.expect);
555
556 return this.expect; // for chaining
557};
558
559function errorWithMessage(e, message) {
560 delete e._hasSerializedErrorMessage;
561 var newError = cloneError(e);
562 newError.output = message;
563 return newError;
564}
565
566function buildDiff(expect, err) {
567 return err.createDiff && err.createDiff(expect.output.clone(), function (actual, expected) {
568 return expect.diff(actual, expected);
569 }, function (v, depth) {
570 return expect.inspect(v, depth || Infinity);
571 }, function (actual, expected) {
572 return expect.equal(actual, expected);
573 });
574}
575
576function handleNestedExpects(expect, e, assertion) {
577 var errorMode = e.errorMode || assertion.errorMode;
578 switch (errorMode) {
579 case 'nested':
580 var comparison = buildDiff(expect, e);
581 var message = assertion.standardErrorMessage().nl()
582 .indentLines()
583 .i().block(function (output) {
584 output.append(e.output);
585 if (comparison) {
586 output.nl(2).append(comparison.diff);
587 }
588 });
589 var newError = errorWithMessage(e, message);
590 delete newError.createDiff;
591 return newError;
592 case 'default':
593 return errorWithMessage(e, assertion.standardErrorMessage());
594 case 'bubble':
595 return errorWithMessage(e, e.output);
596 case 'diff':
597 return errorWithMessage(e, e.output.clone().append(function (output) {
598 var comparison = buildDiff(expect, e);
599 delete e.createDiff;
600
601 if (comparison && comparison.diff) {
602 output.append(comparison.diff);
603 } else {
604 output.append(e.output);
605 }
606 }));
607 default:
608 throw new Error("Unknown error mode: '" + assertion.errorMode + "'");
609 }
610}
611
612function installExpectMethods(unexpected, expectFunction) {
613 var expect = expectFunction.bind(unexpected);
614 expect.it = unexpected.it.bind(unexpected);
615 expect.equal = unexpected.equal.bind(unexpected);
616 expect.inspect = unexpected.inspect.bind(unexpected);
617 expect.findTypeOf = unexpected.findTypeOf.bind(unexpected);
618 expect.fail = unexpected.fail.bind(unexpected);
619 expect.diff = unexpected.diff.bind(unexpected);
620 expect.addAssertion = unexpected.addAssertion.bind(unexpected);
621 expect.addType = unexpected.addType.bind(unexpected);
622 expect.clone = unexpected.clone.bind(unexpected);
623 expect.toString = unexpected.toString.bind(unexpected);
624 expect.assertions = unexpected.assertions;
625 expect.installPlugin = unexpected.installPlugin.bind(unexpected);
626 expect.output = unexpected.output;
627 expect.outputFormat = unexpected.outputFormat.bind(unexpected);
628 return expect;
629}
630
631function makeExpectFunction(unexpected) {
632 var expect = installExpectMethods(unexpected, unexpected.expect);
633 unexpected.expect = expect;
634 return expect;
635}
636
637Unexpected.prototype.setErrorMessage = function (err) {
638 if (!err._hasSerializedErrorMessage) {
639 var outputFormat = this.outputFormat();
640 var message = err.output.clone().append(err.output);
641
642 var comparison = buildDiff(this.expect, err);
643 if (comparison) {
644 message.nl(2).append(comparison.diff);
645 }
646 delete err.createDiff;
647
648 if (outputFormat === 'html') {
649 outputFormat = 'text';
650 err.htmlMessage = message.toString('html');
651 }
652 err.output = message;
653 err.message = '\n' + message.toString(outputFormat);
654 err._hasSerializedErrorMessage = true;
655 }
656};
657
658var nestingLevel = 0;
659Unexpected.prototype.expect = function expect(subject, testDescriptionString) {
660 var that = this;
661 if (arguments.length < 2) {
662 throw new Error('The expect function requires at least two parameters.');
663 }
664 if (typeof testDescriptionString !== 'string') {
665 throw new Error('The expect function requires the second parameter to be a string.');
666 }
667 var matchingType = this.findTypeOf(subject);
668 var typeWithAssertion = matchingType;
669 var assertionRule = this.assertions[typeWithAssertion.name][testDescriptionString];
670 while (!assertionRule && typeWithAssertion.name !== anyType.name) {
671 // FIXME: Detect cycles?
672 typeWithAssertion = typeWithAssertion.baseType;
673 assertionRule = this.assertions[typeWithAssertion.name][testDescriptionString];
674 }
675 if (assertionRule) {
676 var flags = extend({}, assertionRule.flags);
677
678 var callInNestedContext = function (callback) {
679 if (nestingLevel === 0) {
680 setTimeout(function () {
681 nestingLevel = 0;
682 }, 0);
683 }
684
685 nestingLevel += 1;
686 try {
687 callback();
688 } catch (e) {
689 if (e._isUnexpected) {
690 truncateStack(e, wrappedExpect);
691 var wrappedError = handleNestedExpects(wrappedExpect, e, assertion);
692 if (nestingLevel === 1) {
693 that.setErrorMessage(wrappedError);
694 }
695 throw wrappedError;
696 }
697 throw e;
698 } finally {
699 nestingLevel -= 1;
700 }
701 };
702
703 var wrappedExpect = function wrappedExpect() {
704 var subject = arguments[0];
705 var testDescriptionString = arguments[1].replace(/\[(!?)([^\]]+)\] ?/g, function (match, negate, flag) {
706 return Boolean(flags[flag]) !== Boolean(negate) ? flag + ' ' : '';
707 }).trim();
708
709 var args = new Array(arguments.length - 2);
710 for (var i = 0; i < arguments.length - 2; i += 1) {
711 args[i] = arguments[i + 2];
712 }
713 callInNestedContext(function () {
714 that.expect.apply(that, [subject, testDescriptionString].concat(args));
715 });
716 };
717
718 // Not sure this is the right way to go about this:
719 wrappedExpect.equal = this.equal;
720 wrappedExpect.types = this.types;
721 wrappedExpect.inspect = this.inspect;
722 wrappedExpect.diff = this.diff;
723 wrappedExpect.findTypeOf = this.findTypeOf;
724 wrappedExpect.output = this.output;
725 wrappedExpect.outputFormat = this.outputFormat;
726 wrappedExpect.fail = function () {
727 var args = arguments;
728 callInNestedContext(function () {
729 that.fail.apply(that, args);
730 });
731 };
732 wrappedExpect.format = this.format;
733 wrappedExpect.it = this.it.bind(this);
734
735 var args = Array.prototype.slice.call(arguments, 2);
736 args.unshift(wrappedExpect, subject);
737 var assertion = new Assertion(wrappedExpect, subject, testDescriptionString,
738 flags, assertionRule.alternations, args.slice(2));
739 var handler = assertionRule.handler;
740 try {
741 handler.apply(assertion, args);
742 } catch (e) {
743 var err = e;
744 if (err._isUnexpected) {
745 truncateStack(err, this.expect);
746 }
747 throw err;
748 }
749 } else {
750 var errorMessage = this.output.clone();
751 var definedForIncompatibleTypes = this.types.filter(function (type) {
752 return this.assertions[type.name][testDescriptionString];
753 }, this);
754 if (definedForIncompatibleTypes.length > 0) {
755 errorMessage.error('The assertion "').strings(testDescriptionString)
756 .error('" is not defined for the type "').strings(matchingType.name).error('",').nl()
757 .error('but it is defined for ');
758 if (definedForIncompatibleTypes.length === 1) {
759 errorMessage.error('the type "').strings(definedForIncompatibleTypes[0].name).error('"');
760 } else {
761 errorMessage.error('these types: ');
762
763
764 definedForIncompatibleTypes.forEach(function (incompatibleType, index) {
765 if (index > 0) {
766 errorMessage.error(', ');
767 }
768 errorMessage.error('"').strings(incompatibleType.name).error('"');
769 });
770 }
771 } else {
772 var assertionsWithScore = [];
773 var bonusForNextMatchingType = 0;
774 [].concat(this.types).reverse().forEach(function (type) {
775 var typeMatchBonus = 0;
776 if (type.identify(subject)) {
777 typeMatchBonus = bonusForNextMatchingType;
778 bonusForNextMatchingType += 0.9;
779 }
780 Object.keys(this.assertions[type.name]).forEach(function (assertion) {
781 assertionsWithScore.push({
782 type: type,
783 assertion: assertion,
784 score: typeMatchBonus - leven(testDescriptionString, assertion)
785 });
786 });
787 }, this);
788 assertionsWithScore.sort(function (a, b) {
789 return b.score - a.score;
790 });
791 errorMessage.error('Unknown assertion "').strings(testDescriptionString)
792 .error('", did you mean: "').strings(assertionsWithScore[0].assertion).error('"');
793 }
794 var missingAssertionError = new Error();
795 missingAssertionError.output = errorMessage;
796 missingAssertionError._isUnexpected = true;
797 missingAssertionError.errorMode = 'bubble';
798 if (nestingLevel === 0) {
799 this.setErrorMessage(missingAssertionError);
800 }
801 this.fail(missingAssertionError);
802 }
803};
804
805Unexpected.prototype.diff = function (a, b) {
806 var output = this.output.clone();
807 var that = this;
808 return this.findTypeOf(a, b).diff(a, b, output, function (actual, expected) {
809 return that.diff(actual, expected);
810 }, function (v, depth) {
811 return that.inspect(v, depth || Infinity);
812 }, function (actual, expected) {
813 return that.equal(actual, expected);
814 });
815};
816
817Unexpected.prototype.toString = function () {
818 var assertions = this.assertions;
819 var isSeenByExpandedPattern = {};
820 Object.keys(assertions).forEach(function (typeName) {
821 Object.keys(assertions[typeName]).forEach(function (expandedPattern) {
822 isSeenByExpandedPattern[expandedPattern] = true;
823 });
824 }, this);
825 return Object.keys(isSeenByExpandedPattern).sort().join('\n');
826};
827
828Unexpected.prototype.clone = function () {
829 var clonedAssertions = {};
830 Object.keys(this.assertions).forEach(function (typeName) {
831 clonedAssertions[typeName] = extend({}, this.assertions[typeName]);
832 }, this);
833 var unexpected = new Unexpected({
834 assertions: clonedAssertions,
835 types: [].concat(this.types),
836 typeByName: extend({}, this.typeByName),
837 output: this.output.clone(),
838 format: this.outputFormat(),
839 installedPlugins: [].concat(this.installedPlugins)
840 });
841 return makeExpectFunction(unexpected);
842};
843
844Unexpected.prototype.outputFormat = function (format) {
845 if (typeof format === 'undefined') {
846 return this._outputFormat;
847 } else {
848 this._outputFormat = format;
849 return this;
850 }
851};
852
853Unexpected.create = function () {
854 var unexpected = new Unexpected();
855 return makeExpectFunction(unexpected);
856};
857
858var expandPattern = (function () {
859 function isFlag(token) {
860 return token.slice(0, 1) === '[' && token.slice(-1) === ']';
861 }
862 function isAlternation(token) {
863 return token.slice(0, 1) === '(' && token.slice(-1) === ')';
864 }
865 function removeEmptyStrings(texts) {
866 return texts.filter(function (text) {
867 return text !== '';
868 });
869 }
870 function createPermutations(tokens, index) {
871 if (index === tokens.length) {
872 return [{ text: '', flags: {}, alternations: [] }];
873 }
874
875 var token = tokens[index];
876 var tail = createPermutations(tokens, index + 1);
877 if (isFlag(token)) {
878 var flag = token.slice(1, -1);
879 return tail.map(function (pattern) {
880 var flags = {};
881 flags[flag] = true;
882 return {
883 text: flag + ' ' + pattern.text,
884 flags: extend(flags, pattern.flags),
885 alternations: pattern.alternations
886 };
887 }).concat(tail.map(function (pattern) {
888 var flags = {};
889 flags[flag] = false;
890 return {
891 text: pattern.text,
892 flags: extend(flags, pattern.flags),
893 alternations: pattern.alternations
894 };
895 }));
896 } else if (isAlternation(token)) {
897 return token
898 .substr(1, token.length - 2) // Remove parentheses
899 .split(/\|/)
900 .reduce(function (result, alternation) {
901 return result.concat(tail.map(function (pattern) {
902 return {
903 text: alternation + pattern.text,
904 flags: pattern.flags,
905 alternations: [alternation].concat(pattern.alternations)
906 };
907 }));
908 }, []);
909 } else {
910 return tail.map(function (pattern) {
911 return {
912 text: token + pattern.text,
913 flags: pattern.flags,
914 alternations: pattern.alternations
915 };
916 });
917 }
918 }
919 return function (pattern) {
920 pattern = pattern.replace(/(\[[^\]]+\]) ?/g, '$1');
921 var splitRegex = /\[[^\]]+\]|\([^\)]+\)/g;
922 var tokens = [];
923 var m;
924 var lastIndex = 0;
925 while ((m = splitRegex.exec(pattern))) {
926 tokens.push(pattern.slice(lastIndex, m.index));
927 tokens.push(pattern.slice(m.index, splitRegex.lastIndex));
928 lastIndex = splitRegex.lastIndex;
929 }
930 tokens.push(pattern.slice(lastIndex));
931 tokens = removeEmptyStrings(tokens);
932 var permutations = createPermutations(tokens, 0);
933 permutations.forEach(function (permutation) {
934 permutation.text = permutation.text.trim();
935 if (permutation.text === '') {
936 // This can only happen if the pattern only contains flags
937 throw new Error("Assertion patterns must not only contain flags");
938 }
939 });
940 return permutations;
941 };
942}());
943
944
945function ensureValidUseOfParenthesesOrBrackets(pattern) {
946 var counts = {
947 '[': 0,
948 ']': 0,
949 '(': 0,
950 ')': 0
951 };
952 for (var i = 0; i < pattern.length; i += 1) {
953 var c = pattern.charAt(i);
954 if (c in counts) {
955 counts[c] += 1;
956 }
957 if (c === ']' && counts['['] >= counts[']']) {
958 if (counts['['] === counts[']'] + 1) {
959 throw new Error("Assertion patterns must not contain flags with brackets: '" + pattern + "'");
960 }
961
962 if (counts['('] !== counts[')']) {
963 throw new Error("Assertion patterns must not contain flags with parentheses: '" + pattern + "'");
964 }
965
966 if (pattern.charAt(i - 1) === '[') {
967 throw new Error("Assertion patterns must not contain empty flags: '" + pattern + "'");
968 }
969 } else if (c === ')' && counts['('] >= counts[')']) {
970 if (counts['('] === counts[')'] + 1) {
971 throw new Error("Assertion patterns must not contain alternations with parentheses: '" + pattern + "'");
972 }
973
974 if (counts['['] !== counts[']']) {
975 throw new Error("Assertion patterns must not contain alternations with brackets: '" + pattern + "'");
976 }
977 }
978 }
979
980 if (counts['['] !== counts[']']) {
981 throw new Error("Assertion patterns must not contain unbalanced brackets: '" + pattern + "'");
982 }
983
984 if (counts['('] !== counts[')']) {
985 throw new Error("Assertion patterns must not contain unbalanced parentheses: '" + pattern + "'");
986 }
987}
988
989function ensureValidPattern(pattern) {
990 if (typeof pattern !== 'string' || pattern === '') {
991 throw new Error("Assertion patterns must be a non empty string");
992 }
993 if (pattern.match(/^\s|\s$/)) {
994 throw new Error("Assertion patterns can't start or end with whitespace");
995 }
996
997 ensureValidUseOfParenthesesOrBrackets(pattern);
998}
999
1000module.exports = Unexpected;
1001
1002},{}],3:[function(require,module,exports){
1003var utils = require(6);
1004var isRegExp = utils.isRegExp;
1005var isArray = utils.isArray;
1006var extend = utils.extend;
1007
1008module.exports = function (expect) {
1009 expect.addAssertion('[not] to be (ok|truthy)', function (expect, subject) {
1010 var not = !!this.flags.not;
1011 var condition = !!subject;
1012 if (condition === not) {
1013 expect.fail();
1014 }
1015 });
1016
1017 expect.addAssertion('[not] to be', function (expect, subject, value) {
1018 expect(subject === value, '[not] to be truthy');
1019 });
1020
1021 expect.addAssertion('string', '[not] to be', function (expect, subject, value) {
1022 expect(subject, '[not] to equal', value);
1023 });
1024
1025 expect.addAssertion('boolean', '[not] to be true', function (expect, subject) {
1026 expect(subject, '[not] to be', true);
1027 });
1028
1029 expect.addAssertion('boolean', '[not] to be false', function (expect, subject) {
1030 expect(subject, '[not] to be', false);
1031 });
1032
1033 expect.addAssertion('[not] to be falsy', function (expect, subject) {
1034 expect(subject, '[!not] to be truthy');
1035 });
1036
1037 expect.addAssertion('[not] to be null', function (expect, subject) {
1038 expect(subject, '[not] to be', null);
1039 });
1040
1041 expect.addAssertion('[not] to be undefined', function (expect, subject) {
1042 expect(typeof subject, '[not] to be', 'undefined');
1043 });
1044
1045 expect.addAssertion('to be defined', function (expect, subject) {
1046 expect(subject, 'not to be undefined');
1047 });
1048
1049 expect.addAssertion('number', '[not] to be NaN', function (expect, subject) {
1050 expect(isNaN(subject), '[not] to be truthy');
1051 });
1052
1053 expect.addAssertion('number', '[not] to be close to', function (expect, subject, value, epsilon) {
1054 this.errorMode = 'bubble';
1055 if (typeof epsilon !== 'number') {
1056 epsilon = 1e-9;
1057 }
1058 try {
1059 expect(Math.abs(subject - value), '[not] to be less than or equal to', epsilon);
1060 } catch (e) {
1061 expect.fail('expected {0} {1} {2} (epsilon: {3})',
1062 expect.inspect(subject),
1063 this.testDescription,
1064 expect.inspect(value),
1065 epsilon.toExponential());
1066 }
1067 });
1068
1069 expect.addAssertion('[not] to be (a|an)', function (expect, subject, type) {
1070 if ('string' === typeof type) {
1071 var subjectType = expect.findTypeOf(subject);
1072 type = /^reg(?:exp?|ular expression)$/.test(type) ? 'regexp' : type;
1073 expect(subjectType.is(type), '[not] to be truthy');
1074 } else {
1075 expect(subject instanceof type, '[not] to be truthy');
1076 }
1077
1078 return this;
1079 });
1080
1081 // Alias for common '[not] to be (a|an)' assertions
1082 expect.addAssertion('[not] to be (a|an) (boolean|number|string|function|object|array|regexp|regex|regular expression)', function (expect, subject) {
1083 expect(subject, '[not] to be ' + this.alternations[0], this.alternations[1]);
1084 });
1085
1086 expect.addAssertion(['string', 'arrayLike'], 'to be (the empty|an empty|a non-empty) (string|array)', function (expect, subject) {
1087 expect(subject, 'to be a', this.alternations[1]);
1088 expect(subject, this.alternations[0] === 'a non-empty' ? 'not to be empty' : 'to be empty');
1089 });
1090
1091 expect.addAssertion('[not] to match', function (expect, subject, regexp) {
1092 subject = String(subject);
1093 try {
1094 expect(String(subject).match(regexp), '[not] to be truthy');
1095 } catch (e) {
1096 if (e._isUnexpected) {
1097 e.label = 'should match';
1098 if (this.flags.not) {
1099 e.createDiff = function (output) {
1100 var lastIndex = 0;
1101 function flushUntilIndex(i) {
1102 if (i > lastIndex) {
1103 output.text(subject.substring(lastIndex, i));
1104 lastIndex = i;
1105 }
1106 }
1107 subject.replace(new RegExp(regexp.source, 'g'), function ($0, index) {
1108 flushUntilIndex(index);
1109 lastIndex += $0.length;
1110 output.diffRemovedHighlight($0);
1111 });
1112 flushUntilIndex(subject.length);
1113 return {diff: output};
1114 };
1115 }
1116 }
1117 expect.fail(e);
1118 }
1119 });
1120
1121 expect.addAssertion('object', '[not] to have [own] property', function (expect, subject, key, value) {
1122 if (arguments.length === 4) {
1123 expect(subject, 'to have [own] property', key);
1124 expect(subject[key], '[not] to equal', value);
1125 } else {
1126 expect(this.flags.own ?
1127 subject && subject.hasOwnProperty(key) :
1128 subject && subject[key] !== undefined,
1129 '[not] to be truthy');
1130 }
1131 });
1132
1133 expect.addAssertion('object', '[not] to have [own] properties', function (expect, subject, properties) {
1134 if (properties && isArray(properties)) {
1135 properties.forEach(function (property) {
1136 expect(subject, '[not] to have [own] property', property);
1137 });
1138 } else if (properties && typeof properties === 'object') {
1139 // TODO the not flag does not make a lot of sense in this case
1140 var flags = this.flags;
1141 if (flags.not) {
1142 Object.keys(properties).forEach(function (property) {
1143 expect(subject, 'not to have [own] property', property);
1144 });
1145 } else {
1146 try {
1147 Object.keys(properties).forEach(function (property) {
1148 var value = properties[property];
1149 if (typeof value === 'undefined') {
1150 expect(subject, 'not to have [own] property', property);
1151 } else {
1152 expect(subject, 'to have [own] property', property, value);
1153 }
1154 });
1155 } catch (e) {
1156 if (e._isUnexpected) {
1157 e.createDiff = function (output, diff) {
1158 var expected = extend({}, properties);
1159 var actual = {};
1160 for (var propertyName in subject) {
1161 if ((!flags.own || subject.hasOwnProperty(propertyName)) && !(propertyName in properties)) {
1162 expected[propertyName] = subject[propertyName];
1163 }
1164 if (!flags.own && !(propertyName in actual)) {
1165 actual[propertyName] = subject[propertyName];
1166 }
1167 }
1168 return diff(actual, expected);
1169 };
1170 }
1171 expect.fail(e);
1172 }
1173 }
1174 } else {
1175 throw new Error("Assertion '" + this.testDescription + "' only supports " +
1176 "input in the form of an Array or an Object.");
1177 }
1178 });
1179
1180 expect.addAssertion(['string', 'object'], '[not] to have length', function (expect, subject, length) {
1181 if ((!subject && typeof subject !== 'string') || typeof subject.length !== 'number') {
1182 throw new Error("Assertion '" + this.testDescription +
1183 "' only supports array like objects");
1184 }
1185 expect(subject.length, '[not] to be', length);
1186 });
1187
1188 expect.addAssertion(['string', 'object'], '[not] to be empty', function (expect, subject) {
1189 var length;
1190 if (isArray(subject) || typeof subject === 'string' || typeof subject.length === 'number') {
1191 length = subject.length;
1192 } else if (subject && typeof subject === 'object') {
1193 length = Object.keys(subject).length;
1194 }
1195 expect(length, '[not] to be', 0);
1196 });
1197
1198 expect.addAssertion(['string', 'arrayLike'], 'to be non-empty', function (expect, subject) {
1199 expect(subject, 'not to be empty');
1200 });
1201
1202 expect.addAssertion('object', ['to [not] [only] have (key|keys)', '[not] to have (key|keys)'], function (expect, subject, keys) {
1203 keys = isArray(keys) ?
1204 keys :
1205 Array.prototype.slice.call(arguments, 2);
1206
1207 var hasKeys = subject && keys.every(function (key) {
1208 return subject.hasOwnProperty(key);
1209 });
1210 if (this.flags.only) {
1211 expect(hasKeys, 'to be truthy');
1212 expect(Object.keys(subject).length === keys.length, '[not] to be truthy');
1213 } else {
1214 expect(hasKeys, '[not] to be truthy');
1215 }
1216 });
1217
1218 expect.addAssertion('string', '[not] to contain', function (expect, subject) {
1219 var args = Array.prototype.slice.call(arguments, 2);
1220 try {
1221 args.forEach(function (arg) {
1222 expect(subject.indexOf(arg) !== -1, '[not] to be truthy');
1223 });
1224 } catch (e) {
1225 if (e._isUnexpected && this.flags.not) {
1226 e.createDiff = function (output) {
1227 var lastIndex = 0;
1228 function flushUntilIndex(i) {
1229 if (i > lastIndex) {
1230 output.text(subject.substring(lastIndex, i));
1231 lastIndex = i;
1232 }
1233 }
1234 subject.replace(new RegExp(args.map(function (arg) {
1235 return utils.escapeRegExpMetaChars(String(arg));
1236 }).join('|'), 'g'), function ($0, index) {
1237 flushUntilIndex(index);
1238 lastIndex += $0.length;
1239 output.diffRemovedHighlight($0);
1240 });
1241 flushUntilIndex(subject.length);
1242 return {diff: output};
1243 };
1244 }
1245 expect.fail(e);
1246 }
1247 });
1248
1249 expect.addAssertion('arrayLike', '[not] to contain', function (expect, subject) {
1250 var args = Array.prototype.slice.call(arguments, 2);
1251 try {
1252 args.forEach(function (arg) {
1253 expect(subject && Array.prototype.some.call(subject, function (item) { return expect.equal(item, arg); }), '[not] to be truthy');
1254 });
1255 } catch (e) {
1256 if (e._isUnexpected && this.flags.not) {
1257 e.createDiff = function (output, diff, inspect, equal) {
1258 return diff(subject, Array.prototype.filter.call(subject, function (item) {
1259 return !args.some(function (arg) {
1260 return equal(item, arg);
1261 });
1262 }));
1263 };
1264 }
1265 expect.fail(e);
1266 }
1267 });
1268
1269 expect.addAssertion('number', '[not] to be finite', function (expect, subject) {
1270 expect(isFinite(subject), '[not] to be truthy');
1271 });
1272
1273 expect.addAssertion('number', '[not] to be infinite', function (expect, subject) {
1274 expect(!isNaN(subject) && !isFinite(subject), '[not] to be truthy');
1275 });
1276
1277 expect.addAssertion(['number', 'string'], '[not] to be within', function (expect, subject, start, finish) {
1278 this.args = [start + '..' + finish];
1279 expect(subject >= start && subject <= finish, '[not] to be truthy');
1280 });
1281
1282 expect.addAssertion(['number', 'string'], ['<', '[not] to be (<|less than|below)'], function (expect, subject, value) {
1283 expect(subject < value, '[not] to be truthy');
1284 });
1285
1286 expect.addAssertion(['number', 'string'], ['<=', '[not] to be (<=|less than or equal to)'], function (expect, subject, value) {
1287 expect(subject <= value, '[not] to be truthy');
1288 });
1289
1290 expect.addAssertion(['number', 'string'], ['>', '[not] to be (>|greater than|above)'], function (expect, subject, value) {
1291 expect(subject > value, '[not] to be truthy');
1292 });
1293
1294 expect.addAssertion(['number', 'string'], ['>=', '[not] to be (>=|greater than or equal to)'], function (expect, subject, value) {
1295 expect(subject >= value, '[not] to be truthy');
1296 });
1297
1298 expect.addAssertion('number', '[not] to be positive', function (expect, subject) {
1299 expect(subject, '[not] to be >', 0);
1300 });
1301
1302 expect.addAssertion('number', '[not] to be negative', function (expect, subject) {
1303 expect(subject, '[not] to be <', 0);
1304 });
1305
1306 expect.addAssertion('[not] to equal', function (expect, subject, value) {
1307 try {
1308 expect(expect.equal(value, subject), '[not] to be truthy');
1309 } catch (e) {
1310 if (e._isUnexpected) {
1311 e.label = 'should equal';
1312 if (!this.flags.not) {
1313 e.createDiff = function (output, diff) {
1314 return diff(subject, value);
1315 };
1316 }
1317 }
1318 expect.fail(e);
1319 }
1320 });
1321
1322 expect.addAssertion('function', '[not] to (throw|throw error|throw exception)', function (expect, subject, arg) {
1323 this.errorMode = 'nested';
1324
1325 var thrown = false;
1326 var argType = typeof arg;
1327
1328 try {
1329 subject();
1330 } catch (e) {
1331 if ('function' === argType) {
1332 arg(e);
1333 } else {
1334 var message,
1335 isUnexpected = e && e._isUnexpected;
1336 if (isUnexpected) {
1337 message = e.output.toString();
1338 } else if (e && Object.prototype.toString.call(e) === '[object Error]') {
1339 message = e.message;
1340 } else {
1341 message = String(e);
1342 }
1343
1344 if ('string' === argType) {
1345 expect(message, '[not] to equal', arg);
1346 } else if (isRegExp(arg)) {
1347 expect(message, '[not] to match', arg);
1348 } else if (this.flags.not) {
1349 expect.fail('threw: {0}', isUnexpected ? e.output : expect.inspect(e));
1350 }
1351 }
1352 thrown = true;
1353 }
1354
1355 this.errorMode = 'default';
1356 if ('string' === argType || isRegExp(arg)) {
1357 // in the presence of a matcher, ensure the `not` only applies to
1358 // the matching.
1359 expect(thrown, 'to be truthy');
1360 } else {
1361 expect(thrown, '[not] to be truthy');
1362 }
1363 });
1364
1365 expect.addAssertion('function', 'to have arity', function (expect, subject, value) {
1366 expect(subject.length, 'to equal', value);
1367 });
1368
1369 expect.addAssertion('object', 'to be (a|an) [non-empty] (map|hash|object) whose values satisfy', function (expect, subject) {
1370 var extraArgs = Array.prototype.slice.call(arguments, 2);
1371 if (extraArgs.length === 0) {
1372 throw new Error('Assertion "' + this.testDescription + '" expects a third argument');
1373 }
1374 this.errorMode = 'nested';
1375 expect(subject, 'to be an object');
1376 if (this.flags['non-empty']) {
1377 expect(subject, 'not to equal', {});
1378 }
1379 this.errorMode = 'bubble';
1380
1381 var errors = {};
1382 expect.findTypeOf(subject).getKeys(subject).forEach(function (key, index) {
1383 try {
1384 if (typeof extraArgs[0] === 'function') {
1385 extraArgs[0](subject[key], index);
1386 } else {
1387 expect.apply(expect, [subject[key], 'to satisfy assertion'].concat(extraArgs));
1388 }
1389 } catch (e) {
1390 errors[key] = e;
1391 }
1392 }, this);
1393
1394 var errorKeys = Object.keys(errors);
1395 if (errorKeys.length > 0) {
1396 expect.fail(function (output) {
1397 var subjectOutput = expect.inspect(subject);
1398 output.error('failed expectation in');
1399 if (subjectOutput.size().height > 1) {
1400 output.nl();
1401 } else {
1402 output.sp();
1403 }
1404 subjectOutput.error(':');
1405 output.block(subjectOutput).nl();
1406 output.indentLines();
1407
1408 errorKeys.forEach(function (key, index) {
1409 var error = errors[key];
1410 output.i().text(key).text(': ');
1411 if (error._isUnexpected) {
1412 output.block(error.output);
1413 } else {
1414 output.block(output.clone().text(error.message));
1415 }
1416
1417 if (index < errorKeys.length - 1) {
1418 output.nl();
1419 }
1420 });
1421 });
1422 }
1423 });
1424
1425 expect.addAssertion('arrayLike', 'to be (a|an) [non-empty] array whose items satisfy', function (expect, subject) { // ...
1426 var extraArgs = Array.prototype.slice.call(arguments, 2);
1427 if (extraArgs.length === 0) {
1428 throw new Error('Assertion "' + this.testDescription + '" expects a third argument');
1429 }
1430 this.errorMode = 'nested';
1431 if (this.flags['non-empty']) {
1432 expect(subject, 'to be non-empty');
1433 }
1434 this.errorMode = 'bubble';
1435 expect.apply(expect, [subject, 'to be a map whose values satisfy'].concat(extraArgs));
1436 });
1437
1438 expect.addAssertion('arrayLike', 'to be (a|an) [non-empty] array of (strings|numbers|booleans|arrays|objects|functions|regexps|regexes|regular expressions)', function (expect, subject) {
1439 if (this.flags['non-empty']) {
1440 expect(subject, 'to be non-empty');
1441 }
1442 var type = this.alternations[1].replace(/e?s$/, '');
1443 expect(subject, 'to be an array whose items satisfy', 'to be a', type);
1444 });
1445
1446 expect.addAssertion('object', 'to be (a|an) [non-empty] (map|hash|object) whose (keys|properties) satisfy', function (expect, subject) {
1447 var extraArgs = Array.prototype.slice.call(arguments, 2);
1448 if (extraArgs.length === 0) {
1449 throw new Error('Assertion "' + this.testDescription + '" expects a third argument');
1450 }
1451 this.errorMode = 'nested';
1452 expect(subject, 'to be an object');
1453 if (this.flags['non-empty']) {
1454 expect(subject, 'not to equal', {});
1455 }
1456 this.errorMode = 'bubble';
1457
1458 var errors = {};
1459 Object.keys(subject).forEach(function (key, index) {
1460 try {
1461 if (typeof extraArgs[0] === 'function') {
1462 extraArgs[0](key, subject[key]);
1463 } else {
1464 expect.apply(expect, [key, 'to satisfy assertion'].concat(extraArgs));
1465 }
1466 } catch (e) {
1467 errors[key] = e;
1468 }
1469 });
1470
1471 var errorKeys = Object.keys(errors);
1472 if (errorKeys.length > 0) {
1473 expect.fail(function (output) {
1474 output.error('failed expectation on keys ')
1475 .text(Object.keys(subject).join(', '))
1476 .error(':').nl()
1477 .indentLines();
1478
1479 errorKeys.forEach(function (key, index) {
1480 var error = errors[key];
1481 output.i().text(key).text(': ');
1482 if (error._isUnexpected) {
1483 output.block(error.output);
1484 } else {
1485 output.block(output.clone().text(error.message));
1486 }
1487
1488 if (index < errorKeys.length - 1) {
1489 output.nl();
1490 }
1491 });
1492 });
1493 }
1494 });
1495
1496 expect.addAssertion('object', 'to be canonical', function (expect, subject) {
1497 var stack = [];
1498
1499 (function traverse(obj) {
1500 var i;
1501 for (i = 0 ; i < stack.length ; i += 1) {
1502 if (stack[i] === obj) {
1503 return;
1504 }
1505 }
1506 if (obj && typeof obj === 'object') {
1507 var keys = Object.keys(obj);
1508 for (i = 0 ; i < keys.length - 1 ; i += 1) {
1509 expect(keys[i], 'to be less than', keys[i + 1]);
1510 }
1511 stack.push(obj);
1512 keys.forEach(function (key) {
1513 traverse(obj[key]);
1514 });
1515 stack.pop();
1516 }
1517 }(subject));
1518 });
1519
1520 expect.addAssertion('Error', 'to [exhaustively] satisfy [assertion]', function (expect, subject, value) {
1521 var valueType = expect.findTypeOf(value);
1522 if (valueType.is('Error')) {
1523 expect(subject, 'to equal', value);
1524 } else if (valueType.is('object')) {
1525 var keys = valueType.getKeys(value);
1526 keys.forEach(function (key) {
1527 expect(subject[key], 'to [exhaustively] satisfy', value[key]);
1528 });
1529 if (this.flags.exhaustively) {
1530 expect(utils.getKeysOfDefinedProperties(subject), 'to have length', keys.filter(function (key) {
1531 return typeof value[key] !== 'undefined';
1532 }).length);
1533 }
1534 } else {
1535 expect(subject.message, 'to [exhaustively] satisfy', value);
1536 }
1537 });
1538
1539 expect.addAssertion('[not] to [exhaustively] satisfy [assertion]', function (expect, subject, value) {
1540 if (this.flags.not) {
1541 try {
1542 expect(subject, 'to [exhaustively] satisfy [assertion]', value);
1543 } catch (e) {
1544 if (!e || !e._isUnexpected) {
1545 throw e;
1546 }
1547 return;
1548 }
1549 expect.fail();
1550 } else if (this.flags.assertion && typeof value === 'string') {
1551 this.errorMode = 'bubble'; // to satisfy assertion 'to be a number' => to be a number
1552 expect.apply(expect, Array.prototype.slice.call(arguments, 1));
1553 } else if (value && value._expectIt) {
1554 try {
1555 value(subject);
1556 } catch (e) {
1557 if (e._isUnexpected) {
1558 e.createDiff = function (output, diff, inspect, equal) {
1559 return {
1560 diff: output.append(e.output),
1561 inline: false
1562 };
1563 };
1564 }
1565 expect.fail(e);
1566 }
1567 } else if (typeof value === 'function') {
1568 value(subject);
1569 } else if (isRegExp(value)) {
1570 expect(subject, 'to match', value);
1571 } else {
1572 var type = expect.findTypeOf(subject, value);
1573 if (type.is('arrayLike') || type.is('object')) {
1574 try {
1575 expect(subject, 'to be an object');
1576 var keys = type.getKeys(value);
1577 keys.forEach(function (key) {
1578 expect(subject[key], 'to [exhaustively] satisfy', value[key]);
1579 });
1580 if (this.flags.exhaustively) {
1581 expect(subject, 'to only have keys', keys);
1582 }
1583 } catch (e) {
1584 if (e._isUnexpected) {
1585 var flags = this.flags;
1586 e.createDiff = function (output, diff, inspect, equal) {
1587 var result = {
1588 diff: output,
1589 inline: true
1590 };
1591
1592 var keyIndex = {};
1593 Object.keys(subject).concat(Object.keys(value)).forEach(function (key) {
1594 if (!(key in result)) {
1595 keyIndex[key] = key;
1596 }
1597 });
1598
1599 var keys = Object.keys(keyIndex);
1600
1601 output.text('{').nl().indentLines();
1602
1603 keys.forEach(function (key, index) {
1604 output.i().block(function () {
1605 var valueOutput;
1606 var annotation = output.clone();
1607 var conflicting;
1608 try {
1609 expect(subject[key], 'to [exhaustively] satisfy', value[key]);
1610 } catch (e) {
1611 if (!e._isUnexpected && !value[key]._expectIt) {
1612 expect.fail(e);
1613 }
1614 conflicting = e;
1615 }
1616 var isInlineDiff = true;
1617 if (conflicting) {
1618 if (!(key in value)) {
1619 if (flags.exhaustively) {
1620 annotation.error('should be removed');
1621 }
1622 } else {
1623 var keyDiff = conflicting.createDiff && conflicting.createDiff(output.clone(), diff, inspect, equal);
1624 isInlineDiff = !keyDiff || keyDiff.inline ;
1625 if (value[key] && value[key]._expectIt) {
1626 if (keyDiff && keyDiff.diff) {
1627 annotation.append(keyDiff.diff);
1628 } else {
1629 annotation.error('should satisfy ').append(inspect(value[key])).nl();
1630 if (conflicting._isUnexpected) {
1631 annotation.append(conflicting.output);
1632 } else {
1633 annotation.error(conflicting.message);
1634 }
1635 }
1636 } else if (!keyDiff || (keyDiff && !keyDiff.inline)) {
1637 annotation.error(conflicting.label || 'should satisfy').sp()
1638 .block(inspect(value[key]));
1639
1640 if (keyDiff) {
1641 annotation.nl().append(keyDiff.diff);
1642 }
1643 } else {
1644 valueOutput = keyDiff.diff;
1645 }
1646 }
1647 }
1648
1649 var last = index === keys.length - 1;
1650 if (!valueOutput) {
1651 valueOutput = inspect(subject[key], conflicting ? Infinity : 1);
1652 }
1653
1654 if (/^[a-z\$\_][a-z0-9\$\_]*$/i.test(key)) {
1655 this.key(key);
1656 } else {
1657 this.append(inspect(key));
1658 }
1659 this.text(':').sp();
1660 valueOutput.text(last ? '' : ',');
1661
1662 if (isInlineDiff) {
1663 this.append(valueOutput);
1664 } else {
1665 this.block(valueOutput);
1666 }
1667 if (!annotation.isEmpty()) {
1668 this.sp().annotationBlock(annotation);
1669 }
1670 }).nl();
1671 });
1672
1673 output.outdentLines().text('}');
1674
1675 return result;
1676 };
1677 }
1678 expect.fail(e);
1679 }
1680 } else {
1681 expect(subject, 'to equal', value);
1682 }
1683 }
1684 });
1685
1686 function wrapDiffWithTypePrefixAndSuffix(e, type) {
1687 if (e._isUnexpected) {
1688 var createDiff = e.createDiff;
1689 e.createDiff = function (output) { // ...
1690 type.prefix.call(e, output);
1691 var result = createDiff.apply(this, arguments);
1692 type.suffix.call(e, output);
1693 return result;
1694 };
1695 }
1696 return e;
1697 }
1698
1699 expect.addAssertion('wrapperObject', 'to [exhaustively] satisfy', function (expect, subject, value) {
1700 var valueType = expect.findTypeOf(value);
1701 if (valueType.is('wrapperObject')) {
1702 var type = expect.findTypeOf(subject, value);
1703 expect(type.is('wrapperObject'), 'to be truthy');
1704 try {
1705 expect(type.unwrap(subject), 'to [exhaustively] satisfy', type.unwrap(value));
1706 } catch (e) {
1707 expect.fail(wrapDiffWithTypePrefixAndSuffix(e, type));
1708 }
1709 } else {
1710 var subjectType = expect.findTypeOf(subject);
1711 expect(subjectType.is('wrapperObject'), 'to be truthy');
1712 try {
1713 expect(subjectType.unwrap(subject), 'to [exhaustively] satisfy', value);
1714 } catch (e) {
1715 e.label = 'should satisfy';
1716 expect.fail(wrapDiffWithTypePrefixAndSuffix(e, subjectType));
1717 }
1718
1719 }
1720 });
1721
1722 expect.addAssertion('function', 'when called with', function (expect, subject, args) { // ...
1723 this.shift(expect, subject.apply(subject, args), 1);
1724 });
1725
1726 expect.addAssertion('array', 'when passed as parameters to', function (expect, subject, fn) { // ...
1727 this.shift(expect, fn.apply(fn, subject), 1);
1728 });
1729};
1730
1731},{}],4:[function(require,module,exports){
1732module.exports = function (expect) {
1733 expect.output.addStyle('error', function (content) {
1734 this.text(content, 'red', 'bold');
1735 });
1736 expect.output.addStyle('success', function (content) {
1737 this.text(content, 'green', 'bold');
1738 });
1739 expect.output.addStyle('strings', function (content) {
1740 this.text(content, '#00A0A0');
1741 });
1742 expect.output.addStyle('key', function (content) {
1743 this.text(content, '#666');
1744 });
1745 expect.output.addStyle('number', function (content) {
1746 this.text(content);
1747 });
1748 expect.output.addStyle('comment', function (content) {
1749 this.gray(content);
1750 });
1751 expect.output.addStyle('regexp', function (content) {
1752 this.green(content);
1753 });
1754 expect.output.addStyle('diffAddedLine', function (content) {
1755 this.text(content, 'green');
1756 });
1757 expect.output.addStyle('diffAddedHighlight', function (content) {
1758 this.text(content, 'bgGreen', 'white');
1759 });
1760 expect.output.addStyle('diffAddedSpecialChar', function (content) {
1761 this.text(content, 'bgGreen', 'cyan', 'bold');
1762 });
1763 expect.output.addStyle('diffRemovedLine', function (content) {
1764 this.text(content, 'red');
1765 });
1766 expect.output.addStyle('diffRemovedHighlight', function (content) {
1767 this.text(content, 'bgRed', 'white');
1768 });
1769 expect.output.addStyle('diffRemovedSpecialChar', function (content) {
1770 this.text(content, 'bgRed', 'cyan', 'bold');
1771 });
1772 // Intended to be redefined by a plugin that offers syntax highlighting:
1773 expect.output.addStyle('code', function (content, language) {
1774 this.text(content);
1775 });
1776
1777 expect.output.addStyle('annotationBlock', function () {
1778 var pen = this.getContentFromArguments(arguments);
1779 var height = pen.size().height;
1780
1781 if (height > 0) {
1782 this.block(function () {
1783 for (var i = 0; i < height; i += 1) {
1784 if (0 < i) {
1785 this.nl();
1786 }
1787 this.error('// ');
1788 }
1789 });
1790 this.block(pen);
1791 }
1792 });
1793
1794};
1795
1796},{}],5:[function(require,module,exports){
1797(function (Buffer){
1798var utils = require(6);
1799var isRegExp = utils.isRegExp;
1800var leftPad = utils.leftPad;
1801var extend = utils.extend;
1802var arrayDiff = require(8);
1803var leven = require(15);
1804
1805module.exports = function (expect) {
1806 expect.addType({
1807 name: 'wrapperObject',
1808 identify: false,
1809 equal: function (a, b, equal) {
1810 return a === b || equal(this.unwrap(a), this.unwrap(b));
1811 },
1812 inspect: function (value, depth, output, inspect) {
1813 output.append(this.prefix(output.clone()));
1814 output.append(inspect(this.unwrap(value)));
1815 output.append(this.suffix(output.clone()));
1816 },
1817 diff: function (actual, expected, output, diff, inspect) {
1818 actual = this.unwrap(actual);
1819 expected = this.unwrap(expected);
1820 var comparison = diff(actual, expected);
1821 var prefixOutput = this.prefix(output.clone());
1822 var suffixOutput = this.suffix(output.clone());
1823 if (comparison && comparison.inline) {
1824 return {
1825 inline: true,
1826 diff: output.append(prefixOutput).append(comparison.diff).append(suffixOutput)
1827 };
1828 } else {
1829 return {
1830 inline: true,
1831 diff: output.append(prefixOutput).nl()
1832 .indentLines()
1833 .i().block(function () {
1834 this.append(inspect(actual)).sp().annotationBlock(function () {
1835 this.error('should be ').block(inspect(expected));
1836 if (comparison) {
1837 this.nl().append(comparison.diff);
1838 }
1839 });
1840 }).nl()
1841 .outdentLines()
1842 .append(suffixOutput)
1843 };
1844 }
1845 }
1846 });
1847
1848 expect.addType({
1849 name: 'object',
1850 identify: function (obj) {
1851 return obj && typeof obj === 'object';
1852 },
1853 getKeys: Object.keys,
1854 equal: function (a, b, equal) {
1855 if (a === b) {
1856 return true;
1857 }
1858
1859 if (b.constructor !== a.constructor) {
1860 return false;
1861 }
1862
1863 var actualKeys = utils.getKeysOfDefinedProperties(a),
1864 expectedKeys = utils.getKeysOfDefinedProperties(b),
1865 key,
1866 i;
1867
1868 // having the same number of owned properties (keys incorporates hasOwnProperty)
1869 if (actualKeys.length !== expectedKeys.length) {
1870 return false;
1871 }
1872 //the same set of keys (although not necessarily the same order),
1873 actualKeys.sort();
1874 expectedKeys.sort();
1875 //~~~cheap key test
1876 for (i = actualKeys.length - 1; i >= 0; i -= 1) {
1877 if (actualKeys[i] !== expectedKeys[i]) {
1878 return false;
1879 }
1880 }
1881
1882 //equivalent values for every corresponding key, and
1883 //~~~possibly expensive deep test
1884 for (i = actualKeys.length - 1; i >= 0; i -= 1) {
1885 key = actualKeys[i];
1886 if (!equal(a[key], b[key])) {
1887 return false;
1888 }
1889 }
1890 return true;
1891 },
1892 inspect: function (obj, depth, output, inspect) {
1893 var keys = Object.keys(obj);
1894 if (keys.length === 0) {
1895 return output.text('{}');
1896 }
1897
1898 var inspectedItems = keys.map(function (key) {
1899 var propertyOutput = output.clone();
1900 if (/^[a-z\$\_][a-z0-9\$\_]*$/i.test(key)) {
1901 propertyOutput.key(key);
1902 } else {
1903 propertyOutput.append(inspect(key, depth));
1904 }
1905 propertyOutput.text(':');
1906
1907 var hasGetter = obj.__lookupGetter__ && obj.__lookupGetter__(key);
1908 var hasSetter = obj.__lookupGetter__ && obj.__lookupSetter__(key);
1909
1910 if (hasGetter || !hasSetter) {
1911 var value = obj[key];
1912 var inspectedValue = inspect(value);
1913 if (value && value._expectIt) {
1914 propertyOutput.sp().block(inspectedValue);
1915 } else {
1916 propertyOutput.sp().append(inspectedValue);
1917 }
1918 }
1919
1920 if (hasGetter && hasSetter) {
1921 propertyOutput.sp().text('[Getter/Setter]');
1922 } else if (hasGetter) {
1923 propertyOutput.sp().text('[Getter]');
1924 } else if (hasSetter) {
1925 propertyOutput.sp().text('[Setter]');
1926 }
1927
1928 return propertyOutput;
1929 });
1930
1931 var width = 0;
1932 var multipleLines = inspectedItems.some(function (o) {
1933 var size = o.size();
1934 width += size.width;
1935 return width > 50 || size.height > 1;
1936 });
1937
1938 inspectedItems.forEach(function (inspectedItem, index) {
1939 var lastIndex = index === inspectedItems.length - 1;
1940
1941 if (!lastIndex) {
1942 inspectedItem.text(',');
1943 }
1944 });
1945
1946 if (multipleLines) {
1947 output.text('{').nl().indentLines();
1948
1949 inspectedItems.forEach(function (inspectedItem, index) {
1950 output.i().block(inspectedItem).nl();
1951 });
1952
1953 output.outdentLines().text('}');
1954 } else {
1955 output.text('{ ');
1956 inspectedItems.forEach(function (inspectedItem, index) {
1957 output.append(inspectedItem);
1958 var lastIndex = index === inspectedItems.length - 1;
1959 if (!lastIndex) {
1960 output.sp();
1961 }
1962 });
1963 output.text(' }');
1964 }
1965 },
1966 diff: function (actual, expected, output, diff, inspect, equal) {
1967 if (actual.constructor !== expected.constructor) {
1968 return {
1969 diff: output.text('Mismatching constructors ')
1970 .text(actual.constructor.name || actual.constructor)
1971 .text(' should be ').text(expected.constructor.name || expected.constructor),
1972 inline: false
1973 };
1974 }
1975
1976 var result = {
1977 diff: output,
1978 inline: true
1979 };
1980
1981 var keyIndex = {};
1982 Object.keys(actual).concat(Object.keys(expected)).forEach(function (key) {
1983 if (!(key in result)) {
1984 keyIndex[key] = key;
1985 }
1986 });
1987
1988 var keys = Object.keys(keyIndex);
1989
1990 output.text('{').nl().indentLines();
1991
1992 keys.forEach(function (key, index) {
1993 output.i().block(function () {
1994 var valueOutput;
1995 var annotation = output.clone();
1996 var conflicting = !equal(actual[key], expected[key]);
1997 var isInlineDiff = false;
1998 if (conflicting) {
1999 if (!(key in expected)) {
2000 annotation.error('should be removed');
2001 } else {
2002 var keyDiff = diff(actual[key], expected[key]);
2003 if (!keyDiff || (keyDiff && !keyDiff.inline)) {
2004 annotation.error('should be ')
2005 .block(inspect(expected[key]));
2006
2007 if (keyDiff) {
2008 annotation.nl().append(keyDiff.diff);
2009 }
2010 } else {
2011 isInlineDiff = true;
2012 valueOutput = keyDiff.diff;
2013 }
2014 }
2015 }
2016
2017 var last = index === keys.length - 1;
2018 if (!valueOutput) {
2019 valueOutput = inspect(actual[key], conflicting ? Infinity : 1);
2020 }
2021
2022 if (/^[a-z\$\_][a-z0-9\$\_]*$/i.test(key)) {
2023 this.key(key);
2024 } else {
2025 this.append(inspect(key));
2026 }
2027 this.text(':').sp();
2028 valueOutput.text(last ? '' : ',');
2029 if (isInlineDiff) {
2030 this.append(valueOutput);
2031 } else {
2032 this.block(valueOutput);
2033 }
2034 if (!annotation.isEmpty()) {
2035 this.sp().annotationBlock(annotation);
2036 }
2037 }).nl();
2038 });
2039
2040 output.outdentLines().text('}');
2041
2042 return result;
2043 }
2044 });
2045
2046 function structurallySimilar(a, b) {
2047 var typeA = typeof a;
2048 var typeB = typeof b;
2049
2050 if (typeA !== typeB) {
2051 return false;
2052 }
2053
2054 if (typeA === 'string') {
2055 return leven(a, b) < a.length / 2;
2056 }
2057
2058 if (typeA !== 'object' || !a) {
2059 return false;
2060 }
2061
2062 if (utils.isArray(a) && utils.isArray(b)) {
2063 return true;
2064 }
2065
2066 var aKeys = Object.keys(a);
2067 var bKeys = Object.keys(b);
2068 var numberOfSimilarKeys = 0;
2069 var requiredSimilarKeys = Math.round(Math.max(aKeys.length, bKeys.length) / 2);
2070 return aKeys.concat(bKeys).some(function (key) {
2071 if (key in a && key in b) {
2072 numberOfSimilarKeys += 1;
2073 }
2074
2075 return numberOfSimilarKeys >= requiredSimilarKeys;
2076 });
2077 }
2078
2079 expect.addType({
2080 name: 'arrayLike',
2081 base: 'object',
2082 identify: function (obj) {
2083 return obj && typeof obj === 'object' && typeof obj.length === 'number';
2084 },
2085 getKeys: function (obj) {
2086 var keys = new Array(obj.length);
2087 for (var i = 0 ; i < obj.length ; i += 1) {
2088 keys[i] = i;
2089 }
2090 return keys;
2091 },
2092 equal: function (a, b, equal) {
2093 return a === b || (a.constructor === b.constructor && a.length === b.length && Array.prototype.every.call(a, function (v, index) {
2094 return equal(v, b[index]);
2095 }));
2096 },
2097 prefix: function (output) {
2098 return output.text('[');
2099 },
2100 suffix: function (output) {
2101 return output.text(']');
2102 },
2103 inspect: function (arr, depth, output, inspect) {
2104 var prefixOutput = this.prefix(output.clone(), arr);
2105 var suffixOutput = this.suffix(output.clone(), arr);
2106 if (arr.length === 0) {
2107 return output.append(prefixOutput).append(suffixOutput);
2108 }
2109
2110 if (depth === 1) {
2111 return output.append(prefixOutput).text('...').append(suffixOutput);
2112 }
2113
2114 if (!Array.isArray(arr)) {
2115 arr = Array.prototype.slice.call(arr);
2116 }
2117
2118 var inspectedItems = arr.map(function (v) {
2119 return inspect(v);
2120 });
2121
2122 var width = 0;
2123 var multipleLines = inspectedItems.some(function (o) {
2124 var size = o.size();
2125 width += size.width;
2126 return width > 50 || o.height > 1;
2127 });
2128
2129 inspectedItems.forEach(function (inspectedItem, index) {
2130 var lastIndex = index === inspectedItems.length - 1;
2131 if (!lastIndex) {
2132 inspectedItem.text(',');
2133 }
2134 });
2135
2136 if (multipleLines) {
2137 output.append(prefixOutput).nl().indentLines();
2138
2139 inspectedItems.forEach(function (inspectedItem, index) {
2140 output.i().block(inspectedItem).nl();
2141 });
2142
2143 output.outdentLines().append(suffixOutput);
2144 } else {
2145 output.append(prefixOutput).sp();
2146 inspectedItems.forEach(function (inspectedItem, index) {
2147 output.append(inspectedItem);
2148 var lastIndex = index === inspectedItems.length - 1;
2149 if (!lastIndex) {
2150 output.sp();
2151 }
2152 });
2153 output.sp().append(suffixOutput);
2154 }
2155 },
2156 diffLimit: 512,
2157 diff: function (actual, expected, output, diff, inspect, equal) {
2158 var result = {
2159 diff: output,
2160 inline: true
2161 };
2162
2163 if (Math.max(actual.length, expected.length) > this.diffLimit) {
2164 result.diff.comment('Diff suppressed due to size > ' + this.diffLimit);
2165 return result;
2166 }
2167
2168 if (actual.constructor !== expected.constructor) {
2169 return this.baseType.diff(actual, expected);
2170 }
2171
2172 if (!Array.isArray(actual)) {
2173 actual = Array.prototype.slice.call(actual);
2174 }
2175 if (!Array.isArray(expected)) {
2176 expected = Array.prototype.slice.call(expected);
2177 }
2178
2179 var mutatedArray = actual.map(function (v) {
2180 return {
2181 type: 'similar',
2182 value: v
2183 };
2184 });
2185
2186 if (mutatedArray.length > 0) {
2187 mutatedArray[mutatedArray.length - 1].last = true;
2188 }
2189
2190 var itemsDiff = arrayDiff(actual, expected, function (a, b) {
2191 return equal(a, b) || structurallySimilar(a, b);
2192 });
2193
2194 var removeTable = [];
2195 function offsetIndex(index) {
2196 return index + (removeTable[index - 1] || 0);
2197 }
2198
2199 var removes = itemsDiff.filter(function (diffItem) {
2200 return diffItem.type === 'remove';
2201 });
2202
2203 var removesByIndex = {};
2204 var removedItems = 0;
2205 removes.forEach(function (diffItem) {
2206 var removeIndex = removedItems + diffItem.index;
2207 mutatedArray.slice(removeIndex, diffItem.howMany + removeIndex).forEach(function (v) {
2208 v.type = 'remove';
2209 });
2210 removedItems += diffItem.howMany;
2211 removesByIndex[diffItem.index] = removedItems;
2212 });
2213
2214 function updateRemoveTable() {
2215 removedItems = 0;
2216 actual.forEach(function (_, index) {
2217 removedItems += removesByIndex[index] || 0;
2218 removeTable[index] = removedItems;
2219 });
2220 }
2221
2222 updateRemoveTable();
2223
2224 var moves = itemsDiff.filter(function (diffItem) {
2225 return diffItem.type === 'move';
2226 });
2227
2228 var movedItems = 0;
2229 moves.forEach(function (diffItem) {
2230 var moveFromIndex = offsetIndex(diffItem.from);
2231 var removed = mutatedArray.slice(moveFromIndex, diffItem.howMany + moveFromIndex);
2232 var added = removed.map(function (v) {
2233 return utils.extend({}, v, { type: 'insert' });
2234 });
2235 removed.forEach(function (v) {
2236 v.type = 'remove';
2237 });
2238 Array.prototype.splice.apply(mutatedArray, [offsetIndex(diffItem.to), 0].concat(added));
2239 movedItems += diffItem.howMany;
2240 removesByIndex[diffItem.from] = movedItems;
2241 updateRemoveTable();
2242 });
2243
2244 var inserts = itemsDiff.filter(function (diffItem) {
2245 return diffItem.type === 'insert';
2246 });
2247
2248 inserts.forEach(function (diffItem) {
2249 var added = diffItem.values.map(function (v) {
2250 return {
2251 type: 'insert',
2252 value: v
2253 };
2254 });
2255 Array.prototype.splice.apply(mutatedArray, [offsetIndex(diffItem.index), 0].concat(added));
2256 });
2257
2258 var offset = 0;
2259 mutatedArray.forEach(function (diffItem, index) {
2260 var type = diffItem.type;
2261 if (type === 'remove') {
2262 offset -= 1;
2263 } else if (type === 'similar') {
2264 diffItem.expected = expected[offset + index];
2265 }
2266 });
2267
2268 var conflicts = mutatedArray.reduce(function (conflicts, item) {
2269 return item.type === 'similar' ? conflicts : conflicts + 1;
2270 }, 0);
2271
2272 for (var i = 0, c = 0; i < Math.max(actual.length, expected.length) && c <= conflicts; i += 1) {
2273 var expectedType = typeof expected[i];
2274 var actualType = typeof actual[i];
2275
2276 if (
2277 actualType !== expectedType ||
2278 ((actualType === 'object' || actualType === 'string') && !structurallySimilar(actual[i], expected[i])) ||
2279 (actualType !== 'object' && actualType !== 'string' && !equal(actual[i], expected[i]))
2280 ) {
2281 c += 1;
2282 }
2283 }
2284
2285 if (c <= conflicts) {
2286 mutatedArray = [];
2287 var j;
2288 for (j = 0; j < Math.min(actual.length, expected.length); j += 1) {
2289 mutatedArray.push({
2290 type: 'similar',
2291 value: actual[j],
2292 expected: expected[j]
2293 });
2294 }
2295
2296 if (actual.length < expected.length) {
2297 for (; j < Math.max(actual.length, expected.length); j += 1) {
2298 mutatedArray.push({
2299 type: 'insert',
2300 value: expected[j]
2301 });
2302 }
2303 } else {
2304 for (; j < Math.max(actual.length, expected.length); j += 1) {
2305 mutatedArray.push({
2306 type: 'remove',
2307 value: actual[j]
2308 });
2309 }
2310 }
2311 mutatedArray[mutatedArray.length - 1].last = true;
2312 }
2313
2314 output.append(this.prefix(output.clone())).nl().indentLines();
2315
2316 mutatedArray.forEach(function (diffItem, index) {
2317 output.i().block(function () {
2318 var type = diffItem.type;
2319 var last = !!diffItem.last;
2320
2321 if (type === 'insert') {
2322 this.annotationBlock(function () {
2323 this.error('missing ').block(inspect(diffItem.value));
2324 });
2325 } else if (type === 'remove') {
2326 this.block(inspect(diffItem.value).text(last ? ' ' : ', ').error('// should be removed'));
2327 } else if (equal(diffItem.value, diffItem.expected)) {
2328 this.block(inspect(diffItem.value).text(last ? '' : ','));
2329 } else {
2330 var valueDiff = diff(diffItem.value, diffItem.expected);
2331 if (valueDiff && valueDiff.inline) {
2332 this.block(valueDiff.diff.text(last ? '' : ','));
2333 } else if (valueDiff) {
2334 this.block(inspect(diffItem.value).text(last ? ' ' : ', ')).annotationBlock(function () {
2335 this.error('should be ').block(inspect(diffItem.expected)).nl()
2336 .append(valueDiff.diff);
2337 });
2338 } else {
2339 this.block(inspect(diffItem.value).text(last ? ' ' : ', ')).annotationBlock(function () {
2340 this.error('should be ').block(inspect(diffItem.expected));
2341 });
2342 }
2343 }
2344 }).nl();
2345 });
2346
2347 output.outdentLines().append(this.suffix(output.clone()));
2348
2349 return result;
2350 }
2351 });
2352
2353 expect.addType({
2354 name: 'array',
2355 base: 'arrayLike',
2356 identify: function (arr) {
2357 return utils.isArray(arr);
2358 }
2359 });
2360
2361 expect.addType({
2362 name: 'arguments',
2363 base: 'arrayLike',
2364 prefix: function (output) {
2365 return output.text('arguments(', 'cyan');
2366 },
2367 suffix: function (output) {
2368 return output.text(')', 'cyan');
2369 },
2370 identify: function (obj) {
2371 return Object.prototype.toString.call(obj) === '[object Arguments]';
2372 }
2373 });
2374
2375 expect.addType({
2376 base: 'object',
2377 name: 'Error',
2378 identify: function (value) {
2379 return utils.isError(value);
2380 },
2381 equal: function (a, b, equal) {
2382 return a === b ||
2383 (equal(a.message, b.message) && this.baseType.equal(a, b));
2384 },
2385 inspect: function (value, depth, output, inspect) {
2386 var errorObject = extend({
2387 message: value.message
2388 }, value);
2389 output.text('[Error: ').append(inspect(errorObject, depth)).text(']');
2390 },
2391 diff: function (actual, expected, output, diff) {
2392 return diff(extend({
2393 message: actual.message
2394 }, actual), extend({
2395 message: expected.message
2396 }, expected));
2397 }
2398 });
2399
2400 expect.addType({
2401 name: 'date',
2402 identify: function (obj) {
2403 return Object.prototype.toString.call(obj) === '[object Date]';
2404 },
2405 equal: function (a, b) {
2406 return a.getTime() === b.getTime();
2407 },
2408 inspect: function (date, depth, output) {
2409 output.text('[Date ').text(date.toUTCString()).text(']');
2410 }
2411 });
2412
2413 expect.addType({
2414 base: 'object',
2415 name: 'function',
2416 identify: function (f) {
2417 return typeof f === 'function';
2418 },
2419 equal: function (a, b) {
2420 return a === b || a.toString() === b.toString();
2421 },
2422 inspect: function (f, depth, output, inspect) {
2423 var source = f.toString();
2424 var name;
2425 var args;
2426 var body;
2427 var matchSource = source.match(/^function (\w*)?\s*\(([^\)]*)\)\s*\{([\s\S]*?( *)?)\}$/);
2428 if (matchSource) {
2429 name = matchSource[1];
2430 args = matchSource[2];
2431 body = matchSource[3];
2432 var bodyIndent = matchSource[4] || '';
2433 if (!/\\\n/.test(body)) {
2434 body = body.replace(new RegExp('^ {' + bodyIndent.length + '}', 'mg'), '');
2435 }
2436 if (!name || name === 'anonymous') {
2437 name = '';
2438 }
2439 if (/^\s*\[native code\]\s*$/.test(body)) {
2440 body = ' /* native code */ ';
2441 } else {
2442 body = body.replace(/^((?:.*\n){3}( *).*\n)[\s\S]*?\n((?:.*\n){3})$/, '$1$2// ... lines removed ...\n$3');
2443 }
2444 } else {
2445 name = f.name || '';
2446 args = ' /*...*/ ';
2447 body = ' /*...*/ ';
2448 }
2449 output.code('function ' + name + '(' + args + ') {' + body + '}', 'javascript');
2450 }
2451 });
2452
2453 expect.addType({
2454 base: 'function',
2455 name: 'expect.it',
2456 identify: function (f) {
2457 return typeof f === 'function' && f._expectIt;
2458 },
2459 inspect: function (f, depth, output, inspect) {
2460 output.text('expect.it(');
2461 var orBranch = false;
2462 f._expectations.forEach(function (expectation, index) {
2463 if (expectation === f._OR) {
2464 orBranch = true;
2465 return;
2466 }
2467
2468 if (orBranch) {
2469 output.text(')\n .or(');
2470 } else if (0 < index) {
2471 output.text(')\n .and(');
2472 }
2473
2474 var args = Array.prototype.slice.call(expectation);
2475 args.forEach(function (arg, i) {
2476 if (0 < i) {
2477 output.text(', ');
2478 }
2479 output.append(inspect(arg));
2480 });
2481 orBranch = false;
2482 });
2483
2484 output.text(')');
2485 }
2486 });
2487
2488 expect.addType({
2489 name: 'regexp',
2490 identify: isRegExp,
2491 equal: function (a, b) {
2492 return a === b || (
2493 a.source === b.source &&
2494 a.global === b.global &&
2495 a.ignoreCase === b.ignoreCase &&
2496 a.multiline === b.multiline
2497 );
2498 },
2499 inspect: function (regExp, depth, output) {
2500 output.regexp(regExp);
2501 }
2502 });
2503
2504 expect.addType({
2505 name: 'DomElement',
2506 identify: function (value) {
2507 return utils.isDOMElement(value);
2508 },
2509 inspect: function (value, depth, output) {
2510 output.code(utils.getOuterHTML(value), 'html');
2511 }
2512 });
2513
2514 expect.addType({
2515 name: 'binaryArray',
2516 base: 'arrayLike',
2517 digitWidth: 2,
2518 hexDumpWidth: 16,
2519 identify: false,
2520 equal: function (a, b) {
2521 if (a === b) {
2522 return true;
2523 }
2524
2525 if (a.length !== b.length) return false;
2526
2527 for (var i = 0; i < a.length; i += 1) {
2528 if (a[i] !== b[i]) return false;
2529 }
2530
2531 return true;
2532 },
2533 hexDump: function (obj, maxLength) {
2534 var hexDump = '';
2535 if (typeof maxLength !== 'number' || maxLength === 0) {
2536 maxLength = obj.length;
2537 }
2538 for (var i = 0 ; i < maxLength ; i += this.hexDumpWidth) {
2539 if (hexDump.length > 0) {
2540 hexDump += '\n';
2541 }
2542 var hexChars = '',
2543 asciiChars = ' │';
2544
2545 for (var j = 0 ; j < this.hexDumpWidth ; j += 1) {
2546 if (i + j < maxLength) {
2547 var octet = obj[i + j];
2548 hexChars += leftPad(octet.toString(16).toUpperCase(), this.digitWidth, '0') + ' ';
2549 asciiChars += String.fromCharCode(octet).replace(/\n/g, '␊').replace(/\r/g, '␍');
2550 } else if (this.digitWidth === 2) {
2551 hexChars += ' ';
2552 }
2553 }
2554
2555 if (this.digitWidth === 2) {
2556 hexDump += hexChars + asciiChars + '│';
2557 } else {
2558 hexDump += hexChars.replace(/\s+$/, '');
2559 }
2560 }
2561 return hexDump;
2562 },
2563 inspect: function (obj, depth, output) {
2564 var codeStr = this.name + '([';
2565 for (var i = 0 ; i < Math.min(this.hexDumpWidth, obj.length) ; i += 1) {
2566 if (i > 0) {
2567 codeStr += ', ';
2568 }
2569 var octet = obj[i];
2570 codeStr += '0x' + leftPad(octet.toString(16).toUpperCase(), this.digitWidth, '0');
2571 }
2572 if (obj.length > this.hexDumpWidth) {
2573 codeStr += ' /* ' + (obj.length - this.hexDumpWidth) + ' more */ ';
2574 }
2575 codeStr += '])';
2576 output.code(codeStr, 'javascript');
2577 },
2578 diffLimit: 512,
2579 diff: function (actual, expected, output, diff, inspect) {
2580 var result = {diff: output};
2581 if (Math.max(actual.length, expected.length) > this.diffLimit) {
2582 result.diff.comment('Diff suppressed due to size > ' + this.diffLimit);
2583 } else {
2584 result.diff = utils.diffStrings(this.hexDump(actual), this.hexDump(expected), output, {type: 'Chars', markUpSpecialCharacters: false})
2585 .replaceText(/[\x00-\x1f\x7f-\xff␊␍]/g, '.').replaceText(/[│ ]/g, function (styles, content) {
2586 this.text(content);
2587 });
2588 }
2589 return result;
2590 }
2591 });
2592
2593 if (typeof Buffer !== 'undefined') {
2594 expect.addType({
2595 name: 'Buffer',
2596 base: 'binaryArray',
2597 identify: Buffer.isBuffer
2598 });
2599 }
2600
2601 [8, 16, 32].forEach(function (numBits) {
2602 ['Int', 'Uint'].forEach(function (intOrUint) {
2603 var constructorName = intOrUint + numBits + 'Array',
2604 Constructor = this[constructorName];
2605 if (typeof Constructor !== 'undefined') {
2606 expect.addType({
2607 name: constructorName,
2608 base: 'binaryArray',
2609 hexDumpWidth: 128 / numBits,
2610 digitWidth: numBits / 4,
2611 identify: function (obj) {
2612 return obj instanceof Constructor;
2613 }
2614 });
2615 }
2616 }, this);
2617 }, this);
2618
2619 expect.addType({
2620 name: 'string',
2621 identify: function (value) {
2622 return typeof value === 'string';
2623 },
2624 inspect: function (value, depth, output) {
2625 output.strings('\'')
2626 .strings(JSON.stringify(value).replace(/^"|"$/g, '')
2627 .replace(/'/g, "\\'")
2628 .replace(/\\"/g, '"'))
2629 .strings('\'');
2630 },
2631 diff: function (actual, expected, output, diff, inspect) {
2632 var result = {
2633 diff: output,
2634 inline: false
2635 };
2636 utils.diffStrings(actual, expected, output, {type: 'WordsWithSpace', markUpSpecialCharacters: true});
2637 return result;
2638 }
2639 });
2640
2641 expect.addType({
2642 name: 'number',
2643 identify: function (value) {
2644 return typeof value === 'number';
2645 },
2646 inspect: function (value, depth, output) {
2647 output.number(value);
2648 }
2649 });
2650
2651 expect.addType({
2652 name: 'boolean',
2653 identify: function (value) {
2654 return typeof value === 'boolean';
2655 }
2656 });
2657
2658 expect.addType({
2659 name: 'undefined',
2660 identify: function (value) {
2661 return typeof value === 'undefined';
2662 }
2663 });
2664
2665 expect.addType({
2666 name: 'null',
2667 identify: function (value) {
2668 return value === null;
2669 }
2670 });
2671};
2672
2673}).call(this,require(9).Buffer)
2674},{}],6:[function(require,module,exports){
2675var stringDiff = require(14);
2676
2677var errorMethodBlacklist = ['message', 'line', 'sourceId', 'sourceURL', 'stack', 'stackArray'].reduce(function (result, prop) {
2678 result[prop] = true;
2679 return result;
2680}, {});
2681
2682var specialCharRegexp = /([\x00-\x09\x0B-\x1F\x7F-\x9F\xAD\u0378\u0379\u037F-\u0383\u038B\u038D\u03A2\u0528-\u0530\u0557\u0558\u0560\u0588\u058B-\u058E\u0590\u05C8-\u05CF\u05EB-\u05EF\u05F5-\u0605\u061C\u061D\u06DD\u070E\u070F\u074B\u074C\u07B2-\u07BF\u07FB-\u07FF\u082E\u082F\u083F\u085C\u085D\u085F-\u089F\u08A1\u08AD-\u08E3\u08FF\u0978\u0980\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09FC-\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF2-\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B55\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B78-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BFB-\u0C00\u0C04\u0C0D\u0C11\u0C29\u0C34\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5A-\u0C5F\u0C64\u0C65\u0C70-\u0C77\u0C80\u0C81\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0D01\u0D04\u0D0D\u0D11\u0D3B\u0D3C\u0D45\u0D49\u0D4F-\u0D56\u0D58-\u0D5F\u0D64\u0D65\u0D76-\u0D78\u0D80\u0D81\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DF1\u0DF5-\u0E00\u0E3B-\u0E3E\u0E5C-\u0E80\u0E83\u0E85\u0E86\u0E89\u0E8B\u0E8C\u0E8E-\u0E93\u0E98\u0EA0\u0EA4\u0EA6\u0EA8\u0EA9\u0EAC\u0EBA\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F48\u0F6D-\u0F70\u0F98\u0FBD\u0FCD\u0FDB-\u0FFF\u10C6\u10C8-\u10CC\u10CE\u10CF\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u137D-\u137F\u139A-\u139F\u13F5-\u13FF\u169D-\u169F\u16F1-\u16FF\u170D\u1715-\u171F\u1737-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17DE\u17DF\u17EA-\u17EF\u17FA-\u17FF\u180F\u181A-\u181F\u1878-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191D-\u191F\u192C-\u192F\u193C-\u193F\u1941-\u1943\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DB-\u19DD\u1A1C\u1A1D\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1A9F\u1AAE-\u1AFF\u1B4C-\u1B4F\u1B7D-\u1B7F\u1BF4-\u1BFB\u1C38-\u1C3A\u1C4A-\u1C4C\u1C80-\u1CBF\u1CC8-\u1CCF\u1CF7-\u1CFF\u1DE7-\u1DFB\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FC5\u1FD4\u1FD5\u1FDC\u1FF0\u1FF1\u1FF5\u1FFF\u200B-\u200F\u202A-\u202E\u2060-\u206F\u2072\u2073\u208F\u209D-\u209F\u20BA-\u20CF\u20F1-\u20FF\u218A-\u218F\u23F4-\u23FF\u2427-\u243F\u244B-\u245F\u2700\u2B4D-\u2B4F\u2B5A-\u2BFF\u2C2F\u2C5F\u2CF4-\u2CF8\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D71-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E3C-\u2E7F\u2E9A\u2EF4-\u2EFF\u2FD6-\u2FEF\u2FFC-\u2FFF\u3040\u3097\u3098\u3100-\u3104\u312E-\u3130\u318F\u31BB-\u31BF\u31E4-\u31EF\u321F\u32FF\u4DB6-\u4DBF\u9FCD-\u9FFF\uA48D-\uA48F\uA4C7-\uA4CF\uA62C-\uA63F\uA698-\uA69E\uA6F8-\uA6FF\uA78F\uA794-\uA79F\uA7AB-\uA7F7\uA82C-\uA82F\uA83A-\uA83F\uA878-\uA87F\uA8C5-\uA8CD\uA8DA-\uA8DF\uA8FC-\uA8FF\uA954-\uA95E\uA97D-\uA97F\uA9CE\uA9DA-\uA9DD\uA9E0-\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A\uAA5B\uAA7C-\uAA7F\uAAC3-\uAADA\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F-\uABBF\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBC2-\uFBD2\uFD40-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFE\uFDFF\uFE1A-\uFE1F\uFE27-\uFE2F\uFE53\uFE67\uFE6C-\uFE6F\uFE75\uFEFD-\uFF00\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFDF\uFFE7\uFFEF-\uFFFB\uFFFE\uFFFF])/g;
2683
2684var utils = module.exports = {
2685 // https://gist.github.com/1044128/
2686 getOuterHTML: function (element) {
2687 // jshint browser:true
2688 if ('outerHTML' in element) return element.outerHTML;
2689 var ns = "http://www.w3.org/1999/xhtml";
2690 var container = document.createElementNS(ns, '_');
2691 var xmlSerializer = new XMLSerializer();
2692 var html;
2693 if (document.xmlVersion) {
2694 return xmlSerializer.serializeToString(element);
2695 } else {
2696 container.appendChild(element.cloneNode(false));
2697 html = container.innerHTML.replace('><', '>' + element.innerHTML + '<');
2698 container.innerHTML = '';
2699 return html;
2700 }
2701 },
2702
2703 // Returns true if object is a DOM element.
2704 isDOMElement: function (object) {
2705 if (typeof HTMLElement === 'object') {
2706 return object instanceof HTMLElement;
2707 } else {
2708 return object &&
2709 typeof object === 'object' &&
2710 object.nodeType === 1 &&
2711 typeof object.nodeName === 'string';
2712 }
2713 },
2714
2715 isArray: function (ar) {
2716 return Object.prototype.toString.call(ar) === '[object Array]';
2717 },
2718
2719 isRegExp: function (re) {
2720 var s;
2721 try {
2722 s = '' + re;
2723 } catch (e) {
2724 return false;
2725 }
2726
2727 return re instanceof RegExp || // easy case
2728 // duck-type for context-switching evalcx case
2729 typeof(re) === 'function' &&
2730 re.constructor.name === 'RegExp' &&
2731 re.compile &&
2732 re.test &&
2733 re.exec &&
2734 s.match(/^\/.*\/[gim]{0,3}$/);
2735 },
2736
2737 isError: function (err) {
2738 return typeof err === 'object' && Object.prototype.toString.call(err) === '[object Error]';
2739 },
2740
2741 extend: function (target) {
2742 for (var i = 1; i < arguments.length; i += 1) {
2743 var source = arguments[i];
2744 Object.keys(source).forEach(function (key) {
2745 target[key] = source[key];
2746 });
2747 }
2748 return target;
2749 },
2750
2751 isUndefinedOrNull: function (value) {
2752 return value === null || value === undefined;
2753 },
2754
2755 getKeysOfDefinedProperties: function (object) {
2756 var keys = Object.keys(object).filter(function (key) {
2757 return typeof object[key] !== 'undefined';
2758 });
2759 // The 'message' property of Error instances is enumerable for some reason, but we want
2760 // to include it in the set when comparing:
2761 if (Object.prototype.toString.call(object) === '[object Error]') {
2762 keys.push('message');
2763 }
2764 return keys;
2765 },
2766
2767 truncateStack: function (err, fn) {
2768 if (Error.captureStackTrace) {
2769 Error.captureStackTrace(err, fn);
2770 } else if ('stack' in err) {
2771 // Excludes IE<10, and fn cannot be anonymous for this backup plan to work:
2772 var stackEntries = err.stack.split(/\r\n?|\n\r?/),
2773 needle = 'at ' + fn.name + ' ';
2774 for (var i = 0 ; i < stackEntries.length ; i += 1) {
2775 if (stackEntries[i].indexOf(needle) !== -1) {
2776 stackEntries.splice(1, i);
2777 err.stack = stackEntries.join("\n");
2778 }
2779 }
2780 }
2781 return err;
2782 },
2783
2784 findFirst: function (arr, predicate, thisObj) {
2785 var scope = thisObj || null;
2786 for (var i = 0 ; i < arr.length ; i += 1) {
2787 if (predicate.call(scope, arr[i], i, arr)) {
2788 return arr[i];
2789 }
2790 }
2791 return null;
2792 },
2793
2794 leftPad: function (str, width, ch) {
2795 ch = ch || ' ';
2796 while (str.length < width) {
2797 str = ch + str;
2798 }
2799 return str;
2800 },
2801
2802 cloneError: function (e) {
2803 var newError = new Error();
2804 Object.keys(e).forEach(function (key) {
2805 if (!errorMethodBlacklist[key]) {
2806 newError[key] = e[key];
2807 }
2808 });
2809 return newError;
2810 },
2811
2812 escapeRegExpMetaChars: function (str) {
2813 return str.replace(/[[\]{}()*+?.\\^$|]/g, '\\$&');
2814 },
2815
2816 escapeChar: function (ch) {
2817 if (ch === '\t') {
2818 return '\\t';
2819 } else if (ch === '\r') {
2820 return '\\r';
2821 } else {
2822 var charCode = ch.charCodeAt(0);
2823 var hexChars = charCode.toString(16).toUpperCase();
2824 if (charCode < 256) {
2825 return '\\x' + utils.leftPad(hexChars, 2, '0');
2826 } else {
2827 return '\\u' + utils.leftPad(hexChars, 4, '0');
2828 }
2829 }
2830 },
2831
2832 diffStrings: function (actual, expected, output, options) {
2833 options = options || {};
2834 var type = options.type || 'WordsWithSpace';
2835
2836 function addStringToOutput(output, text, baseStyle, specialCharStyle) {
2837 if (options.markUpSpecialCharacters) {
2838 text.split(specialCharRegexp).forEach(function (part) {
2839 if (specialCharRegexp.test(part)) {
2840 output[specialCharStyle || baseStyle](utils.escapeChar(part));
2841 } else {
2842 output[baseStyle](part);
2843 }
2844 });
2845 } else {
2846 output[baseStyle](text);
2847 }
2848 return output;
2849 }
2850
2851 var diffLines = [];
2852 var lastPart;
2853 stringDiff.diffLines(actual, expected).forEach(function (part) {
2854 if (lastPart && lastPart.added && part.removed) {
2855 diffLines.push({
2856 oldValue: part.value,
2857 newValue: lastPart.value,
2858 replaced: true
2859 });
2860 lastPart = null;
2861 } else if (lastPart) {
2862 diffLines.push(lastPart);
2863 lastPart = part;
2864 } else {
2865 lastPart = part;
2866 }
2867 });
2868 if (lastPart) {
2869 diffLines.push(lastPart);
2870 }
2871
2872 diffLines.forEach(function (part, index) {
2873 var endsWithNewline = /\n$/.test(part.value);
2874 var value;
2875 if (part.replaced) {
2876 var oldLine = output.clone();
2877 var newLine = output.clone();
2878 var oldValue = part.oldValue;
2879 var newValue = part.newValue;
2880 var oldEndsWithNewline = oldValue.slice(-1) === '\n';
2881 var newEndsWithNewline = newValue.slice(-1) === '\n';
2882 if (oldEndsWithNewline) {
2883 oldValue = oldValue.slice(0, -1);
2884 }
2885 if (newEndsWithNewline) {
2886 newValue = newValue.slice(0, -1);
2887 }
2888
2889 stringDiff['diff' + type](oldValue, newValue).forEach(function (part) {
2890 if (part.added) {
2891 addStringToOutput(newLine, part.value, 'diffAddedHighlight', 'diffAddedSpecialChar');
2892 } else if (part.removed) {
2893 addStringToOutput(oldLine, part.value, 'diffRemovedHighlight', 'diffRemovedSpecialChar');
2894 } else {
2895 newLine.diffAddedLine(part.value);
2896 oldLine.diffRemovedLine(part.value);
2897 }
2898 });
2899 oldLine.prependLinesWith(output.clone().diffRemovedLine('-'));
2900 newLine.prependLinesWith(output.clone().diffAddedLine('+'));
2901
2902 if (oldEndsWithNewline && !newEndsWithNewline) {
2903 oldLine.diffRemovedSpecialChar('\\n');
2904 }
2905
2906 if (newEndsWithNewline && !oldEndsWithNewline) {
2907 newLine.diffAddedSpecialChar('\\n');
2908 }
2909
2910 output.append(oldLine).nl().append(newLine);
2911 if (oldEndsWithNewline && index < diffLines.length - 1) {
2912 output.nl();
2913 }
2914 } else if (part.added) {
2915 value = endsWithNewline ?
2916 part.value.slice(0, -1) :
2917 part.value;
2918
2919 output.append(function () {
2920 addStringToOutput(this, value, 'diffAddedLine').prependLinesWith(function () {
2921 this.diffAddedLine('+');
2922 });
2923 });
2924
2925 if (endsWithNewline) {
2926 output.nl();
2927 }
2928 } else if (part.removed) {
2929 value = endsWithNewline ?
2930 part.value.slice(0, -1) :
2931 part.value;
2932
2933 output.append(function () {
2934 addStringToOutput(this, value, 'diffRemovedLine').prependLinesWith(function () {
2935 this.diffRemovedLine('-');
2936 });
2937 });
2938
2939 if (endsWithNewline) {
2940 output.nl();
2941 }
2942 } else {
2943 output.text(part.value.replace(/^(.)/gm, ' $1'));
2944 }
2945 });
2946 return output;
2947 }
2948};
2949
2950},{}],7:[function(require,module,exports){
2951var Unexpected = require(2);
2952
2953var unexpected = Unexpected.create();
2954var styles = require(4);
2955var types = require(5);
2956var assertions = require(3);
2957
2958styles(unexpected);
2959types(unexpected);
2960assertions(unexpected);
2961
2962module.exports = unexpected;
2963
2964},{}],8:[function(require,module,exports){
2965module.exports = arrayDiff;
2966
2967// Based on some rough benchmarking, this algorithm is about O(2n) worst case,
2968// and it can compute diffs on random arrays of length 1024 in about 34ms,
2969// though just a few changes on an array of length 1024 takes about 0.5ms
2970
2971arrayDiff.InsertDiff = InsertDiff;
2972arrayDiff.RemoveDiff = RemoveDiff;
2973arrayDiff.MoveDiff = MoveDiff;
2974
2975function InsertDiff(index, values) {
2976 this.index = index;
2977 this.values = values;
2978}
2979InsertDiff.prototype.type = 'insert';
2980InsertDiff.prototype.toJSON = function() {
2981 return {
2982 type: this.type
2983 , index: this.index
2984 , values: this.values
2985 };
2986};
2987
2988function RemoveDiff(index, howMany) {
2989 this.index = index;
2990 this.howMany = howMany;
2991}
2992RemoveDiff.prototype.type = 'remove';
2993RemoveDiff.prototype.toJSON = function() {
2994 return {
2995 type: this.type
2996 , index: this.index
2997 , howMany: this.howMany
2998 };
2999};
3000
3001function MoveDiff(from, to, howMany) {
3002 this.from = from;
3003 this.to = to;
3004 this.howMany = howMany;
3005}
3006MoveDiff.prototype.type = 'move';
3007MoveDiff.prototype.toJSON = function() {
3008 return {
3009 type: this.type
3010 , from: this.from
3011 , to: this.to
3012 , howMany: this.howMany
3013 };
3014};
3015
3016function strictEqual(a, b) {
3017 return a === b;
3018}
3019
3020function arrayDiff(before, after, equalFn) {
3021 if (!equalFn) equalFn = strictEqual;
3022
3023 // Find all items in both the before and after array, and represent them
3024 // as moves. Many of these "moves" may end up being discarded in the last
3025 // pass if they are from an index to the same index, but we don't know this
3026 // up front, since we haven't yet offset the indices.
3027 //
3028 // Also keep a map of all the indicies accounted for in the before and after
3029 // arrays. These maps are used next to create insert and remove diffs.
3030 var beforeLength = before.length;
3031 var afterLength = after.length;
3032 var moves = [];
3033 var beforeMarked = {};
3034 var afterMarked = {};
3035 for (var beforeIndex = 0; beforeIndex < beforeLength; beforeIndex++) {
3036 var beforeItem = before[beforeIndex];
3037 for (var afterIndex = 0; afterIndex < afterLength; afterIndex++) {
3038 if (afterMarked[afterIndex]) continue;
3039 if (!equalFn(beforeItem, after[afterIndex])) continue;
3040 var from = beforeIndex;
3041 var to = afterIndex;
3042 var howMany = 0;
3043 do {
3044 beforeMarked[beforeIndex++] = afterMarked[afterIndex++] = true;
3045 howMany++;
3046 } while (
3047 beforeIndex < beforeLength &&
3048 afterIndex < afterLength &&
3049 equalFn(before[beforeIndex], after[afterIndex]) &&
3050 !afterMarked[afterIndex]
3051 );
3052 moves.push(new MoveDiff(from, to, howMany));
3053 beforeIndex--;
3054 break;
3055 }
3056 }
3057
3058 // Create a remove for all of the items in the before array that were
3059 // not marked as being matched in the after array as well
3060 var removes = [];
3061 for (beforeIndex = 0; beforeIndex < beforeLength;) {
3062 if (beforeMarked[beforeIndex]) {
3063 beforeIndex++;
3064 continue;
3065 }
3066 var index = beforeIndex;
3067 var howMany = 0;
3068 while (beforeIndex < beforeLength && !beforeMarked[beforeIndex++]) {
3069 howMany++;
3070 }
3071 removes.push(new RemoveDiff(index, howMany));
3072 }
3073
3074 // Create an insert for all of the items in the after array that were
3075 // not marked as being matched in the before array as well
3076 var inserts = [];
3077 for (afterIndex = 0; afterIndex < afterLength;) {
3078 if (afterMarked[afterIndex]) {
3079 afterIndex++;
3080 continue;
3081 }
3082 var index = afterIndex;
3083 var howMany = 0;
3084 while (afterIndex < afterLength && !afterMarked[afterIndex++]) {
3085 howMany++;
3086 }
3087 var values = after.slice(index, index + howMany);
3088 inserts.push(new InsertDiff(index, values));
3089 }
3090
3091 var insertsLength = inserts.length;
3092 var removesLength = removes.length;
3093 var movesLength = moves.length;
3094 var i, j;
3095
3096 // Offset subsequent removes and moves by removes
3097 var count = 0;
3098 for (i = 0; i < removesLength; i++) {
3099 var remove = removes[i];
3100 remove.index -= count;
3101 count += remove.howMany;
3102 for (j = 0; j < movesLength; j++) {
3103 var move = moves[j];
3104 if (move.from >= remove.index) move.from -= remove.howMany;
3105 }
3106 }
3107
3108 // Offset moves by inserts
3109 for (i = insertsLength; i--;) {
3110 var insert = inserts[i];
3111 var howMany = insert.values.length;
3112 for (j = movesLength; j--;) {
3113 var move = moves[j];
3114 if (move.to >= insert.index) move.to -= howMany;
3115 }
3116 }
3117
3118 // Offset the to of moves by later moves
3119 for (i = movesLength; i-- > 1;) {
3120 var move = moves[i];
3121 if (move.to === move.from) continue;
3122 for (j = i; j--;) {
3123 var earlier = moves[j];
3124 if (earlier.to >= move.to) earlier.to -= move.howMany;
3125 if (earlier.to >= move.from) earlier.to += move.howMany;
3126 }
3127 }
3128
3129 // Only output moves that end up having an effect after offsetting
3130 var outputMoves = [];
3131
3132 // Offset the from of moves by earlier moves
3133 for (i = 0; i < movesLength; i++) {
3134 var move = moves[i];
3135 if (move.to === move.from) continue;
3136 outputMoves.push(move);
3137 for (j = i + 1; j < movesLength; j++) {
3138 var later = moves[j];
3139 if (later.from >= move.from) later.from -= move.howMany;
3140 if (later.from >= move.to) later.from += move.howMany;
3141 }
3142 }
3143
3144 return removes.concat(outputMoves, inserts);
3145}
3146
3147},{}],9:[function(require,module,exports){
3148/*!
3149 * The buffer module from node.js, for the browser.
3150 *
3151 * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
3152 * @license MIT
3153 */
3154
3155var base64 = require(10)
3156var ieee754 = require(11)
3157var isArray = require(12)
3158
3159exports.Buffer = Buffer
3160exports.SlowBuffer = Buffer
3161exports.INSPECT_MAX_BYTES = 50
3162Buffer.poolSize = 8192 // not used by this implementation
3163
3164var kMaxLength = 0x3fffffff
3165
3166/**
3167 * If `Buffer.TYPED_ARRAY_SUPPORT`:
3168 * === true Use Uint8Array implementation (fastest)
3169 * === false Use Object implementation (most compatible, even IE6)
3170 *
3171 * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
3172 * Opera 11.6+, iOS 4.2+.
3173 *
3174 * Note:
3175 *
3176 * - Implementation must support adding new properties to `Uint8Array` instances.
3177 * Firefox 4-29 lacked support, fixed in Firefox 30+.
3178 * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
3179 *
3180 * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
3181 *
3182 * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
3183 * incorrect length in some situations.
3184 *
3185 * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will
3186 * get the Object implementation, which is slower but will work correctly.
3187 */
3188Buffer.TYPED_ARRAY_SUPPORT = (function () {
3189 try {
3190 var buf = new ArrayBuffer(0)
3191 var arr = new Uint8Array(buf)
3192 arr.foo = function () { return 42 }
3193 return 42 === arr.foo() && // typed array instances can be augmented
3194 typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
3195 new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
3196 } catch (e) {
3197 return false
3198 }
3199})()
3200
3201/**
3202 * Class: Buffer
3203 * =============
3204 *
3205 * The Buffer constructor returns instances of `Uint8Array` that are augmented
3206 * with function properties for all the node `Buffer` API functions. We use
3207 * `Uint8Array` so that square bracket notation works as expected -- it returns
3208 * a single octet.
3209 *
3210 * By augmenting the instances, we can avoid modifying the `Uint8Array`
3211 * prototype.
3212 */
3213function Buffer (subject, encoding, noZero) {
3214 if (!(this instanceof Buffer))
3215 return new Buffer(subject, encoding, noZero)
3216
3217 var type = typeof subject
3218
3219 // Find the length
3220 var length
3221 if (type === 'number')
3222 length = subject > 0 ? subject >>> 0 : 0
3223 else if (type === 'string') {
3224 if (encoding === 'base64')
3225 subject = base64clean(subject)
3226 length = Buffer.byteLength(subject, encoding)
3227 } else if (type === 'object' && subject !== null) { // assume object is array-like
3228 if (subject.type === 'Buffer' && isArray(subject.data))
3229 subject = subject.data
3230 length = +subject.length > 0 ? Math.floor(+subject.length) : 0
3231 } else
3232 throw new TypeError('must start with number, buffer, array or string')
3233
3234 if (this.length > kMaxLength)
3235 throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
3236 'size: 0x' + kMaxLength.toString(16) + ' bytes')
3237
3238 var buf
3239 if (Buffer.TYPED_ARRAY_SUPPORT) {
3240 // Preferred: Return an augmented `Uint8Array` instance for best performance
3241 buf = Buffer._augment(new Uint8Array(length))
3242 } else {
3243 // Fallback: Return THIS instance of Buffer (created by `new`)
3244 buf = this
3245 buf.length = length
3246 buf._isBuffer = true
3247 }
3248
3249 var i
3250 if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') {
3251 // Speed optimization -- use set if we're copying from a typed array
3252 buf._set(subject)
3253 } else if (isArrayish(subject)) {
3254 // Treat array-ish objects as a byte array
3255 if (Buffer.isBuffer(subject)) {
3256 for (i = 0; i < length; i++)
3257 buf[i] = subject.readUInt8(i)
3258 } else {
3259 for (i = 0; i < length; i++)
3260 buf[i] = ((subject[i] % 256) + 256) % 256
3261 }
3262 } else if (type === 'string') {
3263 buf.write(subject, 0, encoding)
3264 } else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) {
3265 for (i = 0; i < length; i++) {
3266 buf[i] = 0
3267 }
3268 }
3269
3270 return buf
3271}
3272
3273Buffer.isBuffer = function (b) {
3274 return !!(b != null && b._isBuffer)
3275}
3276
3277Buffer.compare = function (a, b) {
3278 if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b))
3279 throw new TypeError('Arguments must be Buffers')
3280
3281 var x = a.length
3282 var y = b.length
3283 for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {}
3284 if (i !== len) {
3285 x = a[i]
3286 y = b[i]
3287 }
3288 if (x < y) return -1
3289 if (y < x) return 1
3290 return 0
3291}
3292
3293Buffer.isEncoding = function (encoding) {
3294 switch (String(encoding).toLowerCase()) {
3295 case 'hex':
3296 case 'utf8':
3297 case 'utf-8':
3298 case 'ascii':
3299 case 'binary':
3300 case 'base64':
3301 case 'raw':
3302 case 'ucs2':
3303 case 'ucs-2':
3304 case 'utf16le':
3305 case 'utf-16le':
3306 return true
3307 default:
3308 return false
3309 }
3310}
3311
3312Buffer.concat = function (list, totalLength) {
3313 if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])')
3314
3315 if (list.length === 0) {
3316 return new Buffer(0)
3317 } else if (list.length === 1) {
3318 return list[0]
3319 }
3320
3321 var i
3322 if (totalLength === undefined) {
3323 totalLength = 0
3324 for (i = 0; i < list.length; i++) {
3325 totalLength += list[i].length
3326 }
3327 }
3328
3329 var buf = new Buffer(totalLength)
3330 var pos = 0
3331 for (i = 0; i < list.length; i++) {
3332 var item = list[i]
3333 item.copy(buf, pos)
3334 pos += item.length
3335 }
3336 return buf
3337}
3338
3339Buffer.byteLength = function (str, encoding) {
3340 var ret
3341 str = str + ''
3342 switch (encoding || 'utf8') {
3343 case 'ascii':
3344 case 'binary':
3345 case 'raw':
3346 ret = str.length
3347 break
3348 case 'ucs2':
3349 case 'ucs-2':
3350 case 'utf16le':
3351 case 'utf-16le':
3352 ret = str.length * 2
3353 break
3354 case 'hex':
3355 ret = str.length >>> 1
3356 break
3357 case 'utf8':
3358 case 'utf-8':
3359 ret = utf8ToBytes(str).length
3360 break
3361 case 'base64':
3362 ret = base64ToBytes(str).length
3363 break
3364 default:
3365 ret = str.length
3366 }
3367 return ret
3368}
3369
3370// pre-set for values that may exist in the future
3371Buffer.prototype.length = undefined
3372Buffer.prototype.parent = undefined
3373
3374// toString(encoding, start=0, end=buffer.length)
3375Buffer.prototype.toString = function (encoding, start, end) {
3376 var loweredCase = false
3377
3378 start = start >>> 0
3379 end = end === undefined || end === Infinity ? this.length : end >>> 0
3380
3381 if (!encoding) encoding = 'utf8'
3382 if (start < 0) start = 0
3383 if (end > this.length) end = this.length
3384 if (end <= start) return ''
3385
3386 while (true) {
3387 switch (encoding) {
3388 case 'hex':
3389 return hexSlice(this, start, end)
3390
3391 case 'utf8':
3392 case 'utf-8':
3393 return utf8Slice(this, start, end)
3394
3395 case 'ascii':
3396 return asciiSlice(this, start, end)
3397
3398 case 'binary':
3399 return binarySlice(this, start, end)
3400
3401 case 'base64':
3402 return base64Slice(this, start, end)
3403
3404 case 'ucs2':
3405 case 'ucs-2':
3406 case 'utf16le':
3407 case 'utf-16le':
3408 return utf16leSlice(this, start, end)
3409
3410 default:
3411 if (loweredCase)
3412 throw new TypeError('Unknown encoding: ' + encoding)
3413 encoding = (encoding + '').toLowerCase()
3414 loweredCase = true
3415 }
3416 }
3417}
3418
3419Buffer.prototype.equals = function (b) {
3420 if(!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
3421 return Buffer.compare(this, b) === 0
3422}
3423
3424Buffer.prototype.inspect = function () {
3425 var str = ''
3426 var max = exports.INSPECT_MAX_BYTES
3427 if (this.length > 0) {
3428 str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
3429 if (this.length > max)
3430 str += ' ... '
3431 }
3432 return '<Buffer ' + str + '>'
3433}
3434
3435Buffer.prototype.compare = function (b) {
3436 if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
3437 return Buffer.compare(this, b)
3438}
3439
3440// `get` will be removed in Node 0.13+
3441Buffer.prototype.get = function (offset) {
3442 console.log('.get() is deprecated. Access using array indexes instead.')
3443 return this.readUInt8(offset)
3444}
3445
3446// `set` will be removed in Node 0.13+
3447Buffer.prototype.set = function (v, offset) {
3448 console.log('.set() is deprecated. Access using array indexes instead.')
3449 return this.writeUInt8(v, offset)
3450}
3451
3452function hexWrite (buf, string, offset, length) {
3453 offset = Number(offset) || 0
3454 var remaining = buf.length - offset
3455 if (!length) {
3456 length = remaining
3457 } else {
3458 length = Number(length)
3459 if (length > remaining) {
3460 length = remaining
3461 }
3462 }
3463
3464 // must be an even number of digits
3465 var strLen = string.length
3466 if (strLen % 2 !== 0) throw new Error('Invalid hex string')
3467
3468 if (length > strLen / 2) {
3469 length = strLen / 2
3470 }
3471 for (var i = 0; i < length; i++) {
3472 var byte = parseInt(string.substr(i * 2, 2), 16)
3473 if (isNaN(byte)) throw new Error('Invalid hex string')
3474 buf[offset + i] = byte
3475 }
3476 return i
3477}
3478
3479function utf8Write (buf, string, offset, length) {
3480 var charsWritten = blitBuffer(utf8ToBytes(string), buf, offset, length)
3481 return charsWritten
3482}
3483
3484function asciiWrite (buf, string, offset, length) {
3485 var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length)
3486 return charsWritten
3487}
3488
3489function binaryWrite (buf, string, offset, length) {
3490 return asciiWrite(buf, string, offset, length)
3491}
3492
3493function base64Write (buf, string, offset, length) {
3494 var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length)
3495 return charsWritten
3496}
3497
3498function utf16leWrite (buf, string, offset, length) {
3499 var charsWritten = blitBuffer(utf16leToBytes(string), buf, offset, length)
3500 return charsWritten
3501}
3502
3503Buffer.prototype.write = function (string, offset, length, encoding) {
3504 // Support both (string, offset, length, encoding)
3505 // and the legacy (string, encoding, offset, length)
3506 if (isFinite(offset)) {
3507 if (!isFinite(length)) {
3508 encoding = length
3509 length = undefined
3510 }
3511 } else { // legacy
3512 var swap = encoding
3513 encoding = offset
3514 offset = length
3515 length = swap
3516 }
3517
3518 offset = Number(offset) || 0
3519 var remaining = this.length - offset
3520 if (!length) {
3521 length = remaining
3522 } else {
3523 length = Number(length)
3524 if (length > remaining) {
3525 length = remaining
3526 }
3527 }
3528 encoding = String(encoding || 'utf8').toLowerCase()
3529
3530 var ret
3531 switch (encoding) {
3532 case 'hex':
3533 ret = hexWrite(this, string, offset, length)
3534 break
3535 case 'utf8':
3536 case 'utf-8':
3537 ret = utf8Write(this, string, offset, length)
3538 break
3539 case 'ascii':
3540 ret = asciiWrite(this, string, offset, length)
3541 break
3542 case 'binary':
3543 ret = binaryWrite(this, string, offset, length)
3544 break
3545 case 'base64':
3546 ret = base64Write(this, string, offset, length)
3547 break
3548 case 'ucs2':
3549 case 'ucs-2':
3550 case 'utf16le':
3551 case 'utf-16le':
3552 ret = utf16leWrite(this, string, offset, length)
3553 break
3554 default:
3555 throw new TypeError('Unknown encoding: ' + encoding)
3556 }
3557 return ret
3558}
3559
3560Buffer.prototype.toJSON = function () {
3561 return {
3562 type: 'Buffer',
3563 data: Array.prototype.slice.call(this._arr || this, 0)
3564 }
3565}
3566
3567function base64Slice (buf, start, end) {
3568 if (start === 0 && end === buf.length) {
3569 return base64.fromByteArray(buf)
3570 } else {
3571 return base64.fromByteArray(buf.slice(start, end))
3572 }
3573}
3574
3575function utf8Slice (buf, start, end) {
3576 var res = ''
3577 var tmp = ''
3578 end = Math.min(buf.length, end)
3579
3580 for (var i = start; i < end; i++) {
3581 if (buf[i] <= 0x7F) {
3582 res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i])
3583 tmp = ''
3584 } else {
3585 tmp += '%' + buf[i].toString(16)
3586 }
3587 }
3588
3589 return res + decodeUtf8Char(tmp)
3590}
3591
3592function asciiSlice (buf, start, end) {
3593 var ret = ''
3594 end = Math.min(buf.length, end)
3595
3596 for (var i = start; i < end; i++) {
3597 ret += String.fromCharCode(buf[i])
3598 }
3599 return ret
3600}
3601
3602function binarySlice (buf, start, end) {
3603 return asciiSlice(buf, start, end)
3604}
3605
3606function hexSlice (buf, start, end) {
3607 var len = buf.length
3608
3609 if (!start || start < 0) start = 0
3610 if (!end || end < 0 || end > len) end = len
3611
3612 var out = ''
3613 for (var i = start; i < end; i++) {
3614 out += toHex(buf[i])
3615 }
3616 return out
3617}
3618
3619function utf16leSlice (buf, start, end) {
3620 var bytes = buf.slice(start, end)
3621 var res = ''
3622 for (var i = 0; i < bytes.length; i += 2) {
3623 res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
3624 }
3625 return res
3626}
3627
3628Buffer.prototype.slice = function (start, end) {
3629 var len = this.length
3630 start = ~~start
3631 end = end === undefined ? len : ~~end
3632
3633 if (start < 0) {
3634 start += len;
3635 if (start < 0)
3636 start = 0
3637 } else if (start > len) {
3638 start = len
3639 }
3640
3641 if (end < 0) {
3642 end += len
3643 if (end < 0)
3644 end = 0
3645 } else if (end > len) {
3646 end = len
3647 }
3648
3649 if (end < start)
3650 end = start
3651
3652 if (Buffer.TYPED_ARRAY_SUPPORT) {
3653 return Buffer._augment(this.subarray(start, end))
3654 } else {
3655 var sliceLen = end - start
3656 var newBuf = new Buffer(sliceLen, undefined, true)
3657 for (var i = 0; i < sliceLen; i++) {
3658 newBuf[i] = this[i + start]
3659 }
3660 return newBuf
3661 }
3662}
3663
3664/*
3665 * Need to make sure that buffer isn't trying to write out of bounds.
3666 */
3667function checkOffset (offset, ext, length) {
3668 if ((offset % 1) !== 0 || offset < 0)
3669 throw new RangeError('offset is not uint')
3670 if (offset + ext > length)
3671 throw new RangeError('Trying to access beyond buffer length')
3672}
3673
3674Buffer.prototype.readUInt8 = function (offset, noAssert) {
3675 if (!noAssert)
3676 checkOffset(offset, 1, this.length)
3677 return this[offset]
3678}
3679
3680Buffer.prototype.readUInt16LE = function (offset, noAssert) {
3681 if (!noAssert)
3682 checkOffset(offset, 2, this.length)
3683 return this[offset] | (this[offset + 1] << 8)
3684}
3685
3686Buffer.prototype.readUInt16BE = function (offset, noAssert) {
3687 if (!noAssert)
3688 checkOffset(offset, 2, this.length)
3689 return (this[offset] << 8) | this[offset + 1]
3690}
3691
3692Buffer.prototype.readUInt32LE = function (offset, noAssert) {
3693 if (!noAssert)
3694 checkOffset(offset, 4, this.length)
3695
3696 return ((this[offset]) |
3697 (this[offset + 1] << 8) |
3698 (this[offset + 2] << 16)) +
3699 (this[offset + 3] * 0x1000000)
3700}
3701
3702Buffer.prototype.readUInt32BE = function (offset, noAssert) {
3703 if (!noAssert)
3704 checkOffset(offset, 4, this.length)
3705
3706 return (this[offset] * 0x1000000) +
3707 ((this[offset + 1] << 16) |
3708 (this[offset + 2] << 8) |
3709 this[offset + 3])
3710}
3711
3712Buffer.prototype.readInt8 = function (offset, noAssert) {
3713 if (!noAssert)
3714 checkOffset(offset, 1, this.length)
3715 if (!(this[offset] & 0x80))
3716 return (this[offset])
3717 return ((0xff - this[offset] + 1) * -1)
3718}
3719
3720Buffer.prototype.readInt16LE = function (offset, noAssert) {
3721 if (!noAssert)
3722 checkOffset(offset, 2, this.length)
3723 var val = this[offset] | (this[offset + 1] << 8)
3724 return (val & 0x8000) ? val | 0xFFFF0000 : val
3725}
3726
3727Buffer.prototype.readInt16BE = function (offset, noAssert) {
3728 if (!noAssert)
3729 checkOffset(offset, 2, this.length)
3730 var val = this[offset + 1] | (this[offset] << 8)
3731 return (val & 0x8000) ? val | 0xFFFF0000 : val
3732}
3733
3734Buffer.prototype.readInt32LE = function (offset, noAssert) {
3735 if (!noAssert)
3736 checkOffset(offset, 4, this.length)
3737
3738 return (this[offset]) |
3739 (this[offset + 1] << 8) |
3740 (this[offset + 2] << 16) |
3741 (this[offset + 3] << 24)
3742}
3743
3744Buffer.prototype.readInt32BE = function (offset, noAssert) {
3745 if (!noAssert)
3746 checkOffset(offset, 4, this.length)
3747
3748 return (this[offset] << 24) |
3749 (this[offset + 1] << 16) |
3750 (this[offset + 2] << 8) |
3751 (this[offset + 3])
3752}
3753
3754Buffer.prototype.readFloatLE = function (offset, noAssert) {
3755 if (!noAssert)
3756 checkOffset(offset, 4, this.length)
3757 return ieee754.read(this, offset, true, 23, 4)
3758}
3759
3760Buffer.prototype.readFloatBE = function (offset, noAssert) {
3761 if (!noAssert)
3762 checkOffset(offset, 4, this.length)
3763 return ieee754.read(this, offset, false, 23, 4)
3764}
3765
3766Buffer.prototype.readDoubleLE = function (offset, noAssert) {
3767 if (!noAssert)
3768 checkOffset(offset, 8, this.length)
3769 return ieee754.read(this, offset, true, 52, 8)
3770}
3771
3772Buffer.prototype.readDoubleBE = function (offset, noAssert) {
3773 if (!noAssert)
3774 checkOffset(offset, 8, this.length)
3775 return ieee754.read(this, offset, false, 52, 8)
3776}
3777
3778function checkInt (buf, value, offset, ext, max, min) {
3779 if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
3780 if (value > max || value < min) throw new TypeError('value is out of bounds')
3781 if (offset + ext > buf.length) throw new TypeError('index out of range')
3782}
3783
3784Buffer.prototype.writeUInt8 = function (value, offset, noAssert) {
3785 value = +value
3786 offset = offset >>> 0
3787 if (!noAssert)
3788 checkInt(this, value, offset, 1, 0xff, 0)
3789 if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
3790 this[offset] = value
3791 return offset + 1
3792}
3793
3794function objectWriteUInt16 (buf, value, offset, littleEndian) {
3795 if (value < 0) value = 0xffff + value + 1
3796 for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
3797 buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
3798 (littleEndian ? i : 1 - i) * 8
3799 }
3800}
3801
3802Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) {
3803 value = +value
3804 offset = offset >>> 0
3805 if (!noAssert)
3806 checkInt(this, value, offset, 2, 0xffff, 0)
3807 if (Buffer.TYPED_ARRAY_SUPPORT) {
3808 this[offset] = value
3809 this[offset + 1] = (value >>> 8)
3810 } else objectWriteUInt16(this, value, offset, true)
3811 return offset + 2
3812}
3813
3814Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) {
3815 value = +value
3816 offset = offset >>> 0
3817 if (!noAssert)
3818 checkInt(this, value, offset, 2, 0xffff, 0)
3819 if (Buffer.TYPED_ARRAY_SUPPORT) {
3820 this[offset] = (value >>> 8)
3821 this[offset + 1] = value
3822 } else objectWriteUInt16(this, value, offset, false)
3823 return offset + 2
3824}
3825
3826function objectWriteUInt32 (buf, value, offset, littleEndian) {
3827 if (value < 0) value = 0xffffffff + value + 1
3828 for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
3829 buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
3830 }
3831}
3832
3833Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) {
3834 value = +value
3835 offset = offset >>> 0
3836 if (!noAssert)
3837 checkInt(this, value, offset, 4, 0xffffffff, 0)
3838 if (Buffer.TYPED_ARRAY_SUPPORT) {
3839 this[offset + 3] = (value >>> 24)
3840 this[offset + 2] = (value >>> 16)
3841 this[offset + 1] = (value >>> 8)
3842 this[offset] = value
3843 } else objectWriteUInt32(this, value, offset, true)
3844 return offset + 4
3845}
3846
3847Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) {
3848 value = +value
3849 offset = offset >>> 0
3850 if (!noAssert)
3851 checkInt(this, value, offset, 4, 0xffffffff, 0)
3852 if (Buffer.TYPED_ARRAY_SUPPORT) {
3853 this[offset] = (value >>> 24)
3854 this[offset + 1] = (value >>> 16)
3855 this[offset + 2] = (value >>> 8)
3856 this[offset + 3] = value
3857 } else objectWriteUInt32(this, value, offset, false)
3858 return offset + 4
3859}
3860
3861Buffer.prototype.writeInt8 = function (value, offset, noAssert) {
3862 value = +value
3863 offset = offset >>> 0
3864 if (!noAssert)
3865 checkInt(this, value, offset, 1, 0x7f, -0x80)
3866 if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
3867 if (value < 0) value = 0xff + value + 1
3868 this[offset] = value
3869 return offset + 1
3870}
3871
3872Buffer.prototype.writeInt16LE = function (value, offset, noAssert) {
3873 value = +value
3874 offset = offset >>> 0
3875 if (!noAssert)
3876 checkInt(this, value, offset, 2, 0x7fff, -0x8000)
3877 if (Buffer.TYPED_ARRAY_SUPPORT) {
3878 this[offset] = value
3879 this[offset + 1] = (value >>> 8)
3880 } else objectWriteUInt16(this, value, offset, true)
3881 return offset + 2
3882}
3883
3884Buffer.prototype.writeInt16BE = function (value, offset, noAssert) {
3885 value = +value
3886 offset = offset >>> 0
3887 if (!noAssert)
3888 checkInt(this, value, offset, 2, 0x7fff, -0x8000)
3889 if (Buffer.TYPED_ARRAY_SUPPORT) {
3890 this[offset] = (value >>> 8)
3891 this[offset + 1] = value
3892 } else objectWriteUInt16(this, value, offset, false)
3893 return offset + 2
3894}
3895
3896Buffer.prototype.writeInt32LE = function (value, offset, noAssert) {
3897 value = +value
3898 offset = offset >>> 0
3899 if (!noAssert)
3900 checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
3901 if (Buffer.TYPED_ARRAY_SUPPORT) {
3902 this[offset] = value
3903 this[offset + 1] = (value >>> 8)
3904 this[offset + 2] = (value >>> 16)
3905 this[offset + 3] = (value >>> 24)
3906 } else objectWriteUInt32(this, value, offset, true)
3907 return offset + 4
3908}
3909
3910Buffer.prototype.writeInt32BE = function (value, offset, noAssert) {
3911 value = +value
3912 offset = offset >>> 0
3913 if (!noAssert)
3914 checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
3915 if (value < 0) value = 0xffffffff + value + 1
3916 if (Buffer.TYPED_ARRAY_SUPPORT) {
3917 this[offset] = (value >>> 24)
3918 this[offset + 1] = (value >>> 16)
3919 this[offset + 2] = (value >>> 8)
3920 this[offset + 3] = value
3921 } else objectWriteUInt32(this, value, offset, false)
3922 return offset + 4
3923}
3924
3925function checkIEEE754 (buf, value, offset, ext, max, min) {
3926 if (value > max || value < min) throw new TypeError('value is out of bounds')
3927 if (offset + ext > buf.length) throw new TypeError('index out of range')
3928}
3929
3930function writeFloat (buf, value, offset, littleEndian, noAssert) {
3931 if (!noAssert)
3932 checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
3933 ieee754.write(buf, value, offset, littleEndian, 23, 4)
3934 return offset + 4
3935}
3936
3937Buffer.prototype.writeFloatLE = function (value, offset, noAssert) {
3938 return writeFloat(this, value, offset, true, noAssert)
3939}
3940
3941Buffer.prototype.writeFloatBE = function (value, offset, noAssert) {
3942 return writeFloat(this, value, offset, false, noAssert)
3943}
3944
3945function writeDouble (buf, value, offset, littleEndian, noAssert) {
3946 if (!noAssert)
3947 checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
3948 ieee754.write(buf, value, offset, littleEndian, 52, 8)
3949 return offset + 8
3950}
3951
3952Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) {
3953 return writeDouble(this, value, offset, true, noAssert)
3954}
3955
3956Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) {
3957 return writeDouble(this, value, offset, false, noAssert)
3958}
3959
3960// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
3961Buffer.prototype.copy = function (target, target_start, start, end) {
3962 var source = this
3963
3964 if (!start) start = 0
3965 if (!end && end !== 0) end = this.length
3966 if (!target_start) target_start = 0
3967
3968 // Copy 0 bytes; we're done
3969 if (end === start) return
3970 if (target.length === 0 || source.length === 0) return
3971
3972 // Fatal error conditions
3973 if (end < start) throw new TypeError('sourceEnd < sourceStart')
3974 if (target_start < 0 || target_start >= target.length)
3975 throw new TypeError('targetStart out of bounds')
3976 if (start < 0 || start >= source.length) throw new TypeError('sourceStart out of bounds')
3977 if (end < 0 || end > source.length) throw new TypeError('sourceEnd out of bounds')
3978
3979 // Are we oob?
3980 if (end > this.length)
3981 end = this.length
3982 if (target.length - target_start < end - start)
3983 end = target.length - target_start + start
3984
3985 var len = end - start
3986
3987 if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
3988 for (var i = 0; i < len; i++) {
3989 target[i + target_start] = this[i + start]
3990 }
3991 } else {
3992 target._set(this.subarray(start, start + len), target_start)
3993 }
3994}
3995
3996// fill(value, start=0, end=buffer.length)
3997Buffer.prototype.fill = function (value, start, end) {
3998 if (!value) value = 0
3999 if (!start) start = 0
4000 if (!end) end = this.length
4001
4002 if (end < start) throw new TypeError('end < start')
4003
4004 // Fill 0 bytes; we're done
4005 if (end === start) return
4006 if (this.length === 0) return
4007
4008 if (start < 0 || start >= this.length) throw new TypeError('start out of bounds')
4009 if (end < 0 || end > this.length) throw new TypeError('end out of bounds')
4010
4011 var i
4012 if (typeof value === 'number') {
4013 for (i = start; i < end; i++) {
4014 this[i] = value
4015 }
4016 } else {
4017 var bytes = utf8ToBytes(value.toString())
4018 var len = bytes.length
4019 for (i = start; i < end; i++) {
4020 this[i] = bytes[i % len]
4021 }
4022 }
4023
4024 return this
4025}
4026
4027/**
4028 * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
4029 * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
4030 */
4031Buffer.prototype.toArrayBuffer = function () {
4032 if (typeof Uint8Array !== 'undefined') {
4033 if (Buffer.TYPED_ARRAY_SUPPORT) {
4034 return (new Buffer(this)).buffer
4035 } else {
4036 var buf = new Uint8Array(this.length)
4037 for (var i = 0, len = buf.length; i < len; i += 1) {
4038 buf[i] = this[i]
4039 }
4040 return buf.buffer
4041 }
4042 } else {
4043 throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
4044 }
4045}
4046
4047// HELPER FUNCTIONS
4048// ================
4049
4050var BP = Buffer.prototype
4051
4052/**
4053 * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
4054 */
4055Buffer._augment = function (arr) {
4056 arr.constructor = Buffer
4057 arr._isBuffer = true
4058
4059 // save reference to original Uint8Array get/set methods before overwriting
4060 arr._get = arr.get
4061 arr._set = arr.set
4062
4063 // deprecated, will be removed in node 0.13+
4064 arr.get = BP.get
4065 arr.set = BP.set
4066
4067 arr.write = BP.write
4068 arr.toString = BP.toString
4069 arr.toLocaleString = BP.toString
4070 arr.toJSON = BP.toJSON
4071 arr.equals = BP.equals
4072 arr.compare = BP.compare
4073 arr.copy = BP.copy
4074 arr.slice = BP.slice
4075 arr.readUInt8 = BP.readUInt8
4076 arr.readUInt16LE = BP.readUInt16LE
4077 arr.readUInt16BE = BP.readUInt16BE
4078 arr.readUInt32LE = BP.readUInt32LE
4079 arr.readUInt32BE = BP.readUInt32BE
4080 arr.readInt8 = BP.readInt8
4081 arr.readInt16LE = BP.readInt16LE
4082 arr.readInt16BE = BP.readInt16BE
4083 arr.readInt32LE = BP.readInt32LE
4084 arr.readInt32BE = BP.readInt32BE
4085 arr.readFloatLE = BP.readFloatLE
4086 arr.readFloatBE = BP.readFloatBE
4087 arr.readDoubleLE = BP.readDoubleLE
4088 arr.readDoubleBE = BP.readDoubleBE
4089 arr.writeUInt8 = BP.writeUInt8
4090 arr.writeUInt16LE = BP.writeUInt16LE
4091 arr.writeUInt16BE = BP.writeUInt16BE
4092 arr.writeUInt32LE = BP.writeUInt32LE
4093 arr.writeUInt32BE = BP.writeUInt32BE
4094 arr.writeInt8 = BP.writeInt8
4095 arr.writeInt16LE = BP.writeInt16LE
4096 arr.writeInt16BE = BP.writeInt16BE
4097 arr.writeInt32LE = BP.writeInt32LE
4098 arr.writeInt32BE = BP.writeInt32BE
4099 arr.writeFloatLE = BP.writeFloatLE
4100 arr.writeFloatBE = BP.writeFloatBE
4101 arr.writeDoubleLE = BP.writeDoubleLE
4102 arr.writeDoubleBE = BP.writeDoubleBE
4103 arr.fill = BP.fill
4104 arr.inspect = BP.inspect
4105 arr.toArrayBuffer = BP.toArrayBuffer
4106
4107 return arr
4108}
4109
4110var INVALID_BASE64_RE = /[^+\/0-9A-z]/g
4111
4112function base64clean (str) {
4113 // Node strips out invalid characters like \n and \t from the string, base64-js does not
4114 str = stringtrim(str).replace(INVALID_BASE64_RE, '')
4115 // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
4116 while (str.length % 4 !== 0) {
4117 str = str + '='
4118 }
4119 return str
4120}
4121
4122function stringtrim (str) {
4123 if (str.trim) return str.trim()
4124 return str.replace(/^\s+|\s+$/g, '')
4125}
4126
4127function isArrayish (subject) {
4128 return isArray(subject) || Buffer.isBuffer(subject) ||
4129 subject && typeof subject === 'object' &&
4130 typeof subject.length === 'number'
4131}
4132
4133function toHex (n) {
4134 if (n < 16) return '0' + n.toString(16)
4135 return n.toString(16)
4136}
4137
4138function utf8ToBytes (str) {
4139 var byteArray = []
4140 for (var i = 0; i < str.length; i++) {
4141 var b = str.charCodeAt(i)
4142 if (b <= 0x7F) {
4143 byteArray.push(b)
4144 } else {
4145 var start = i
4146 if (b >= 0xD800 && b <= 0xDFFF) i++
4147 var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%')
4148 for (var j = 0; j < h.length; j++) {
4149 byteArray.push(parseInt(h[j], 16))
4150 }
4151 }
4152 }
4153 return byteArray
4154}
4155
4156function asciiToBytes (str) {
4157 var byteArray = []
4158 for (var i = 0; i < str.length; i++) {
4159 // Node's code seems to be doing this and not & 0x7F..
4160 byteArray.push(str.charCodeAt(i) & 0xFF)
4161 }
4162 return byteArray
4163}
4164
4165function utf16leToBytes (str) {
4166 var c, hi, lo
4167 var byteArray = []
4168 for (var i = 0; i < str.length; i++) {
4169 c = str.charCodeAt(i)
4170 hi = c >> 8
4171 lo = c % 256
4172 byteArray.push(lo)
4173 byteArray.push(hi)
4174 }
4175
4176 return byteArray
4177}
4178
4179function base64ToBytes (str) {
4180 return base64.toByteArray(str)
4181}
4182
4183function blitBuffer (src, dst, offset, length) {
4184 for (var i = 0; i < length; i++) {
4185 if ((i + offset >= dst.length) || (i >= src.length))
4186 break
4187 dst[i + offset] = src[i]
4188 }
4189 return i
4190}
4191
4192function decodeUtf8Char (str) {
4193 try {
4194 return decodeURIComponent(str)
4195 } catch (err) {
4196 return String.fromCharCode(0xFFFD) // UTF 8 invalid char
4197 }
4198}
4199
4200},{}],10:[function(require,module,exports){
4201var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
4202
4203;(function (exports) {
4204 'use strict';
4205
4206 var Arr = (typeof Uint8Array !== 'undefined')
4207 ? Uint8Array
4208 : Array
4209
4210 var PLUS = '+'.charCodeAt(0)
4211 var SLASH = '/'.charCodeAt(0)
4212 var NUMBER = '0'.charCodeAt(0)
4213 var LOWER = 'a'.charCodeAt(0)
4214 var UPPER = 'A'.charCodeAt(0)
4215
4216 function decode (elt) {
4217 var code = elt.charCodeAt(0)
4218 if (code === PLUS)
4219 return 62 // '+'
4220 if (code === SLASH)
4221 return 63 // '/'
4222 if (code < NUMBER)
4223 return -1 //no match
4224 if (code < NUMBER + 10)
4225 return code - NUMBER + 26 + 26
4226 if (code < UPPER + 26)
4227 return code - UPPER
4228 if (code < LOWER + 26)
4229 return code - LOWER + 26
4230 }
4231
4232 function b64ToByteArray (b64) {
4233 var i, j, l, tmp, placeHolders, arr
4234
4235 if (b64.length % 4 > 0) {
4236 throw new Error('Invalid string. Length must be a multiple of 4')
4237 }
4238
4239 // the number of equal signs (place holders)
4240 // if there are two placeholders, than the two characters before it
4241 // represent one byte
4242 // if there is only one, then the three characters before it represent 2 bytes
4243 // this is just a cheap hack to not do indexOf twice
4244 var len = b64.length
4245 placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
4246
4247 // base64 is 4/3 + up to two characters of the original data
4248 arr = new Arr(b64.length * 3 / 4 - placeHolders)
4249
4250 // if there are placeholders, only get up to the last complete 4 chars
4251 l = placeHolders > 0 ? b64.length - 4 : b64.length
4252
4253 var L = 0
4254
4255 function push (v) {
4256 arr[L++] = v
4257 }
4258
4259 for (i = 0, j = 0; i < l; i += 4, j += 3) {
4260 tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
4261 push((tmp & 0xFF0000) >> 16)
4262 push((tmp & 0xFF00) >> 8)
4263 push(tmp & 0xFF)
4264 }
4265
4266 if (placeHolders === 2) {
4267 tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
4268 push(tmp & 0xFF)
4269 } else if (placeHolders === 1) {
4270 tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
4271 push((tmp >> 8) & 0xFF)
4272 push(tmp & 0xFF)
4273 }
4274
4275 return arr
4276 }
4277
4278 function uint8ToBase64 (uint8) {
4279 var i,
4280 extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
4281 output = "",
4282 temp, length
4283
4284 function encode (num) {
4285 return lookup.charAt(num)
4286 }
4287
4288 function tripletToBase64 (num) {
4289 return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
4290 }
4291
4292 // go through the array every three bytes, we'll deal with trailing stuff later
4293 for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
4294 temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
4295 output += tripletToBase64(temp)
4296 }
4297
4298 // pad the end with zeros, but make sure to not forget the extra bytes
4299 switch (extraBytes) {
4300 case 1:
4301 temp = uint8[uint8.length - 1]
4302 output += encode(temp >> 2)
4303 output += encode((temp << 4) & 0x3F)
4304 output += '=='
4305 break
4306 case 2:
4307 temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
4308 output += encode(temp >> 10)
4309 output += encode((temp >> 4) & 0x3F)
4310 output += encode((temp << 2) & 0x3F)
4311 output += '='
4312 break
4313 }
4314
4315 return output
4316 }
4317
4318 exports.toByteArray = b64ToByteArray
4319 exports.fromByteArray = uint8ToBase64
4320}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
4321
4322},{}],11:[function(require,module,exports){
4323exports.read = function(buffer, offset, isLE, mLen, nBytes) {
4324 var e, m,
4325 eLen = nBytes * 8 - mLen - 1,
4326 eMax = (1 << eLen) - 1,
4327 eBias = eMax >> 1,
4328 nBits = -7,
4329 i = isLE ? (nBytes - 1) : 0,
4330 d = isLE ? -1 : 1,
4331 s = buffer[offset + i];
4332
4333 i += d;
4334
4335 e = s & ((1 << (-nBits)) - 1);
4336 s >>= (-nBits);
4337 nBits += eLen;
4338 for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
4339
4340 m = e & ((1 << (-nBits)) - 1);
4341 e >>= (-nBits);
4342 nBits += mLen;
4343 for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
4344
4345 if (e === 0) {
4346 e = 1 - eBias;
4347 } else if (e === eMax) {
4348 return m ? NaN : ((s ? -1 : 1) * Infinity);
4349 } else {
4350 m = m + Math.pow(2, mLen);
4351 e = e - eBias;
4352 }
4353 return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
4354};
4355
4356exports.write = function(buffer, value, offset, isLE, mLen, nBytes) {
4357 var e, m, c,
4358 eLen = nBytes * 8 - mLen - 1,
4359 eMax = (1 << eLen) - 1,
4360 eBias = eMax >> 1,
4361 rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
4362 i = isLE ? 0 : (nBytes - 1),
4363 d = isLE ? 1 : -1,
4364 s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
4365
4366 value = Math.abs(value);
4367
4368 if (isNaN(value) || value === Infinity) {
4369 m = isNaN(value) ? 1 : 0;
4370 e = eMax;
4371 } else {
4372 e = Math.floor(Math.log(value) / Math.LN2);
4373 if (value * (c = Math.pow(2, -e)) < 1) {
4374 e--;
4375 c *= 2;
4376 }
4377 if (e + eBias >= 1) {
4378 value += rt / c;
4379 } else {
4380 value += rt * Math.pow(2, 1 - eBias);
4381 }
4382 if (value * c >= 2) {
4383 e++;
4384 c /= 2;
4385 }
4386
4387 if (e + eBias >= eMax) {
4388 m = 0;
4389 e = eMax;
4390 } else if (e + eBias >= 1) {
4391 m = (value * c - 1) * Math.pow(2, mLen);
4392 e = e + eBias;
4393 } else {
4394 m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
4395 e = 0;
4396 }
4397 }
4398
4399 for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
4400
4401 e = (e << mLen) | m;
4402 eLen += mLen;
4403 for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
4404
4405 buffer[offset + i - d] |= s * 128;
4406};
4407
4408},{}],12:[function(require,module,exports){
4409
4410/**
4411 * isArray
4412 */
4413
4414var isArray = Array.isArray;
4415
4416/**
4417 * toString
4418 */
4419
4420var str = Object.prototype.toString;
4421
4422/**
4423 * Whether or not the given `val`
4424 * is an array.
4425 *
4426 * example:
4427 *
4428 * isArray([]);
4429 * // > true
4430 * isArray(arguments);
4431 * // > false
4432 * isArray('');
4433 * // > false
4434 *
4435 * @param {mixed} val
4436 * @return {bool}
4437 */
4438
4439module.exports = isArray || function (val) {
4440 return !! val && '[object Array]' == str.call(val);
4441};
4442
4443},{}],13:[function(require,module,exports){
4444// shim for using process in browser
4445
4446var process = module.exports = {};
4447
4448process.nextTick = (function () {
4449 var canSetImmediate = typeof window !== 'undefined'
4450 && window.setImmediate;
4451 var canPost = typeof window !== 'undefined'
4452 && window.postMessage && window.addEventListener
4453 ;
4454
4455 if (canSetImmediate) {
4456 return function (f) { return window.setImmediate(f) };
4457 }
4458
4459 if (canPost) {
4460 var queue = [];
4461 window.addEventListener('message', function (ev) {
4462 var source = ev.source;
4463 if ((source === window || source === null) && ev.data === 'process-tick') {
4464 ev.stopPropagation();
4465 if (queue.length > 0) {
4466 var fn = queue.shift();
4467 fn();
4468 }
4469 }
4470 }, true);
4471
4472 return function nextTick(fn) {
4473 queue.push(fn);
4474 window.postMessage('process-tick', '*');
4475 };
4476 }
4477
4478 return function nextTick(fn) {
4479 setTimeout(fn, 0);
4480 };
4481})();
4482
4483process.title = 'browser';
4484process.browser = true;
4485process.env = {};
4486process.argv = [];
4487
4488function noop() {}
4489
4490process.on = noop;
4491process.addListener = noop;
4492process.once = noop;
4493process.off = noop;
4494process.removeListener = noop;
4495process.removeAllListeners = noop;
4496process.emit = noop;
4497
4498process.binding = function (name) {
4499 throw new Error('process.binding is not supported');
4500}
4501
4502// TODO(shtylman)
4503process.cwd = function () { return '/' };
4504process.chdir = function (dir) {
4505 throw new Error('process.chdir is not supported');
4506};
4507
4508},{}],14:[function(require,module,exports){
4509/* See LICENSE file for terms of use */
4510
4511/*
4512 * Text diff implementation.
4513 *
4514 * This library supports the following APIS:
4515 * JsDiff.diffChars: Character by character diff
4516 * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
4517 * JsDiff.diffLines: Line based diff
4518 *
4519 * JsDiff.diffCss: Diff targeted at CSS content
4520 *
4521 * These methods are based on the implementation proposed in
4522 * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
4523 * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
4524 */
4525(function(global, undefined) {
4526 var JsDiff = (function() {
4527 /*jshint maxparams: 5*/
4528 function map(arr, mapper, that) {
4529 if (Array.prototype.map) {
4530 return Array.prototype.map.call(arr, mapper, that);
4531 }
4532
4533 var other = new Array(arr.length);
4534
4535 for (var i = 0, n = arr.length; i < n; i++) {
4536 other[i] = mapper.call(that, arr[i], i, arr);
4537 }
4538 return other;
4539 }
4540 function clonePath(path) {
4541 return { newPos: path.newPos, components: path.components.slice(0) };
4542 }
4543 function removeEmpty(array) {
4544 var ret = [];
4545 for (var i = 0; i < array.length; i++) {
4546 if (array[i]) {
4547 ret.push(array[i]);
4548 }
4549 }
4550 return ret;
4551 }
4552 function escapeHTML(s) {
4553 var n = s;
4554 n = n.replace(/&/g, '&amp;');
4555 n = n.replace(/</g, '&lt;');
4556 n = n.replace(/>/g, '&gt;');
4557 n = n.replace(/"/g, '&quot;');
4558
4559 return n;
4560 }
4561
4562 var Diff = function(ignoreWhitespace) {
4563 this.ignoreWhitespace = ignoreWhitespace;
4564 };
4565 Diff.prototype = {
4566 diff: function(oldString, newString) {
4567 // Handle the identity case (this is due to unrolling editLength == 0
4568 if (newString === oldString) {
4569 return [{ value: newString }];
4570 }
4571 if (!newString) {
4572 return [{ value: oldString, removed: true }];
4573 }
4574 if (!oldString) {
4575 return [{ value: newString, added: true }];
4576 }
4577
4578 newString = this.tokenize(newString);
4579 oldString = this.tokenize(oldString);
4580
4581 var newLen = newString.length, oldLen = oldString.length;
4582 var maxEditLength = newLen + oldLen;
4583 var bestPath = [{ newPos: -1, components: [] }];
4584
4585 // Seed editLength = 0
4586 var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
4587 if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) {
4588 return bestPath[0].components;
4589 }
4590
4591 for (var editLength = 1; editLength <= maxEditLength; editLength++) {
4592 for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) {
4593 var basePath;
4594 var addPath = bestPath[diagonalPath-1],
4595 removePath = bestPath[diagonalPath+1];
4596 oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
4597 if (addPath) {
4598 // No one else is going to attempt to use this value, clear it
4599 bestPath[diagonalPath-1] = undefined;
4600 }
4601
4602 var canAdd = addPath && addPath.newPos+1 < newLen;
4603 var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
4604 if (!canAdd && !canRemove) {
4605 bestPath[diagonalPath] = undefined;
4606 continue;
4607 }
4608
4609 // Select the diagonal that we want to branch from. We select the prior
4610 // path whose position in the new string is the farthest from the origin
4611 // and does not pass the bounds of the diff graph
4612 if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {
4613 basePath = clonePath(removePath);
4614 this.pushComponent(basePath.components, oldString[oldPos], undefined, true);
4615 } else {
4616 basePath = clonePath(addPath);
4617 basePath.newPos++;
4618 this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined);
4619 }
4620
4621 var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath);
4622
4623 if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) {
4624 return basePath.components;
4625 } else {
4626 bestPath[diagonalPath] = basePath;
4627 }
4628 }
4629 }
4630 },
4631
4632 pushComponent: function(components, value, added, removed) {
4633 var last = components[components.length-1];
4634 if (last && last.added === added && last.removed === removed) {
4635 // We need to clone here as the component clone operation is just
4636 // as shallow array clone
4637 components[components.length-1] =
4638 {value: this.join(last.value, value), added: added, removed: removed };
4639 } else {
4640 components.push({value: value, added: added, removed: removed });
4641 }
4642 },
4643 extractCommon: function(basePath, newString, oldString, diagonalPath) {
4644 var newLen = newString.length,
4645 oldLen = oldString.length,
4646 newPos = basePath.newPos,
4647 oldPos = newPos - diagonalPath;
4648 while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) {
4649 newPos++;
4650 oldPos++;
4651
4652 this.pushComponent(basePath.components, newString[newPos], undefined, undefined);
4653 }
4654 basePath.newPos = newPos;
4655 return oldPos;
4656 },
4657
4658 equals: function(left, right) {
4659 var reWhitespace = /\S/;
4660 if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {
4661 return true;
4662 } else {
4663 return left === right;
4664 }
4665 },
4666 join: function(left, right) {
4667 return left + right;
4668 },
4669 tokenize: function(value) {
4670 return value;
4671 }
4672 };
4673
4674 var CharDiff = new Diff();
4675
4676 var WordDiff = new Diff(true);
4677 var WordWithSpaceDiff = new Diff();
4678 WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) {
4679 return removeEmpty(value.split(/(\s+|\b)/));
4680 };
4681
4682 var CssDiff = new Diff(true);
4683 CssDiff.tokenize = function(value) {
4684 return removeEmpty(value.split(/([{}:;,]|\s+)/));
4685 };
4686
4687 var LineDiff = new Diff();
4688 LineDiff.tokenize = function(value) {
4689 var retLines = [],
4690 lines = value.split(/^/m);
4691
4692 for(var i = 0; i < lines.length; i++) {
4693 var line = lines[i],
4694 lastLine = lines[i - 1];
4695
4696 // Merge lines that may contain windows new lines
4697 if (line == '\n' && lastLine && lastLine[lastLine.length - 1] === '\r') {
4698 retLines[retLines.length - 1] += '\n';
4699 } else if (line) {
4700 retLines.push(line);
4701 }
4702 }
4703
4704 return retLines;
4705 };
4706
4707 return {
4708 Diff: Diff,
4709
4710 diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); },
4711 diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); },
4712 diffWordsWithSpace: function(oldStr, newStr) { return WordWithSpaceDiff.diff(oldStr, newStr); },
4713 diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); },
4714
4715 diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); },
4716
4717 createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) {
4718 var ret = [];
4719
4720 ret.push('Index: ' + fileName);
4721 ret.push('===================================================================');
4722 ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader));
4723 ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader));
4724
4725 var diff = LineDiff.diff(oldStr, newStr);
4726 if (!diff[diff.length-1].value) {
4727 diff.pop(); // Remove trailing newline add
4728 }
4729 diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier
4730
4731 function contextLines(lines) {
4732 return map(lines, function(entry) { return ' ' + entry; });
4733 }
4734 function eofNL(curRange, i, current) {
4735 var last = diff[diff.length-2],
4736 isLast = i === diff.length-2,
4737 isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed);
4738
4739 // Figure out if this is the last line for the given file and missing NL
4740 if (!/\n$/.test(current.value) && (isLast || isLastOfType)) {
4741 curRange.push('\\ No newline at end of file');
4742 }
4743 }
4744
4745 var oldRangeStart = 0, newRangeStart = 0, curRange = [],
4746 oldLine = 1, newLine = 1;
4747 for (var i = 0; i < diff.length; i++) {
4748 var current = diff[i],
4749 lines = current.lines || current.value.replace(/\n$/, '').split('\n');
4750 current.lines = lines;
4751
4752 if (current.added || current.removed) {
4753 if (!oldRangeStart) {
4754 var prev = diff[i-1];
4755 oldRangeStart = oldLine;
4756 newRangeStart = newLine;
4757
4758 if (prev) {
4759 curRange = contextLines(prev.lines.slice(-4));
4760 oldRangeStart -= curRange.length;
4761 newRangeStart -= curRange.length;
4762 }
4763 }
4764 curRange.push.apply(curRange, map(lines, function(entry) { return (current.added?'+':'-') + entry; }));
4765 eofNL(curRange, i, current);
4766
4767 if (current.added) {
4768 newLine += lines.length;
4769 } else {
4770 oldLine += lines.length;
4771 }
4772 } else {
4773 if (oldRangeStart) {
4774 // Close out any changes that have been output (or join overlapping)
4775 if (lines.length <= 8 && i < diff.length-2) {
4776 // Overlapping
4777 curRange.push.apply(curRange, contextLines(lines));
4778 } else {
4779 // end the range and output
4780 var contextSize = Math.min(lines.length, 4);
4781 ret.push(
4782 '@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize)
4783 + ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize)
4784 + ' @@');
4785 ret.push.apply(ret, curRange);
4786 ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));
4787 if (lines.length <= 4) {
4788 eofNL(ret, i, current);
4789 }
4790
4791 oldRangeStart = 0; newRangeStart = 0; curRange = [];
4792 }
4793 }
4794 oldLine += lines.length;
4795 newLine += lines.length;
4796 }
4797 }
4798
4799 return ret.join('\n') + '\n';
4800 },
4801
4802 applyPatch: function(oldStr, uniDiff) {
4803 var diffstr = uniDiff.split('\n');
4804 var diff = [];
4805 var remEOFNL = false,
4806 addEOFNL = false;
4807
4808 for (var i = (diffstr[0][0]==='I'?4:0); i < diffstr.length; i++) {
4809 if(diffstr[i][0] === '@') {
4810 var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
4811 diff.unshift({
4812 start:meh[3],
4813 oldlength:meh[2],
4814 oldlines:[],
4815 newlength:meh[4],
4816 newlines:[]
4817 });
4818 } else if(diffstr[i][0] === '+') {
4819 diff[0].newlines.push(diffstr[i].substr(1));
4820 } else if(diffstr[i][0] === '-') {
4821 diff[0].oldlines.push(diffstr[i].substr(1));
4822 } else if(diffstr[i][0] === ' ') {
4823 diff[0].newlines.push(diffstr[i].substr(1));
4824 diff[0].oldlines.push(diffstr[i].substr(1));
4825 } else if(diffstr[i][0] === '\\') {
4826 if (diffstr[i-1][0] === '+') {
4827 remEOFNL = true;
4828 } else if(diffstr[i-1][0] === '-') {
4829 addEOFNL = true;
4830 }
4831 }
4832 }
4833
4834 var str = oldStr.split('\n');
4835 for (var i = diff.length - 1; i >= 0; i--) {
4836 var d = diff[i];
4837 for (var j = 0; j < d.oldlength; j++) {
4838 if(str[d.start-1+j] !== d.oldlines[j]) {
4839 return false;
4840 }
4841 }
4842 Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines));
4843 }
4844
4845 if (remEOFNL) {
4846 while (!str[str.length-1]) {
4847 str.pop();
4848 }
4849 } else if (addEOFNL) {
4850 str.push('');
4851 }
4852 return str.join('\n');
4853 },
4854
4855 convertChangesToXML: function(changes){
4856 var ret = [];
4857 for ( var i = 0; i < changes.length; i++) {
4858 var change = changes[i];
4859 if (change.added) {
4860 ret.push('<ins>');
4861 } else if (change.removed) {
4862 ret.push('<del>');
4863 }
4864
4865 ret.push(escapeHTML(change.value));
4866
4867 if (change.added) {
4868 ret.push('</ins>');
4869 } else if (change.removed) {
4870 ret.push('</del>');
4871 }
4872 }
4873 return ret.join('');
4874 },
4875
4876 // See: http://code.google.com/p/google-diff-match-patch/wiki/API
4877 convertChangesToDMP: function(changes){
4878 var ret = [], change;
4879 for ( var i = 0; i < changes.length; i++) {
4880 change = changes[i];
4881 ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]);
4882 }
4883 return ret;
4884 }
4885 };
4886 })();
4887
4888 if (typeof module !== 'undefined') {
4889 module.exports = JsDiff;
4890 }
4891 else if (typeof define === 'function') {
4892 define([], function() { return JsDiff; });
4893 }
4894 else if (typeof global.JsDiff === 'undefined') {
4895 global.JsDiff = JsDiff;
4896 }
4897})(this);
4898
4899},{}],15:[function(require,module,exports){
4900// intentionally commented out as it makes it slower...
4901//'use strict';
4902
4903var arr = [];
4904
4905module.exports = function (a, b) {
4906 if (a === b) {
4907 return 0;
4908 }
4909
4910 var aLen = a.length;
4911 var bLen = b.length;
4912
4913 if (aLen === 0) {
4914 return b.length;
4915 }
4916
4917 if (bLen === 0) {
4918 return a.length;
4919 }
4920
4921 var bCharCode;
4922 var ret;
4923 var tmp;
4924 var tmp2;
4925 var i = 0;
4926 var j = 0;
4927
4928 while (i < aLen) {
4929 arr[i] = ++i;
4930 }
4931
4932 while (j < bLen) {
4933 bCharCode = b.charCodeAt(j);
4934 tmp = j++;
4935 ret = j;
4936
4937 for (i = 0; i < aLen; i++) {
4938 tmp2 = bCharCode === a.charCodeAt(i) ? tmp : tmp + 1;
4939 tmp = arr[i];
4940 ret = arr[i] = tmp > ret ? tmp2 > ret ? ret + 1 : tmp2 : tmp2 > tmp ? tmp + 1 : tmp2;
4941 }
4942 }
4943
4944 return ret;
4945};
4946
4947},{}],16:[function(require,module,exports){
4948var utils = require(24);
4949var TextSerializer = require(20);
4950var colorDiff = require(28);
4951
4952var ansiStyles = utils.extend({}, require(25));
4953Object.keys(ansiStyles).forEach(function (styleName) {
4954 ansiStyles[styleName.toLowerCase()] = ansiStyles[styleName];
4955});
4956
4957function AnsiSerializer() {}
4958
4959AnsiSerializer.prototype = new TextSerializer();
4960
4961var colorPalettes = {
4962 16: {
4963 '#000000': 'black',
4964 '#ff0000': 'red',
4965 '#00ff00': 'green',
4966 '#ffff00': 'yellow',
4967 '#0000ff': 'blue',
4968 '#ff00ff': 'magenta',
4969 '#00ffff': 'cyan',
4970 '#ffffff': 'white',
4971 '#808080': 'gray'
4972 },
4973 256: {}
4974};
4975
4976var diffPalettes = {};
4977
4978function convertColorToObject(color) {
4979 if (color.length < 6) {
4980 // Allow CSS shorthand
4981 color = color.replace(/^#?([0-9a-f])([0-9a-f])([0-9a-f])$/i, '$1$1$2$2$3$3');
4982 }
4983 // Split color into red, green, and blue components
4984 var hexMatch = color.match(/^#?([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])$/i);
4985 if (hexMatch) {
4986 return {
4987 R: parseInt(hexMatch[1], 16),
4988 G: parseInt(hexMatch[2], 16),
4989 B: parseInt(hexMatch[3], 16)
4990 };
4991 }
4992}
4993
4994function toHexColor(colorObject) {
4995 var hexString = (Math.round(colorObject.R) * 0x10000 + Math.round(colorObject.G) * 0x100 + Math.round(colorObject.B)).toString(16);
4996 return '#' + ('00000'.substr(0, 6 - hexString.length)) + hexString;
4997}
4998
4999function firstUp(text) {
5000 return text.substring(0, 1).toUpperCase() + text.substring(1);
5001}
5002
5003diffPalettes[16] = Object.keys(colorPalettes[16]).map(convertColorToObject);
5004diffPalettes['bg16'] = Object.keys(colorPalettes[16]).filter(function (color) {
5005 return color !== "#808080";
5006}).map(convertColorToObject);
5007diffPalettes[256] = [].concat(diffPalettes[16]);
5008var nextAnsiColorNumber = 16;
5009function registerNext256PaletteEntry(obj) {
5010 diffPalettes[256].push(obj);
5011 colorPalettes[256][toHexColor(obj)] = nextAnsiColorNumber;
5012 nextAnsiColorNumber += 1;
5013}
5014
5015for (var r = 0 ; r < 6 ; r += 1) {
5016 for (var g = 0 ; g < 6 ; g += 1) {
5017 for (var b = 0 ; b < 6 ; b += 1) {
5018 registerNext256PaletteEntry({
5019 R: Math.round(r * 256 / 6),
5020 G: Math.round(g * 256 / 6),
5021 B: Math.round(b * 256 / 6)
5022 });
5023 }
5024 }
5025}
5026
5027[
5028 0x08, 0x12, 0x1c, 0x26, 0x30, 0x3a, 0x44, 0x4e, 0x58, 0x60, 0x66, 0x76,
5029 0x80, 0x8a, 0x94, 0x9e, 0xa8, 0xb2, 0xbc, 0xc6, 0xd0, 0xda, 0xe4, 0xee
5030].forEach(function (value) {
5031 registerNext256PaletteEntry({R: value, G: value, B: value});
5032});
5033
5034var rgbRegexp = /^(?:bg)?#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
5035AnsiSerializer.prototype.text = function () {
5036 var content = arguments[0];
5037 if (arguments.length > 1) {
5038 for (var i = 1; i < arguments.length; i += 1) {
5039 var styleName = arguments[i];
5040
5041 if (ansiStyles[styleName]) {
5042 content = ansiStyles[styleName].open + content + ansiStyles[styleName].close;
5043 } else if (rgbRegexp.test(styleName)) {
5044 var originalStyleName = styleName;
5045 var isBackgroundColor = styleName.substring(0, 2) === 'bg';
5046 var colorName = isBackgroundColor ? styleName.substring(2) : styleName;
5047
5048 var color16Hex = toHexColor(colorDiff.closest(convertColorToObject(colorName),
5049 diffPalettes[isBackgroundColor ? 'bg16' : 16]));
5050 var closestColor16 = colorPalettes[16][color16Hex];
5051
5052 var color256Hex = toHexColor(colorDiff.closest(convertColorToObject(colorName), diffPalettes[256]));
5053 var closest256ColorIndex = colorPalettes[256][color256Hex];
5054
5055 if (isBackgroundColor) {
5056 styleName = 'bg' + firstUp(closestColor16);
5057 } else {
5058 styleName = closestColor16;
5059 }
5060
5061 var open = ansiStyles[styleName].open;
5062 var close = ansiStyles[styleName].close;
5063 if (color16Hex !== color256Hex) {
5064 open += '\x1b[' + (isBackgroundColor ? 48 : 38) + ';5;' + closest256ColorIndex + 'm';
5065 }
5066 ansiStyles[originalStyleName] = {open: open, close: close};
5067 content = open + content + close;
5068 }
5069 }
5070 }
5071
5072 return content;
5073};
5074
5075module.exports = AnsiSerializer;
5076
5077},{}],17:[function(require,module,exports){
5078var cssStyles = require(21);
5079var flattenBlocksInLines = require(23);
5080
5081function ColoredConsoleSerializer() {}
5082
5083ColoredConsoleSerializer.prototype.serialize = function (lines) {
5084 var formatString = '';
5085 var styleStrings = [];
5086 this.serializeLines(flattenBlocksInLines(lines)).forEach(function (entry) {
5087 if (entry) {
5088 formatString += entry[0];
5089 if (entry.length > 1) {
5090 styleStrings.push(entry[1]);
5091 }
5092 }
5093 });
5094 return [formatString].concat(styleStrings);
5095};
5096
5097ColoredConsoleSerializer.prototype.serializeLines = function (lines) {
5098 var result = [];
5099 lines.forEach(function (line, i) {
5100 if (i > 0) {
5101 result.push(['%c\n ', '']);
5102 }
5103 Array.prototype.push.apply(result, this.serializeLine(line));
5104 }, this);
5105 return result;
5106};
5107
5108ColoredConsoleSerializer.prototype.serializeLine = function (line) {
5109 var result = [];
5110 line.forEach(function (outputEntry) {
5111 if (this[outputEntry.style]) {
5112 result.push(this[outputEntry.style].apply(this, outputEntry.args));
5113 }
5114 }, this);
5115 return result;
5116};
5117
5118ColoredConsoleSerializer.prototype.block = function (content) {
5119 return this.serializeLines(content);
5120};
5121
5122var rgbRegexp = /^(?:bg)?#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
5123ColoredConsoleSerializer.prototype.text = function () {
5124 var content = String(arguments[0]);
5125 if (content === '') {
5126 return null;
5127 }
5128 var result = ['%c' + content.replace(/%/g, '%%')];
5129 var styleProperties = [];
5130
5131 if (arguments.length > 1) {
5132 for (var i = 1; i < arguments.length; i += 1) {
5133 var styleName = arguments[i];
5134 if (rgbRegexp.test(styleName)) {
5135 if (styleName.substring(0, 2) === 'bg') {
5136 styleProperties.push('background-color: ' + styleName.substring(2));
5137 } else {
5138 styleProperties.push('color: ' + styleName);
5139 }
5140 } else if (cssStyles[styleName]) {
5141 styleProperties.push(cssStyles[styleName]);
5142 }
5143 }
5144 }
5145 result.push(styleProperties.join('; '));
5146 return result;
5147};
5148
5149module.exports = ColoredConsoleSerializer;
5150
5151},{}],18:[function(require,module,exports){
5152var cssStyles = require(21);
5153
5154function HtmlSerializer() {}
5155
5156HtmlSerializer.prototype.serialize = function (lines) {
5157 return '<div style="font-family: monospace; white-space: nowrap">\n' + this.serializeLines(lines) + '\n</div>';
5158};
5159
5160HtmlSerializer.prototype.serializeLines = function (lines) {
5161 return lines.map(function (line) {
5162 return ' <div>' + (this.serializeLine(line).join('') || '&nbsp;') + '</div>';
5163 }, this).join('\n');
5164};
5165
5166HtmlSerializer.prototype.serializeLine = function (line) {
5167 return line.map(function (outputEntry) {
5168 return this[outputEntry.style] ?
5169 this[outputEntry.style].apply(this, outputEntry.args) :
5170 '';
5171 }, this);
5172};
5173
5174HtmlSerializer.prototype.block = function (content) {
5175 return '<div style="display: inline-block; vertical-align: top">\n' +
5176 this.serializeLines(content) +
5177 '\n</div>';
5178};
5179
5180var rgbRegexp = /^(?:bg)?#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
5181HtmlSerializer.prototype.text = function () {
5182 var content = String(arguments[0])
5183 .replace(/&/g, '&amp;')
5184 .replace(/ /g, '&nbsp;')
5185 .replace(/</g, '&lt;')
5186 .replace(/>/g, '&gt;')
5187 .replace(/"/g, '&quot;');
5188
5189 if (arguments.length > 1) {
5190 var styleProperties = [];
5191 for (var i = 1; i < arguments.length; i += 1) {
5192 var styleName = arguments[i];
5193 if (rgbRegexp.test(styleName)) {
5194 if (styleName.substring(0, 2) === 'bg') {
5195 styleProperties.push('background-color: ' + styleName.substring(2));
5196 } else {
5197 styleProperties.push('color: ' + styleName);
5198 }
5199 } else if (cssStyles[styleName]) {
5200 styleProperties.push(cssStyles[styleName]);
5201 }
5202
5203 }
5204 content = '<span style="' + styleProperties.join('; ') + '">' + content + '</span>';
5205 }
5206 return content;
5207};
5208
5209module.exports = HtmlSerializer;
5210
5211},{}],19:[function(require,module,exports){
5212/*global window*/
5213var utils = require(24);
5214var extend = utils.extend;
5215var duplicateText = require(22);
5216
5217function MagicPen(options) {
5218 if (!(this instanceof MagicPen)) {
5219 return new MagicPen(options);
5220 }
5221
5222 options = options || {};
5223
5224 var indentationWidth = 'indentationWidth' in options ?
5225 options.indentationWidth : 2;
5226 this.indentationWidth = Math.max(indentationWidth, 0);
5227
5228 this.indentationLevel = 0;
5229 this.output = [[]];
5230 this.styles = {};
5231 this.installedPlugins = [];
5232}
5233
5234if (typeof window !== 'undefined' && typeof window.navigator !== 'undefined') {
5235 if (window.mochaPhantomJS) {
5236 MagicPen.defaultFormat = 'ansi'; // colored console
5237 } else {
5238 MagicPen.defaultFormat = 'html'; // Browser
5239 }
5240} else if (require(30)) {
5241 MagicPen.defaultFormat = 'ansi'; // colored console
5242} else {
5243 MagicPen.defaultFormat = 'text'; // Plain text
5244}
5245
5246MagicPen.prototype.newline = MagicPen.prototype.nl = function (count) {
5247 if (typeof count === 'undefined') {
5248 count = 1;
5249 }
5250
5251 if (count === 0) {
5252 return this;
5253 }
5254
5255 for (var i = 0; i < count; i += 1) {
5256 this.output.push([]);
5257 }
5258 return this;
5259};
5260
5261MagicPen.serializers = {
5262 text: require(20),
5263 html: require(18),
5264 ansi: require(16),
5265 coloredConsole: require(17)
5266};
5267
5268function hasSameTextStyling(a, b) {
5269 if (!a || !b || a.style !== 'text' || b.style !== 'text') {
5270 return false;
5271 }
5272
5273 return utils.arrayEquals(Array.prototype.slice.call(a.args, 1),
5274 Array.prototype.slice.call(b.args, 1));
5275}
5276
5277function normalizeLine(line) {
5278 if (line.length === 0) {
5279 return line;
5280 }
5281
5282 var result = [line[0]];
5283 for (var i = 1; i < line.length; i += 1) {
5284 var lastEntry = result[result.length - 1];
5285 var entry = line[i];
5286 if (entry.style === 'text' && entry.args[0] === '') {
5287 continue;
5288 }
5289
5290 if (hasSameTextStyling(lastEntry, entry)) {
5291 result[result.length - 1] = {
5292 style: entry.style,
5293 args: [lastEntry.args[0] + entry.args[0]].concat(entry.args.slice(1))
5294 };
5295 } else {
5296 result.push(entry);
5297 }
5298 }
5299
5300 return result;
5301}
5302
5303MagicPen.prototype.write = function (options) {
5304 if (this.styles[options.style]) {
5305 this.styles[options.style].apply(this, options.args);
5306 return this;
5307 }
5308 var lastLine = this.output[this.output.length - 1];
5309 var lastEntry = lastLine[lastLine.length - 1];
5310 if (hasSameTextStyling(lastEntry, options)) {
5311 options.args[0] = lastEntry.args[0] + options.args[0];
5312 lastLine[lastLine.length - 1] = options;
5313 } else {
5314 lastLine.push(options);
5315 }
5316
5317 return this;
5318};
5319
5320MagicPen.prototype.indentLines = function () {
5321 this.indentationLevel += 1;
5322 return this;
5323};
5324
5325MagicPen.prototype.indent = MagicPen.prototype.i = function () {
5326 for (var i = 0; i < this.indentationLevel; i += 1) {
5327 this.space(this.indentationWidth);
5328 }
5329 return this;
5330};
5331
5332MagicPen.prototype.outdentLines = function () {
5333 this.indentationLevel = Math.max(0, this.indentationLevel - 1);
5334 return this;
5335};
5336
5337MagicPen.prototype.addStyle = function (style, handler, allowRedefinition) {
5338 if (this[style] && !allowRedefinition) {
5339 throw new Error('"' + style + '" style is already defined, set 3rd arg (allowRedefinition) to true to define it anyway');
5340 }
5341 this.styles[style] = handler;
5342 this[style] = function () {
5343 handler.apply(this, arguments);
5344 return this;
5345 };
5346 return this;
5347};
5348
5349MagicPen.prototype.toString = function (format) {
5350 format = format || 'text';
5351 if (format === 'auto') {
5352 format = MagicPen.defaultFormat;
5353 }
5354 var serializer = new MagicPen.serializers[format]();
5355 return serializer.serialize(this.output);
5356};
5357
5358MagicPen.prototype.text = function () {
5359 var content = arguments[0];
5360 if (content === '') {
5361 return this;
5362 }
5363
5364 var args = new Array(arguments.length);
5365 for (var i = 0; i < arguments.length; i += 1) {
5366 args[i] = arguments[i];
5367 }
5368 content = String(content);
5369 if (content.indexOf('\n') !== -1) {
5370 args = args.slice(1);
5371 var lines = content.split(/\n/);
5372 lines.forEach(function (lineContent, index) {
5373 this.write({ style: 'text', args: [lineContent].concat(args) });
5374 if (index < lines.length - 1) {
5375 this.nl();
5376 }
5377 }, this);
5378 return this;
5379 } else {
5380 return this.write({ style: 'text', args: args });
5381 }
5382};
5383
5384MagicPen.prototype.removeFormatting = function () {
5385 var result = this.clone();
5386 this.output.forEach(function (line, index) {
5387 result.output[index] = normalizeLine(line.map(function (outputEntry) {
5388 return outputEntry.style === 'text' ?
5389 { style: 'text', args: [outputEntry.args[0]] } :
5390 outputEntry;
5391 }));
5392 });
5393 result.indentationLevel = this.indentationLevel;
5394 return result;
5395};
5396
5397MagicPen.prototype.getContentFromArguments = function (args) {
5398 var clone;
5399 if (args[0].isMagicPen) {
5400 return args[0];
5401 } else if (typeof args[0] === 'function') {
5402 clone = this.clone();
5403 args[0].call(clone, clone);
5404 return clone;
5405 } else if (typeof args[0] === 'string') {
5406 clone = this.clone();
5407 clone[args[0]].apply(clone, Array.prototype.slice.call(args, 1));
5408 return clone;
5409 } else {
5410 throw new Error('Requires the arguments to be:\n' +
5411 'a pen or\n' +
5412 'a callback append content to a penor\n' +
5413 'a style and arguments for that style');
5414 }
5415};
5416
5417MagicPen.prototype.block = function () {
5418 var pen = this.getContentFromArguments(arguments);
5419
5420 var blockOutput = pen.output.map(function (line) {
5421 return [].concat(line);
5422 });
5423 return this.write({ style: 'block', args: [blockOutput] });
5424};
5425
5426MagicPen.prototype.append = function () {
5427 var pen = this.getContentFromArguments(arguments);
5428
5429 if (pen.isEmpty()) {
5430 return this;
5431 }
5432
5433 var lastLine = this.output[this.output.length - 1];
5434 Array.prototype.push.apply(lastLine, pen.output[0]);
5435 this.output[this.output.length - 1] = normalizeLine(lastLine);
5436
5437 this.output.push.apply(this.output, pen.output.slice(1));
5438
5439 return this;
5440};
5441
5442MagicPen.prototype.prependLinesWith = function () {
5443 var pen = this.getContentFromArguments(arguments);
5444
5445 if (pen.isEmpty()) {
5446 return this;
5447 }
5448
5449 if (pen.output.length > 1) {
5450 throw new Error('PrependLinesWith only supports a pen with single line content');
5451 }
5452
5453 var height = this.size().height;
5454 var output = this.clone();
5455 output.block(function () {
5456 for (var i = 0; i < height; i += 1) {
5457 if (0 < i) {
5458 this.nl();
5459 }
5460 this.append(pen);
5461 }
5462 });
5463 output.block(this);
5464
5465 this.output = output.output;
5466 return this;
5467};
5468
5469MagicPen.prototype.space = MagicPen.prototype.sp = function (count) {
5470 if (count === 0) {
5471 return this;
5472 }
5473
5474 if (typeof count === 'undefined') {
5475 count = 1;
5476 }
5477
5478 this.text(duplicateText(' ', count));
5479 return this;
5480};
5481
5482[
5483 'bold', 'dim', 'italic', 'underline', 'inverse', 'hidden',
5484 'strikeThrough', 'black', 'red', 'green', 'yellow', 'blue',
5485 'magenta', 'cyan', 'white', 'gray', 'bgBlack', 'bgRed',
5486 'bgGreen', 'bgYellow', 'bgBlue', 'bgMagenta', 'bgCyan',
5487 'bgWhite'
5488].forEach(function (textStyle) {
5489 MagicPen.prototype[textStyle] = MagicPen.prototype[textStyle.toLowerCase()] = function (content) {
5490 return this.text.call(this, content, textStyle);
5491 };
5492});
5493
5494MagicPen.prototype.clone = function () {
5495 function MagicPenClone() {}
5496 MagicPenClone.prototype = this;
5497 var clonedPen = new MagicPenClone();
5498 clonedPen.styles = extend({}, this.styles);
5499 clonedPen.indentationLevel = 0;
5500 clonedPen.output = [[]];
5501 clonedPen.installedPlugins = [].concat(this.installedPlugins);
5502 return clonedPen;
5503};
5504
5505MagicPen.prototype.isMagicPen = true;
5506
5507MagicPen.prototype.size = function () {
5508 return utils.calculateSize(this.output);
5509};
5510
5511MagicPen.prototype.installPlugin = function (plugin) {
5512 var alreadyInstalled = this.installedPlugins.some(function (installedPlugin) {
5513 return installedPlugin === plugin.name;
5514 });
5515
5516 if (alreadyInstalled) {
5517 return;
5518 }
5519
5520 if (typeof plugin !== 'object' ||
5521 typeof plugin.name !== 'string' ||
5522 typeof plugin.installInto !== 'function' ||
5523 (plugin.dependencies && !Array.isArray(plugin.dependencies))) {
5524 throw new Error('Plugins must adhere to the following interface\n' +
5525 '{\n' +
5526 ' name: <plugin name>,\n' +
5527 ' dependencies: <an optional list of dependencies>,\n' +
5528 ' installInto: <a function that will update the given magicpen instance>\n' +
5529 '}');
5530 }
5531
5532 if (plugin.dependencies) {
5533 var installedPlugins = this.installedPlugins;
5534 var unfulfilledDependencies = plugin.dependencies.filter(function (dependency) {
5535 return !installedPlugins.some(function (plugin) {
5536 return plugin === dependency;
5537 });
5538 });
5539
5540 if (unfulfilledDependencies.length === 1) {
5541 throw new Error(plugin.name + ' requires plugin ' + unfulfilledDependencies[0]);
5542 } else if (unfulfilledDependencies.length > 1) {
5543 throw new Error(plugin.name + ' requires plugins ' +
5544 unfulfilledDependencies.slice(0, -1).join(', ') +
5545 ' and ' + unfulfilledDependencies[unfulfilledDependencies.length - 1]);
5546 }
5547 }
5548
5549 this.installedPlugins.push(plugin.name);
5550 plugin.installInto(this);
5551
5552 return this; // for chaining
5553};
5554
5555function replaceText(output, outputArray, regexp, cb) {
5556 var replacedOutput = output;
5557 outputArray.forEach(function (line, i) {
5558 if (0 < i) {
5559 replacedOutput.nl();
5560 }
5561
5562 line.forEach(function (outputEntry, j) {
5563 if (outputEntry.style === 'block') {
5564 return replacedOutput.output[replacedOutput.output.length - 1].push({
5565 style: 'block',
5566 args: [replaceText(output.clone(), outputEntry.args[0], regexp, cb)]
5567 });
5568 } else if (outputEntry.style !== 'text') {
5569 return replacedOutput.output[replacedOutput.output.length - 1].push(outputEntry);
5570 }
5571
5572 if (regexp.global) {
5573 regexp.lastIndex = 0;
5574 }
5575 var styles = outputEntry.args.slice(1);
5576 var m;
5577 var first = true;
5578 var lastIndex = 0;
5579 var text = outputEntry.args[0];
5580 while ((m = regexp.exec(text)) !== null && (regexp.global || first)) {
5581 if (lastIndex < m.index) {
5582 replacedOutput.text.apply(replacedOutput, [text.substring(lastIndex, m.index)].concat(styles));
5583 }
5584
5585 cb.apply(replacedOutput, [styles].concat(m));
5586 first = false;
5587 lastIndex = m.index + m[0].length;
5588 }
5589
5590 if (lastIndex === 0) {
5591 var lastLine;
5592 if (replacedOutput.output.length === 0) {
5593 lastLine = replacedOutput.output[0] = [];
5594 } else {
5595 lastLine = replacedOutput.output[replacedOutput.output.length - 1];
5596 }
5597
5598 lastLine.push(outputEntry);
5599 } else if (lastIndex < text.length) {
5600 replacedOutput.text.apply(replacedOutput, [text.substring(lastIndex, text.length)].concat(styles));
5601 }
5602 }, this);
5603 }, this);
5604
5605 return replacedOutput.output.map(normalizeLine);
5606}
5607
5608MagicPen.prototype.isEmpty = function () {
5609 return this.output.length === 1 && this.output[0].length === 0;
5610};
5611
5612
5613MagicPen.prototype.replaceText = function (regexp, cb) {
5614 if (this.isEmpty()) {
5615 return this;
5616 }
5617
5618 if (typeof regexp === 'string') {
5619 regexp = new RegExp(utils.escapeRegExp(regexp), 'g');
5620 }
5621
5622 if (typeof cb === 'string') {
5623 var text = cb;
5624 cb = function (styles, _) {
5625 var args = [text].concat(styles);
5626 this.text.apply(this, args);
5627 };
5628 }
5629
5630
5631 if (arguments.length === 1) {
5632 cb = regexp;
5633 regexp = /.*/;
5634 }
5635
5636 this.output = replaceText(this.clone(), this.output, regexp, cb);
5637
5638 return this;
5639};
5640
5641module.exports = MagicPen;
5642
5643},{}],20:[function(require,module,exports){
5644var flattenBlocksInLines = require(23);
5645
5646function TextSerializer() {}
5647
5648TextSerializer.prototype.serialize = function (lines) {
5649 lines = flattenBlocksInLines(lines);
5650 return lines.map(this.serializeLine, this).join('\n');
5651};
5652
5653TextSerializer.prototype.serializeLine = function (line) {
5654 return line.map(function (outputEntry) {
5655 return this[outputEntry.style] ?
5656 String(this[outputEntry.style].apply(this, outputEntry.args)) :
5657 '';
5658 }, this).join('');
5659};
5660
5661TextSerializer.prototype.text = function (content) {
5662 return content;
5663};
5664
5665TextSerializer.prototype.block = function (content) {
5666 return this.serialize(content);
5667};
5668
5669module.exports = TextSerializer;
5670
5671},{}],21:[function(require,module,exports){
5672var cssStyles = {
5673 bold: 'font-weight: bold',
5674 dim: 'opacity: 0.7',
5675 italic: 'font-style: italic',
5676 underline: 'text-decoration: underline',
5677 inverse: '-webkit-filter: invert(%100); filter: invert(100%)',
5678 hidden: 'visibility: hidden',
5679 strikeThrough: 'text-decoration: line-through',
5680
5681 black: 'color: black',
5682 red: 'color: red',
5683 green: 'color: green',
5684 yellow: 'color: yellow',
5685 blue: 'color: blue',
5686 magenta: 'color: magenta',
5687 cyan: 'color: cyan',
5688 white: 'color: white',
5689 gray: 'color: gray',
5690
5691 bgBlack: 'background-color: black',
5692 bgRed: 'background-color: red',
5693 bgGreen: 'background-color: green',
5694 bgYellow: 'background-color: yellow',
5695 bgBlue: 'background-color: blue',
5696 bgMagenta: 'background-color: magenta',
5697 bgCyan: 'background-color: cyan',
5698 bgWhite: 'background-color: white'
5699};
5700
5701Object.keys(cssStyles).forEach(function (styleName) {
5702 cssStyles[styleName.toLowerCase()] = cssStyles[styleName];
5703});
5704
5705module.exports = cssStyles;
5706
5707},{}],22:[function(require,module,exports){
5708var whitespaceCacheLength = 256;
5709var whitespaceCache = [''];
5710for (var i = 1; i <= whitespaceCacheLength; i += 1) {
5711 whitespaceCache[i] = whitespaceCache[i - 1] + ' ';
5712}
5713
5714function duplicateText(content, times) {
5715 if (times < 0) {
5716 return '';
5717 }
5718
5719 var result = '';
5720
5721 if (content === ' ') {
5722 if (times <= whitespaceCacheLength) {
5723 return whitespaceCache[times];
5724 }
5725
5726 var segment = whitespaceCache[whitespaceCacheLength];
5727 var numberOfSegments = Math.floor(times / whitespaceCacheLength);
5728 for (var i = 0; i < numberOfSegments; i += 1) {
5729 result += segment;
5730 }
5731 result += whitespaceCache[times % whitespaceCacheLength];
5732 } else {
5733 for (var j = 0; j < times; j += 1) {
5734 result += content;
5735 }
5736 }
5737
5738 return result;
5739}
5740
5741module.exports = duplicateText;
5742
5743},{}],23:[function(require,module,exports){
5744var utils = require(24);
5745var duplicateText = require(22);
5746
5747function createPadding(length) {
5748 return { style: 'text', args: [duplicateText(' ', length)] };
5749}
5750
5751function lineContainsBlocks(line) {
5752 return line.some(function (outputEntry) {
5753 return outputEntry.style === 'block' ||
5754 (outputEntry.style === 'text' && String(outputEntry.args[0]).indexOf('\n') !== -1);
5755 });
5756}
5757
5758function flattenBlocksInOutputEntry(outputEntry) {
5759 switch (outputEntry.style) {
5760 case 'text': return String(outputEntry.args[0]).split('\n').map(function (line) {
5761 var args = [line].concat(outputEntry.args.slice(1));
5762 return [{ style: 'text', args: args }];
5763 });
5764 case 'block': return flattenBlocksInLines(outputEntry.args[0]);
5765 default: return [];
5766 }
5767}
5768
5769function flattenBlocksInLine(line) {
5770 if (line.length === 0) {
5771 return [[]];
5772 }
5773
5774 if (!lineContainsBlocks(line)) {
5775 return [line];
5776 }
5777
5778 var result = [];
5779
5780 var startIndex = 0;
5781 line.forEach(function (outputEntry, blockIndex) {
5782 var blockLines = flattenBlocksInOutputEntry(outputEntry);
5783 var blockLinesLengths = blockLines.map(function (line) {
5784 return utils.calculateLineSize(line).width;
5785 });
5786
5787 var longestLineLength = Math.max.apply(null, blockLinesLengths);
5788
5789 var padLines = blockIndex < line.length - 1;
5790
5791 blockLines.forEach(function (blockLine, index) {
5792 if (!result[index]) {
5793 result[index] = [createPadding(startIndex)];
5794 }
5795
5796 Array.prototype.push.apply(result[index], blockLine);
5797
5798 var paddingLength = longestLineLength - blockLinesLengths[index];
5799 if (padLines && paddingLength > 0) {
5800 result[index].push(createPadding(paddingLength));
5801 }
5802 });
5803
5804 if (padLines) {
5805 for (var i = blockLines.length; i < result.length; i += 1) {
5806 result[i].push(createPadding(longestLineLength));
5807 }
5808 }
5809
5810 startIndex += longestLineLength;
5811 }, this);
5812 return result;
5813}
5814
5815function flattenBlocksInLines(lines) {
5816 var result = [];
5817 lines.forEach(function (line) {
5818 flattenBlocksInLine(line).forEach(function (line) {
5819 result.push(line);
5820 });
5821 });
5822 return result;
5823}
5824
5825module.exports = flattenBlocksInLines;
5826
5827},{}],24:[function(require,module,exports){
5828var utils = {
5829 extend: function (target) {
5830 for (var i = 1; i < arguments.length; i += 1) {
5831 var source = arguments[i];
5832 Object.keys(source).forEach(function (key) {
5833 target[key] = source[key];
5834 });
5835 }
5836 return target;
5837 },
5838
5839 calculateOutputEntrySize: function (outputEntry) {
5840 switch (outputEntry.style) {
5841 case 'text':
5842 return { width: String(outputEntry.args[0]).length, height: 1 };
5843 case 'block':
5844 return utils.calculateSize(outputEntry.args[0]);
5845 default: return { width: 0, height: 0 };
5846 }
5847 },
5848
5849 calculateLineSize: function (line) {
5850 var size = { height: 1, width: 0 };
5851 line.forEach(function (outputEntry) {
5852 var outputEntrySize = utils.calculateOutputEntrySize(outputEntry);
5853 size.width += outputEntrySize.width;
5854 size.height = Math.max(outputEntrySize.height, size.height);
5855 });
5856 return size;
5857 },
5858
5859 calculateSize: function (lines) {
5860 var size = { height: 0, width: 0 };
5861 lines.forEach(function (line) {
5862 var lineSize = utils.calculateLineSize(line);
5863 size.height += lineSize.height;
5864 size.width = Math.max(size.width, lineSize.width);
5865 });
5866 return size;
5867 },
5868
5869 arrayEquals: function (a, b) {
5870 if (a === b) {
5871 return true;
5872 }
5873
5874 if (!a || a.length !== b.length) {
5875 return false;
5876 }
5877
5878 for (var i = 0; i < a.length; i += 1) {
5879 if (a[i] !== b[i]) {
5880 return false;
5881 }
5882 }
5883
5884 return true;
5885
5886 },
5887
5888 escapeRegExp: function (text){
5889 return text.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1");
5890 }
5891};
5892
5893module.exports = utils;
5894
5895},{}],25:[function(require,module,exports){
5896'use strict';
5897
5898var styles = module.exports = {
5899 modifiers: {
5900 reset: [0, 0],
5901 bold: [1, 22], // 21 isn't widely supported and 22 does the same thing
5902 dim: [2, 22],
5903 italic: [3, 23],
5904 underline: [4, 24],
5905 inverse: [7, 27],
5906 hidden: [8, 28],
5907 strikethrough: [9, 29]
5908 },
5909 colors: {
5910 black: [30, 39],
5911 red: [31, 39],
5912 green: [32, 39],
5913 yellow: [33, 39],
5914 blue: [34, 39],
5915 magenta: [35, 39],
5916 cyan: [36, 39],
5917 white: [37, 39],
5918 gray: [90, 39]
5919 },
5920 bgColors: {
5921 bgBlack: [40, 49],
5922 bgRed: [41, 49],
5923 bgGreen: [42, 49],
5924 bgYellow: [43, 49],
5925 bgBlue: [44, 49],
5926 bgMagenta: [45, 49],
5927 bgCyan: [46, 49],
5928 bgWhite: [47, 49]
5929 }
5930};
5931
5932// fix humans
5933styles.colors.grey = styles.colors.gray;
5934
5935Object.keys(styles).forEach(function (groupName) {
5936 var group = styles[groupName];
5937
5938 Object.keys(group).forEach(function (styleName) {
5939 var style = group[styleName];
5940
5941 styles[styleName] = group[styleName] = {
5942 open: '\u001b[' + style[0] + 'm',
5943 close: '\u001b[' + style[1] + 'm'
5944 };
5945 });
5946
5947 Object.defineProperty(styles, groupName, {
5948 value: group,
5949 enumerable: false
5950 });
5951});
5952
5953},{}],26:[function(require,module,exports){
5954/**
5955 * @author Markus Näsman
5956 * @copyright 2012 (c) Markus Näsman <markus at botten dot org >
5957 * @license Copyright (c) 2012, Markus Näsman
5958 * All rights reserved.
5959 * Redistribution and use in source and binary forms, with or without
5960 * modification, are permitted provided that the following conditions are met:
5961 * * Redistributions of source code must retain the above copyright
5962 * notice, this list of conditions and the following disclaimer.
5963 * * Redistributions in binary form must reproduce the above copyright
5964 * notice, this list of conditions and the following disclaimer in the
5965 * documentation and/or other materials provided with the distribution.
5966 * * Neither the name of the <organization> nor the
5967 * names of its contributors may be used to endorse or promote products
5968 * derived from this software without specific prior written permission.
5969 *
5970 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
5971 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
5972 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
5973 * DISCLAIMED. IN NO EVENT SHALL MARKUS NÄSMAN BE LIABLE FOR ANY
5974 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
5975 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
5976 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
5977 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5978 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
5979 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5980 */
5981
5982/**
5983* EXPORTS
5984*/
5985exports.rgb_to_lab = rgb_to_lab;
5986
5987/**
5988* IMPORTS
5989*/
5990var pow = Math.pow;
5991var sqrt = Math.sqrt;
5992
5993/**
5994 * API FUNCTIONS
5995 */
5996
5997/**
5998* Returns c converted to labcolor.
5999* @param {rgbcolor} c should have fields R,G,B
6000* @return {labcolor} c converted to labcolor
6001*/
6002function rgb_to_lab(c)
6003{
6004 return xyz_to_lab(rgb_to_xyz(c))
6005}
6006
6007/**
6008* Returns c converted to xyzcolor.
6009* @param {rgbcolor} c should have fields R,G,B
6010* @return {xyzcolor} c converted to xyzcolor
6011*/
6012function rgb_to_xyz(c)
6013{
6014 // Based on http://www.easyrgb.com/index.php?X=MATH&H=02
6015 var R = ( c.R / 255 );
6016 var G = ( c.G / 255 );
6017 var B = ( c.B / 255 );
6018
6019 if ( R > 0.04045 ) R = pow(( ( R + 0.055 ) / 1.055 ),2.4);
6020 else R = R / 12.92;
6021 if ( G > 0.04045 ) G = pow(( ( G + 0.055 ) / 1.055 ),2.4);
6022 else G = G / 12.92;
6023 if ( B > 0.04045 ) B = pow(( ( B + 0.055 ) / 1.055 ), 2.4);
6024 else B = B / 12.92;
6025
6026 R *= 100;
6027 G *= 100;
6028 B *= 100;
6029
6030 // Observer. = 2°, Illuminant = D65
6031 var X = R * 0.4124 + G * 0.3576 + B * 0.1805;
6032 var Y = R * 0.2126 + G * 0.7152 + B * 0.0722;
6033 var Z = R * 0.0193 + G * 0.1192 + B * 0.9505;
6034 return {'X' : X, 'Y' : Y, 'Z' : Z};
6035}
6036
6037/**
6038* Returns c converted to labcolor.
6039* @param {xyzcolor} c should have fields X,Y,Z
6040* @return {labcolor} c converted to labcolor
6041*/
6042function xyz_to_lab(c)
6043{
6044 // Based on http://www.easyrgb.com/index.php?X=MATH&H=07
6045 var ref_Y = 100.000;
6046 var ref_Z = 108.883;
6047 var ref_X = 95.047; // Observer= 2°, Illuminant= D65
6048 var Y = c.Y / ref_Y;
6049 var Z = c.Z / ref_Z;
6050 var X = c.X / ref_X;
6051 if ( X > 0.008856 ) X = pow(X, 1/3);
6052 else X = ( 7.787 * X ) + ( 16 / 116 );
6053 if ( Y > 0.008856 ) Y = pow(Y, 1/3);
6054 else Y = ( 7.787 * Y ) + ( 16 / 116 );
6055 if ( Z > 0.008856 ) Z = pow(Z, 1/3);
6056 else Z = ( 7.787 * Z ) + ( 16 / 116 );
6057 var L = ( 116 * Y ) - 16;
6058 var a = 500 * ( X - Y );
6059 var b = 200 * ( Y - Z );
6060 return {'L' : L , 'a' : a, 'b' : b};
6061}
6062
6063// Local Variables:
6064// allout-layout: t
6065// js-indent-level: 2
6066// End:
6067
6068},{}],27:[function(require,module,exports){
6069/**
6070 * @author Markus Näsman
6071 * @copyright 2012 (c) Markus Näsman <markus at botten dot org >
6072 * @license Copyright (c) 2012, Markus Näsman
6073 * All rights reserved.
6074 * Redistribution and use in source and binary forms, with or without
6075 * modification, are permitted provided that the following conditions are met:
6076 * * Redistributions of source code must retain the above copyright
6077 * notice, this list of conditions and the following disclaimer.
6078 * * Redistributions in binary form must reproduce the above copyright
6079 * notice, this list of conditions and the following disclaimer in the
6080 * documentation and/or other materials provided with the distribution.
6081 * * Neither the name of the <organization> nor the
6082 * names of its contributors may be used to endorse or promote products
6083 * derived from this software without specific prior written permission.
6084 *
6085 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
6086 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
6087 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
6088 * DISCLAIMED. IN NO EVENT SHALL MARKUS NÄSMAN BE LIABLE FOR ANY
6089 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
6090 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
6091 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6092 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6093 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
6094 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6095 */
6096
6097/**
6098* EXPORTS
6099*/
6100exports.ciede2000 = ciede2000;
6101
6102/**
6103* IMPORTS
6104*/
6105var sqrt = Math.sqrt;
6106var pow = Math.pow;
6107var cos = Math.cos;
6108var atan2 = Math.atan2;
6109var sin = Math.sin;
6110var abs = Math.abs;
6111var exp = Math.exp;
6112var PI = Math.PI;
6113
6114/**
6115 * API FUNCTIONS
6116 */
6117
6118/**
6119* Returns diff between c1 and c2 using the CIEDE2000 algorithm
6120* @param {labcolor} c1 Should have fields L,a,b
6121* @param {labcolor} c2 Should have fields L,a,b
6122* @return {float} Difference between c1 and c2
6123*/
6124function ciede2000(c1,c2)
6125{
6126 /**
6127 * Implemented as in "The CIEDE2000 Color-Difference Formula:
6128 * Implementation Notes, Supplementary Test Data, and Mathematical Observations"
6129 * by Gaurav Sharma, Wencheng Wu and Edul N. Dalal.
6130 */
6131
6132 // Get L,a,b values for color 1
6133 var L1 = c1.L;
6134 var a1 = c1.a;
6135 var b1 = c1.b;
6136
6137 // Get L,a,b values for color 2
6138 var L2 = c2.L;
6139 var a2 = c2.a;
6140 var b2 = c2.b;
6141
6142 // Weight factors
6143 var kL = 1;
6144 var kC = 1;
6145 var kH = 1;
6146
6147 /**
6148 * Step 1: Calculate C1p, C2p, h1p, h2p
6149 */
6150 var C1 = sqrt(pow(a1, 2) + pow(b1, 2)) //(2)
6151 var C2 = sqrt(pow(a2, 2) + pow(b2, 2)) //(2)
6152
6153 var a_C1_C2 = (C1+C2)/2.0; //(3)
6154
6155 var G = 0.5 * (1 - sqrt(pow(a_C1_C2 , 7.0) /
6156 (pow(a_C1_C2, 7.0) + pow(25.0, 7.0)))); //(4)
6157
6158 var a1p = (1.0 + G) * a1; //(5)
6159 var a2p = (1.0 + G) * a2; //(5)
6160
6161 var C1p = sqrt(pow(a1p, 2) + pow(b1, 2)); //(6)
6162 var C2p = sqrt(pow(a2p, 2) + pow(b2, 2)); //(6)
6163
6164 var hp_f = function(x,y) //(7)
6165 {
6166 if(x== 0 && y == 0) return 0;
6167 else{
6168 var tmphp = degrees(atan2(x,y));
6169 if(tmphp >= 0) return tmphp
6170 else return tmphp + 360;
6171 }
6172 }
6173
6174 var h1p = hp_f(b1, a1p); //(7)
6175 var h2p = hp_f(b2, a2p); //(7)
6176
6177 /**
6178 * Step 2: Calculate dLp, dCp, dHp
6179 */
6180 var dLp = L2 - L1; //(8)
6181 var dCp = C2p - C1p; //(9)
6182
6183 var dhp_f = function(C1, C2, h1p, h2p) //(10)
6184 {
6185 if(C1*C2 == 0) return 0;
6186 else if(abs(h2p-h1p) <= 180) return h2p-h1p;
6187 else if((h2p-h1p) > 180) return (h2p-h1p)-360;
6188 else if((h2p-h1p) < -180) return (h2p-h1p)+360;
6189 else throw(new Error());
6190 }
6191 var dhp = dhp_f(C1,C2, h1p, h2p); //(10)
6192 var dHp = 2*sqrt(C1p*C2p)*sin(radians(dhp)/2.0); //(11)
6193
6194 /**
6195 * Step 3: Calculate CIEDE2000 Color-Difference
6196 */
6197 var a_L = (L1 + L2) / 2.0; //(12)
6198 var a_Cp = (C1p + C2p) / 2.0; //(13)
6199
6200 var a_hp_f = function(C1, C2, h1p, h2p) { //(14)
6201 if(C1*C2 == 0) return h1p+h2p
6202 else if(abs(h1p-h2p)<= 180) return (h1p+h2p)/2.0;
6203 else if((abs(h1p-h2p) > 180) && ((h1p+h2p) < 360)) return (h1p+h2p+360)/2.0;
6204 else if((abs(h1p-h2p) > 180) && ((h1p+h2p) >= 360)) return (h1p+h2p-360)/2.0;
6205 else throw(new Error());
6206 }
6207 var a_hp = a_hp_f(C1,C2,h1p,h2p); //(14)
6208 var T = 1-0.17*cos(radians(a_hp-30))+0.24*cos(radians(2*a_hp))+
6209 0.32*cos(radians(3*a_hp+6))-0.20*cos(radians(4*a_hp-63)); //(15)
6210 var d_ro = 30 * exp(-(pow((a_hp-275)/25,2))); //(16)
6211 var RC = sqrt((pow(a_Cp, 7.0)) / (pow(a_Cp, 7.0) + pow(25.0, 7.0)));//(17)
6212 var SL = 1 + ((0.015 * pow(a_L - 50, 2)) /
6213 sqrt(20 + pow(a_L - 50, 2.0)));//(18)
6214 var SC = 1 + 0.045 * a_Cp;//(19)
6215 var SH = 1 + 0.015 * a_Cp * T;//(20)
6216 var RT = -2 * RC * sin(radians(2 * d_ro));//(21)
6217 var dE = sqrt(pow(dLp /(SL * kL), 2) + pow(dCp /(SC * kC), 2) +
6218 pow(dHp /(SH * kH), 2) + RT * (dCp /(SC * kC)) *
6219 (dHp / (SH * kH))); //(22)
6220 return dE;
6221}
6222
6223/**
6224 * INTERNAL FUNCTIONS
6225 */
6226function degrees(n) { return n*(180/PI); }
6227function radians(n) { return n*(PI/180); }
6228
6229// Local Variables:
6230// allout-layout: t
6231// js-indent-level: 2
6232// End:
6233
6234},{}],28:[function(require,module,exports){
6235'use strict';
6236
6237var diff = require(27);
6238var convert = require(26);
6239var palette = require(29);
6240
6241var color = module.exports = {};
6242
6243color.diff = diff.ciede2000;
6244color.rgb_to_lab = convert.rgb_to_lab;
6245color.map_palette = palette.map_palette;
6246color.palette_map_key = palette.palette_map_key;
6247
6248color.closest = function(target, relative) {
6249 var key = color.palette_map_key(target);
6250
6251 var result = color.map_palette([target], relative, 'closest');
6252
6253 return result[key];
6254};
6255
6256color.furthest = function(target, relative) {
6257 var key = color.palette_map_key(target);
6258
6259 var result = color.map_palette([target], relative, 'furthest');
6260
6261 return result[key];
6262};
6263
6264},{}],29:[function(require,module,exports){
6265/**
6266 * @author Markus Näsman
6267 * @copyright 2012 (c) Markus Näsman <markus at botten dot org >
6268 * @license Copyright (c) 2012, Markus Näsman
6269 * All rights reserved.
6270 * Redistribution and use in source and binary forms, with or without
6271 * modification, are permitted provided that the following conditions are met:
6272 * * Redistributions of source code must retain the above copyright
6273 * notice, this list of conditions and the following disclaimer.
6274 * * Redistributions in binary form must reproduce the above copyright
6275 * notice, this list of conditions and the following disclaimer in the
6276 * documentation and/or other materials provided with the distribution.
6277 * * Neither the name of the <organization> nor the
6278 * names of its contributors may be used to endorse or promote products
6279 * derived from this software without specific prior written permission.
6280 *
6281 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
6282 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
6283 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
6284 * DISCLAIMED. IN NO EVENT SHALL MARKUS NÄSMAN BE LIABLE FOR ANY
6285 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
6286 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
6287 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
6288 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6289 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
6290 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6291 */
6292
6293/**
6294* EXPORTS
6295*/
6296exports.map_palette = map_palette;
6297exports.palette_map_key = palette_map_key;
6298
6299/**
6300* IMPORTS
6301*/
6302var color_diff = require(27);
6303var color_convert = require(26);
6304
6305/**
6306 * API FUNCTIONS
6307 */
6308
6309/**
6310* Returns the hash key used for a {rgbcolor} in a {palettemap}
6311* @param {rgbcolor} c should have fields R,G,B
6312* @return {string}
6313*/
6314function palette_map_key(c)
6315{
6316 return "R" + c.R + "B" + c.B + "G" + c.G;
6317}
6318
6319/**
6320* Returns a mapping from each color in a to the closest color in b
6321* @param [{rgbcolor}] a each element should have fields R,G,B
6322* @param [{rgbcolor}] b each element should have fields R,G,B
6323* @param 'type' should have field closest or furthest
6324* @return {palettemap}
6325*/
6326function map_palette(a, b, type)
6327{
6328 var c = {};
6329 type = type || 'closest';
6330 for (var idx1 in a){
6331 var color1 = a[idx1];
6332 var best_color = undefined;
6333 var best_color_diff = undefined;
6334 for (var idx2 in b)
6335 {
6336 var color2 = b[idx2];
6337 var current_color_diff = diff(color1,color2);
6338
6339 if((best_color == undefined) || ((type === 'closest') && (current_color_diff < best_color_diff)))
6340 {
6341 best_color = color2;
6342 best_color_diff = current_color_diff;
6343 continue;
6344 }
6345 if((type === 'furthest') && (current_color_diff > best_color_diff))
6346 {
6347 best_color = color2;
6348 best_color_diff = current_color_diff;
6349 continue;
6350 }
6351 }
6352 c[palette_map_key(color1)] = best_color;
6353 }
6354 return c;
6355}
6356
6357/**
6358 * INTERNAL FUNCTIONS
6359 */
6360
6361function diff(c1,c2)
6362{
6363 c1 = color_convert.rgb_to_lab(c1);
6364 c2 = color_convert.rgb_to_lab(c2);
6365 return color_diff.ciede2000(c1,c2);
6366}
6367
6368// Local Variables:
6369// allout-layout: t
6370// js-indent-level: 2
6371// End:
6372
6373},{}],30:[function(require,module,exports){
6374(function (process){
6375'use strict';
6376var argv = process.argv;
6377
6378module.exports = (function () {
6379 if (argv.indexOf('--no-color') !== -1 ||
6380 argv.indexOf('--no-colors') !== -1 ||
6381 argv.indexOf('--color=false') !== -1) {
6382 return false;
6383 }
6384
6385 if (argv.indexOf('--color') !== -1 ||
6386 argv.indexOf('--colors') !== -1 ||
6387 argv.indexOf('--color=true') !== -1 ||
6388 argv.indexOf('--color=always') !== -1) {
6389 return true;
6390 }
6391
6392 if (process.stdout && !process.stdout.isTTY) {
6393 return false;
6394 }
6395
6396 if (process.platform === 'win32') {
6397 return true;
6398 }
6399
6400 if ('COLORTERM' in process.env) {
6401 return true;
6402 }
6403
6404 if (process.env.TERM === 'dumb') {
6405 return false;
6406 }
6407
6408 if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(process.env.TERM)) {
6409 return true;
6410 }
6411
6412 return false;
6413})();
6414
6415}).call(this,require(13))
6416},{}]},{},[7])(7)
6417});
\No newline at end of file