spec_views 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +101 -16
  3. data/Rakefile +3 -1
  4. data/app/assets/config/spec_views_manifest.js +1 -0
  5. data/app/assets/javascripts/spec_views/diff.js +60 -0
  6. data/app/assets/javascripts/spec_views/jsdiff.js +1055 -0
  7. data/app/controllers/spec_views/views_controller.rb +18 -60
  8. data/app/models/spec_views/base_matcher.rb +64 -0
  9. data/app/models/spec_views/directory.rb +133 -0
  10. data/app/models/spec_views/html_matcher.rb +39 -0
  11. data/app/models/spec_views/http_response_extractor.rb +31 -0
  12. data/app/models/spec_views/mail_message_extractor.rb +30 -0
  13. data/app/models/spec_views/pdf_matcher.rb +49 -0
  14. data/app/views/layouts/spec_views.html.erb +261 -0
  15. data/app/views/spec_views/views/_actions.html.erb +11 -0
  16. data/app/views/spec_views/views/_directory_footer.html.erb +14 -0
  17. data/app/views/spec_views/views/compare.html.erb +11 -0
  18. data/app/views/spec_views/views/diff.html.erb +16 -0
  19. data/app/views/spec_views/views/index.html.erb +48 -0
  20. data/app/views/spec_views/views/preview.html.erb +32 -0
  21. data/config/routes.rb +3 -0
  22. data/lib/spec_views/configuration.rb +3 -2
  23. data/lib/spec_views/engine.rb +10 -0
  24. data/lib/spec_views/support.rb +56 -166
  25. data/lib/spec_views/version.rb +3 -1
  26. data/lib/spec_views.rb +3 -1
  27. data/lib/tasks/spec_views_tasks.rake +1 -0
  28. metadata +26 -15
  29. data/app/views/layouts/spec_views.html.haml +0 -200
  30. data/app/views/spec_views/views/compare.html.haml +0 -16
  31. data/app/views/spec_views/views/index.html.haml +0 -29
  32. data/app/views/spec_views/views/preview.html.haml +0 -19
@@ -0,0 +1,1055 @@
1
+ /*!
2
+
3
+ diff v2.0.1
4
+
5
+ Software License Agreement (BSD License)
6
+
7
+ Copyright (c) 2009-2015, Kevin Decker <kpdecker@gmail.com>
8
+
9
+ All rights reserved.
10
+
11
+ Redistribution and use of this software in source and binary forms, with or without modification,
12
+ are permitted provided that the following conditions are met:
13
+
14
+ * Redistributions of source code must retain the above
15
+ copyright notice, this list of conditions and the
16
+ following disclaimer.
17
+
18
+ * Redistributions in binary form must reproduce the above
19
+ copyright notice, this list of conditions and the
20
+ following disclaimer in the documentation and/or other
21
+ materials provided with the distribution.
22
+
23
+ * Neither the name of Kevin Decker nor the names of its
24
+ contributors may be used to endorse or promote products
25
+ derived from this software without specific prior
26
+ written permission.
27
+
28
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
29
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
30
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
31
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
34
+ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
35
+ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
+ @license
37
+ */
38
+ (function webpackUniversalModuleDefinition(root, factory) {
39
+ if(typeof exports === 'object' && typeof module === 'object')
40
+ module.exports = factory();
41
+ else if(typeof define === 'function' && define.amd)
42
+ define(factory);
43
+ else if(typeof exports === 'object')
44
+ exports["JsDiff"] = factory();
45
+ else
46
+ root["JsDiff"] = factory();
47
+ })(this, function() {
48
+ return /******/ (function(modules) { // webpackBootstrap
49
+ /******/ // The module cache
50
+ /******/ var installedModules = {};
51
+
52
+ /******/ // The require function
53
+ /******/ function __webpack_require__(moduleId) {
54
+
55
+ /******/ // Check if module is in cache
56
+ /******/ if(installedModules[moduleId])
57
+ /******/ return installedModules[moduleId].exports;
58
+
59
+ /******/ // Create a new module (and put it into the cache)
60
+ /******/ var module = installedModules[moduleId] = {
61
+ /******/ exports: {},
62
+ /******/ id: moduleId,
63
+ /******/ loaded: false
64
+ /******/ };
65
+
66
+ /******/ // Execute the module function
67
+ /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
68
+
69
+ /******/ // Flag the module as loaded
70
+ /******/ module.loaded = true;
71
+
72
+ /******/ // Return the exports of the module
73
+ /******/ return module.exports;
74
+ /******/ }
75
+
76
+
77
+ /******/ // expose the modules object (__webpack_modules__)
78
+ /******/ __webpack_require__.m = modules;
79
+
80
+ /******/ // expose the module cache
81
+ /******/ __webpack_require__.c = installedModules;
82
+
83
+ /******/ // __webpack_public_path__
84
+ /******/ __webpack_require__.p = "";
85
+
86
+ /******/ // Load entry module and return exports
87
+ /******/ return __webpack_require__(0);
88
+ /******/ })
89
+ /************************************************************************/
90
+ /******/ ([
91
+ /* 0 */
92
+ /***/ function(module, exports, __webpack_require__) {
93
+
94
+ /* See LICENSE file for terms of use */
95
+
96
+ /*
97
+ * Text diff implementation.
98
+ *
99
+ * This library supports the following APIS:
100
+ * JsDiff.diffChars: Character by character diff
101
+ * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
102
+ * JsDiff.diffLines: Line based diff
103
+ *
104
+ * JsDiff.diffCss: Diff targeted at CSS content
105
+ *
106
+ * These methods are based on the implementation proposed in
107
+ * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
108
+ * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
109
+ */
110
+ 'use strict';
111
+
112
+ exports.__esModule = true;
113
+ // istanbul ignore next
114
+
115
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
116
+
117
+ var _diffBase = __webpack_require__(1);
118
+
119
+ var _diffBase2 = _interopRequireDefault(_diffBase);
120
+
121
+ var _diffCharacter = __webpack_require__(3);
122
+
123
+ var _diffWord = __webpack_require__(4);
124
+
125
+ var _diffLine = __webpack_require__(5);
126
+
127
+ var _diffSentence = __webpack_require__(6);
128
+
129
+ var _diffCss = __webpack_require__(7);
130
+
131
+ var _diffJson = __webpack_require__(8);
132
+
133
+ var _patchApply = __webpack_require__(9);
134
+
135
+ var _patchCreate = __webpack_require__(10);
136
+
137
+ var _convertDmp = __webpack_require__(12);
138
+
139
+ var _convertXml = __webpack_require__(13);
140
+
141
+ exports.Diff = _diffBase2['default'];
142
+ exports.diffChars = _diffCharacter.diffChars;
143
+ exports.diffWords = _diffWord.diffWords;
144
+ exports.diffWordsWithSpace = _diffWord.diffWordsWithSpace;
145
+ exports.diffLines = _diffLine.diffLines;
146
+ exports.diffTrimmedLines = _diffLine.diffTrimmedLines;
147
+ exports.diffSentences = _diffSentence.diffSentences;
148
+ exports.diffCss = _diffCss.diffCss;
149
+ exports.diffJson = _diffJson.diffJson;
150
+ exports.structuredPatch = _patchCreate.structuredPatch;
151
+ exports.createTwoFilesPatch = _patchCreate.createTwoFilesPatch;
152
+ exports.createPatch = _patchCreate.createPatch;
153
+ exports.applyPatch = _patchApply.applyPatch;
154
+ exports.convertChangesToDMP = _convertDmp.convertChangesToDMP;
155
+ exports.convertChangesToXML = _convertXml.convertChangesToXML;
156
+ exports.canonicalize = _diffJson.canonicalize;
157
+
158
+
159
+ /***/ },
160
+ /* 1 */
161
+ /***/ function(module, exports, __webpack_require__) {
162
+
163
+ 'use strict';
164
+
165
+ exports.__esModule = true;
166
+ exports['default'] = Diff;
167
+ // istanbul ignore next
168
+
169
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
170
+
171
+ var _utilMap = __webpack_require__(2);
172
+
173
+ var _utilMap2 = _interopRequireDefault(_utilMap);
174
+
175
+ function Diff(ignoreWhitespace) {
176
+ this.ignoreWhitespace = ignoreWhitespace;
177
+ }
178
+
179
+ Diff.prototype = {
180
+ diff: function diff(oldString, newString, callback) {
181
+ var self = this;
182
+
183
+ function done(value) {
184
+ if (callback) {
185
+ setTimeout(function () {
186
+ callback(undefined, value);
187
+ }, 0);
188
+ return true;
189
+ } else {
190
+ return value;
191
+ }
192
+ }
193
+
194
+ // Allow subclasses to massage the input prior to running
195
+ oldString = this.castInput(oldString);
196
+ newString = this.castInput(newString);
197
+
198
+ // Handle the identity case (this is due to unrolling editLength == 0
199
+ if (newString === oldString) {
200
+ return done([{ value: newString }]);
201
+ }
202
+ if (!newString) {
203
+ return done([{ value: oldString, removed: true }]);
204
+ }
205
+ if (!oldString) {
206
+ return done([{ value: newString, added: true }]);
207
+ }
208
+
209
+ newString = this.removeEmpty(this.tokenize(newString));
210
+ oldString = this.removeEmpty(this.tokenize(oldString));
211
+
212
+ var newLen = newString.length,
213
+ oldLen = oldString.length;
214
+ var editLength = 1;
215
+ var maxEditLength = newLen + oldLen;
216
+ var bestPath = [{ newPos: -1, components: [] }];
217
+
218
+ // Seed editLength = 0, i.e. the content starts with the same values
219
+ var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
220
+ if (bestPath[0].newPos + 1 >= newLen && oldPos + 1 >= oldLen) {
221
+ // Identity per the equality and tokenizer
222
+ return done([{ value: newString.join('') }]);
223
+ }
224
+
225
+ // Main worker method. checks all permutations of a given edit length for acceptance.
226
+ function execEditLength() {
227
+ for (var diagonalPath = -1 * editLength; diagonalPath <= editLength; diagonalPath += 2) {
228
+ var basePath = undefined;
229
+ var addPath = bestPath[diagonalPath - 1],
230
+ removePath = bestPath[diagonalPath + 1],
231
+ _oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
232
+ if (addPath) {
233
+ // No one else is going to attempt to use this value, clear it
234
+ bestPath[diagonalPath - 1] = undefined;
235
+ }
236
+
237
+ var canAdd = addPath && addPath.newPos + 1 < newLen,
238
+ canRemove = removePath && 0 <= _oldPos && _oldPos < oldLen;
239
+ if (!canAdd && !canRemove) {
240
+ // If this path is a terminal then prune
241
+ bestPath[diagonalPath] = undefined;
242
+ continue;
243
+ }
244
+
245
+ // Select the diagonal that we want to branch from. We select the prior
246
+ // path whose position in the new string is the farthest from the origin
247
+ // and does not pass the bounds of the diff graph
248
+ if (!canAdd || canRemove && addPath.newPos < removePath.newPos) {
249
+ basePath = clonePath(removePath);
250
+ self.pushComponent(basePath.components, undefined, true);
251
+ } else {
252
+ basePath = addPath; // No need to clone, we've pulled it from the list
253
+ basePath.newPos++;
254
+ self.pushComponent(basePath.components, true, undefined);
255
+ }
256
+
257
+ _oldPos = self.extractCommon(basePath, newString, oldString, diagonalPath);
258
+
259
+ // If we have hit the end of both strings, then we are done
260
+ if (basePath.newPos + 1 >= newLen && _oldPos + 1 >= oldLen) {
261
+ return done(buildValues(basePath.components, newString, oldString, self.useLongestToken));
262
+ } else {
263
+ // Otherwise track this path as a potential candidate and continue.
264
+ bestPath[diagonalPath] = basePath;
265
+ }
266
+ }
267
+
268
+ editLength++;
269
+ }
270
+
271
+ // Performs the length of edit iteration. Is a bit fugly as this has to support the
272
+ // sync and async mode which is never fun. Loops over execEditLength until a value
273
+ // is produced.
274
+ if (callback) {
275
+ (function exec() {
276
+ setTimeout(function () {
277
+ // This should not happen, but we want to be safe.
278
+ /* istanbul ignore next */
279
+ if (editLength > maxEditLength) {
280
+ return callback();
281
+ }
282
+
283
+ if (!execEditLength()) {
284
+ exec();
285
+ }
286
+ }, 0);
287
+ })();
288
+ } else {
289
+ while (editLength <= maxEditLength) {
290
+ var ret = execEditLength();
291
+ if (ret) {
292
+ return ret;
293
+ }
294
+ }
295
+ }
296
+ },
297
+
298
+ pushComponent: function pushComponent(components, added, removed) {
299
+ var last = components[components.length - 1];
300
+ if (last && last.added === added && last.removed === removed) {
301
+ // We need to clone here as the component clone operation is just
302
+ // as shallow array clone
303
+ components[components.length - 1] = { count: last.count + 1, added: added, removed: removed };
304
+ } else {
305
+ components.push({ count: 1, added: added, removed: removed });
306
+ }
307
+ },
308
+ extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath) {
309
+ var newLen = newString.length,
310
+ oldLen = oldString.length,
311
+ newPos = basePath.newPos,
312
+ oldPos = newPos - diagonalPath,
313
+ commonCount = 0;
314
+ while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) {
315
+ newPos++;
316
+ oldPos++;
317
+ commonCount++;
318
+ }
319
+
320
+ if (commonCount) {
321
+ basePath.components.push({ count: commonCount });
322
+ }
323
+
324
+ basePath.newPos = newPos;
325
+ return oldPos;
326
+ },
327
+
328
+ equals: function equals(left, right) {
329
+ var reWhitespace = /\S/;
330
+ return left === right || this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right);
331
+ },
332
+ removeEmpty: function removeEmpty(array) {
333
+ var ret = [];
334
+ for (var i = 0; i < array.length; i++) {
335
+ if (array[i]) {
336
+ ret.push(array[i]);
337
+ }
338
+ }
339
+ return ret;
340
+ },
341
+ castInput: function castInput(value) {
342
+ return value;
343
+ },
344
+ tokenize: function tokenize(value) {
345
+ return value.split('');
346
+ }
347
+ };
348
+
349
+ function buildValues(components, newString, oldString, useLongestToken) {
350
+ var componentPos = 0,
351
+ componentLen = components.length,
352
+ newPos = 0,
353
+ oldPos = 0;
354
+
355
+ for (; componentPos < componentLen; componentPos++) {
356
+ var component = components[componentPos];
357
+ if (!component.removed) {
358
+ if (!component.added && useLongestToken) {
359
+ var value = newString.slice(newPos, newPos + component.count);
360
+ value = _utilMap2['default'](value, function (value, i) {
361
+ var oldValue = oldString[oldPos + i];
362
+ return oldValue.length > value.length ? oldValue : value;
363
+ });
364
+
365
+ component.value = value.join('');
366
+ } else {
367
+ component.value = newString.slice(newPos, newPos + component.count).join('');
368
+ }
369
+ newPos += component.count;
370
+
371
+ // Common case
372
+ if (!component.added) {
373
+ oldPos += component.count;
374
+ }
375
+ } else {
376
+ component.value = oldString.slice(oldPos, oldPos + component.count).join('');
377
+ oldPos += component.count;
378
+
379
+ // Reverse add and remove so removes are output first to match common convention
380
+ // The diffing algorithm is tied to add then remove output and this is the simplest
381
+ // route to get the desired output with minimal overhead.
382
+ if (componentPos && components[componentPos - 1].added) {
383
+ var tmp = components[componentPos - 1];
384
+ components[componentPos - 1] = components[componentPos];
385
+ components[componentPos] = tmp;
386
+ }
387
+ }
388
+ }
389
+
390
+ return components;
391
+ }
392
+
393
+ function clonePath(path) {
394
+ return { newPos: path.newPos, components: path.components.slice(0) };
395
+ }
396
+ module.exports = exports['default'];
397
+
398
+
399
+ /***/ },
400
+ /* 2 */
401
+ /***/ function(module, exports) {
402
+
403
+ // Following this pattern to make sure the ignore next is in the correct place after babel builds
404
+ "use strict";
405
+
406
+ exports.__esModule = true;
407
+ exports["default"] = map;
408
+
409
+ /* istanbul ignore next */
410
+ function map(arr, mapper, that) {
411
+ if (Array.prototype.map) {
412
+ return Array.prototype.map.call(arr, mapper, that);
413
+ }
414
+
415
+ var other = new Array(arr.length);
416
+
417
+ for (var i = 0, n = arr.length; i < n; i++) {
418
+ other[i] = mapper.call(that, arr[i], i, arr);
419
+ }
420
+ return other;
421
+ }
422
+ module.exports = exports["default"];
423
+
424
+
425
+ /***/ },
426
+ /* 3 */
427
+ /***/ function(module, exports, __webpack_require__) {
428
+
429
+ 'use strict';
430
+
431
+ exports.__esModule = true;
432
+ exports.diffChars = diffChars;
433
+ // istanbul ignore next
434
+
435
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
436
+
437
+ var _base = __webpack_require__(1);
438
+
439
+ var _base2 = _interopRequireDefault(_base);
440
+
441
+ var characterDiff = new _base2['default']();
442
+ exports.characterDiff = characterDiff;
443
+
444
+ function diffChars(oldStr, newStr, callback) {
445
+ return characterDiff.diff(oldStr, newStr, callback);
446
+ }
447
+
448
+
449
+ /***/ },
450
+ /* 4 */
451
+ /***/ function(module, exports, __webpack_require__) {
452
+
453
+ 'use strict';
454
+
455
+ exports.__esModule = true;
456
+ exports.diffWords = diffWords;
457
+ exports.diffWordsWithSpace = diffWordsWithSpace;
458
+ // istanbul ignore next
459
+
460
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
461
+
462
+ var _base = __webpack_require__(1);
463
+
464
+ // Based on https://en.wikipedia.org/wiki/Latin_script_in_Unicode
465
+ //
466
+ // Ranges and exceptions:
467
+ // Latin-1 Supplement, 0080–00FF
468
+ // - U+00D7 × Multiplication sign
469
+ // - U+00F7 ÷ Division sign
470
+ // Latin Extended-A, 0100–017F
471
+ // Latin Extended-B, 0180–024F
472
+ // IPA Extensions, 0250–02AF
473
+ // Spacing Modifier Letters, 02B0–02FF
474
+ // - U+02C7 ˇ &#711; Caron
475
+ // - U+02D8 ˘ &#728; Breve
476
+ // - U+02D9 ˙ &#729; Dot Above
477
+ // - U+02DA ˚ &#730; Ring Above
478
+ // - U+02DB ˛ &#731; Ogonek
479
+ // - U+02DC ˜ &#732; Small Tilde
480
+ // - U+02DD ˝ &#733; Double Acute Accent
481
+ // Latin Extended Additional, 1E00–1EFF
482
+
483
+ var _base2 = _interopRequireDefault(_base);
484
+
485
+ var extendedWordChars = /^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/;
486
+
487
+ var wordDiff = new _base2['default'](true);
488
+ exports.wordDiff = wordDiff;
489
+ var wordWithSpaceDiff = new _base2['default']();
490
+ exports.wordWithSpaceDiff = wordWithSpaceDiff;
491
+ wordDiff.tokenize = wordWithSpaceDiff.tokenize = function (value) {
492
+ var tokens = value.split(/(\s+|\b)/);
493
+
494
+ // Join the boundary splits that we do not consider to be boundaries. This is primarily the extended Latin character set.
495
+ for (var i = 0; i < tokens.length - 1; i++) {
496
+ // If we have an empty string in the next field and we have only word chars before and after, merge
497
+ if (!tokens[i + 1] && tokens[i + 2] && extendedWordChars.test(tokens[i]) && extendedWordChars.test(tokens[i + 2])) {
498
+ tokens[i] += tokens[i + 2];
499
+ tokens.splice(i + 1, 2);
500
+ i--;
501
+ }
502
+ }
503
+
504
+ return tokens;
505
+ };
506
+
507
+ function diffWords(oldStr, newStr, callback) {
508
+ return wordDiff.diff(oldStr, newStr, callback);
509
+ }
510
+
511
+ function diffWordsWithSpace(oldStr, newStr, callback) {
512
+ return wordWithSpaceDiff.diff(oldStr, newStr, callback);
513
+ }
514
+
515
+
516
+ /***/ },
517
+ /* 5 */
518
+ /***/ function(module, exports, __webpack_require__) {
519
+
520
+ 'use strict';
521
+
522
+ exports.__esModule = true;
523
+ exports.diffLines = diffLines;
524
+ exports.diffTrimmedLines = diffTrimmedLines;
525
+ // istanbul ignore next
526
+
527
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
528
+
529
+ var _base = __webpack_require__(1);
530
+
531
+ var _base2 = _interopRequireDefault(_base);
532
+
533
+ var lineDiff = new _base2['default']();
534
+ exports.lineDiff = lineDiff;
535
+ var trimmedLineDiff = new _base2['default']();
536
+ exports.trimmedLineDiff = trimmedLineDiff;
537
+ trimmedLineDiff.ignoreTrim = true;
538
+
539
+ lineDiff.tokenize = trimmedLineDiff.tokenize = function (value) {
540
+ var retLines = [],
541
+ lines = value.split(/^/m);
542
+ for (var i = 0; i < lines.length; i++) {
543
+ var line = lines[i],
544
+ lastLine = lines[i - 1],
545
+ lastLineLastChar = lastLine && lastLine[lastLine.length - 1];
546
+
547
+ // Merge lines that may contain windows new lines
548
+ if (line === '\n' && lastLineLastChar === '\r') {
549
+ retLines[retLines.length - 1] = retLines[retLines.length - 1].slice(0, -1) + '\r\n';
550
+ } else {
551
+ if (this.ignoreTrim) {
552
+ line = line.trim();
553
+ // add a newline unless this is the last line.
554
+ if (i < lines.length - 1) {
555
+ line += '\n';
556
+ }
557
+ }
558
+ retLines.push(line);
559
+ }
560
+ }
561
+
562
+ return retLines;
563
+ };
564
+
565
+ function diffLines(oldStr, newStr, callback) {
566
+ return lineDiff.diff(oldStr, newStr, callback);
567
+ }
568
+
569
+ function diffTrimmedLines(oldStr, newStr, callback) {
570
+ return trimmedLineDiff.diff(oldStr, newStr, callback);
571
+ }
572
+
573
+
574
+ /***/ },
575
+ /* 6 */
576
+ /***/ function(module, exports, __webpack_require__) {
577
+
578
+ 'use strict';
579
+
580
+ exports.__esModule = true;
581
+ exports.diffSentences = diffSentences;
582
+ // istanbul ignore next
583
+
584
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
585
+
586
+ var _base = __webpack_require__(1);
587
+
588
+ var _base2 = _interopRequireDefault(_base);
589
+
590
+ var sentenceDiff = new _base2['default']();
591
+ exports.sentenceDiff = sentenceDiff;
592
+ sentenceDiff.tokenize = function (value) {
593
+ return value.split(/(\S.+?[.!?])(?=\s+|$)/);
594
+ };
595
+
596
+ function diffSentences(oldStr, newStr, callback) {
597
+ return sentenceDiff.diff(oldStr, newStr, callback);
598
+ }
599
+
600
+
601
+ /***/ },
602
+ /* 7 */
603
+ /***/ function(module, exports, __webpack_require__) {
604
+
605
+ 'use strict';
606
+
607
+ exports.__esModule = true;
608
+ exports.diffCss = diffCss;
609
+ // istanbul ignore next
610
+
611
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
612
+
613
+ var _base = __webpack_require__(1);
614
+
615
+ var _base2 = _interopRequireDefault(_base);
616
+
617
+ var cssDiff = new _base2['default']();
618
+ exports.cssDiff = cssDiff;
619
+ cssDiff.tokenize = function (value) {
620
+ return value.split(/([{}:;,]|\s+)/);
621
+ };
622
+
623
+ function diffCss(oldStr, newStr, callback) {
624
+ return cssDiff.diff(oldStr, newStr, callback);
625
+ }
626
+
627
+
628
+ /***/ },
629
+ /* 8 */
630
+ /***/ function(module, exports, __webpack_require__) {
631
+
632
+ 'use strict';
633
+
634
+ exports.__esModule = true;
635
+ exports.diffJson = diffJson;
636
+ exports.canonicalize = canonicalize;
637
+ // istanbul ignore next
638
+
639
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
640
+
641
+ var _base = __webpack_require__(1);
642
+
643
+ var _base2 = _interopRequireDefault(_base);
644
+
645
+ var _line = __webpack_require__(5);
646
+
647
+ var objectPrototypeToString = Object.prototype.toString;
648
+
649
+ var jsonDiff = new _base2['default']();
650
+ // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a
651
+ // dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output:
652
+ exports.jsonDiff = jsonDiff;
653
+ jsonDiff.useLongestToken = true;
654
+
655
+ jsonDiff.tokenize = _line.lineDiff.tokenize;
656
+ jsonDiff.castInput = function (value) {
657
+ return typeof value === 'string' ? value : JSON.stringify(canonicalize(value), undefined, ' ');
658
+ };
659
+ jsonDiff.equals = function (left, right) {
660
+ return _base2['default'].prototype.equals(left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1'));
661
+ };
662
+
663
+ function diffJson(oldObj, newObj, callback) {
664
+ return jsonDiff.diff(oldObj, newObj, callback);
665
+ }
666
+
667
+ // This function handles the presence of circular references by bailing out when encountering an
668
+ // object that is already on the "stack" of items being processed.
669
+
670
+ function canonicalize(obj, stack, replacementStack) {
671
+ stack = stack || [];
672
+ replacementStack = replacementStack || [];
673
+
674
+ var i = undefined;
675
+
676
+ for (i = 0; i < stack.length; i += 1) {
677
+ if (stack[i] === obj) {
678
+ return replacementStack[i];
679
+ }
680
+ }
681
+
682
+ var canonicalizedObj = undefined;
683
+
684
+ if ('[object Array]' === objectPrototypeToString.call(obj)) {
685
+ stack.push(obj);
686
+ canonicalizedObj = new Array(obj.length);
687
+ replacementStack.push(canonicalizedObj);
688
+ for (i = 0; i < obj.length; i += 1) {
689
+ canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack);
690
+ }
691
+ stack.pop();
692
+ replacementStack.pop();
693
+ } else if (typeof obj === 'object' && obj !== null) {
694
+ stack.push(obj);
695
+ canonicalizedObj = {};
696
+ replacementStack.push(canonicalizedObj);
697
+ var sortedKeys = [],
698
+ key = undefined;
699
+ for (key in obj) {
700
+ /* istanbul ignore else */
701
+ if (obj.hasOwnProperty(key)) {
702
+ sortedKeys.push(key);
703
+ }
704
+ }
705
+ sortedKeys.sort();
706
+ for (i = 0; i < sortedKeys.length; i += 1) {
707
+ key = sortedKeys[i];
708
+ canonicalizedObj[key] = canonicalize(obj[key], stack, replacementStack);
709
+ }
710
+ stack.pop();
711
+ replacementStack.pop();
712
+ } else {
713
+ canonicalizedObj = obj;
714
+ }
715
+ return canonicalizedObj;
716
+ }
717
+
718
+
719
+ /***/ },
720
+ /* 9 */
721
+ /***/ function(module, exports) {
722
+
723
+ 'use strict';
724
+
725
+ exports.__esModule = true;
726
+ exports.applyPatch = applyPatch;
727
+
728
+ function applyPatch(oldStr, uniDiff) {
729
+ var diffstr = uniDiff.split('\n'),
730
+ hunks = [],
731
+ i = 0,
732
+ remEOFNL = false,
733
+ addEOFNL = false;
734
+
735
+ // Skip to the first change hunk
736
+ while (i < diffstr.length && !/^@@/.test(diffstr[i])) {
737
+ i++;
738
+ }
739
+
740
+ // Parse the unified diff
741
+ for (; i < diffstr.length; i++) {
742
+ if (diffstr[i][0] === '@') {
743
+ var chnukHeader = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
744
+ hunks.unshift({
745
+ start: chnukHeader[3],
746
+ oldlength: +chnukHeader[2],
747
+ removed: [],
748
+ newlength: chnukHeader[4],
749
+ added: []
750
+ });
751
+ } else if (diffstr[i][0] === '+') {
752
+ hunks[0].added.push(diffstr[i].substr(1));
753
+ } else if (diffstr[i][0] === '-') {
754
+ hunks[0].removed.push(diffstr[i].substr(1));
755
+ } else if (diffstr[i][0] === ' ') {
756
+ hunks[0].added.push(diffstr[i].substr(1));
757
+ hunks[0].removed.push(diffstr[i].substr(1));
758
+ } else if (diffstr[i][0] === '\\') {
759
+ if (diffstr[i - 1][0] === '+') {
760
+ remEOFNL = true;
761
+ } else if (diffstr[i - 1][0] === '-') {
762
+ addEOFNL = true;
763
+ }
764
+ }
765
+ }
766
+
767
+ // Apply the diff to the input
768
+ var lines = oldStr.split('\n');
769
+ for (i = hunks.length - 1; i >= 0; i--) {
770
+ var hunk = hunks[i];
771
+ // Sanity check the input string. Bail if we don't match.
772
+ for (var j = 0; j < hunk.oldlength; j++) {
773
+ if (lines[hunk.start - 1 + j] !== hunk.removed[j]) {
774
+ return false;
775
+ }
776
+ }
777
+ Array.prototype.splice.apply(lines, [hunk.start - 1, hunk.oldlength].concat(hunk.added));
778
+ }
779
+
780
+ // Handle EOFNL insertion/removal
781
+ if (remEOFNL) {
782
+ while (!lines[lines.length - 1]) {
783
+ lines.pop();
784
+ }
785
+ } else if (addEOFNL) {
786
+ lines.push('');
787
+ }
788
+ return lines.join('\n');
789
+ }
790
+
791
+
792
+ /***/ },
793
+ /* 10 */
794
+ /***/ function(module, exports, __webpack_require__) {
795
+
796
+ 'use strict';
797
+
798
+ exports.__esModule = true;
799
+ exports.structuredPatch = structuredPatch;
800
+ exports.createTwoFilesPatch = createTwoFilesPatch;
801
+ exports.createPatch = createPatch;
802
+ // istanbul ignore next
803
+
804
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
805
+
806
+ var _diffPatch = __webpack_require__(11);
807
+
808
+ var _utilMap = __webpack_require__(2);
809
+
810
+ var _utilMap2 = _interopRequireDefault(_utilMap);
811
+
812
+ function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
813
+ if (!options) {
814
+ options = { context: 4 };
815
+ }
816
+
817
+ var diff = _diffPatch.patchDiff.diff(oldStr, newStr);
818
+ diff.push({ value: '', lines: [] }); // Append an empty value to make cleanup easier
819
+
820
+ function contextLines(lines) {
821
+ return _utilMap2['default'](lines, function (entry) {
822
+ return ' ' + entry;
823
+ });
824
+ }
825
+
826
+ var hunks = [];
827
+ var oldRangeStart = 0,
828
+ newRangeStart = 0,
829
+ curRange = [],
830
+ oldLine = 1,
831
+ newLine = 1;
832
+
833
+ var _loop = function (i) {
834
+ var current = diff[i],
835
+ lines = current.lines || current.value.replace(/\n$/, '').split('\n');
836
+ current.lines = lines;
837
+
838
+ if (current.added || current.removed) {
839
+ // If we have previous context, start with that
840
+ if (!oldRangeStart) {
841
+ var prev = diff[i - 1];
842
+ oldRangeStart = oldLine;
843
+ newRangeStart = newLine;
844
+
845
+ if (prev) {
846
+ curRange = options.context > 0 ? contextLines(prev.lines.slice(-options.context)) : [];
847
+ oldRangeStart -= curRange.length;
848
+ newRangeStart -= curRange.length;
849
+ }
850
+ }
851
+
852
+ // Output our changes
853
+ curRange.push.apply(curRange, _utilMap2['default'](lines, function (entry) {
854
+ return (current.added ? '+' : '-') + entry;
855
+ }));
856
+
857
+ // Track the updated file position
858
+ if (current.added) {
859
+ newLine += lines.length;
860
+ } else {
861
+ oldLine += lines.length;
862
+ }
863
+ } else {
864
+ // Identical context lines. Track line changes
865
+ if (oldRangeStart) {
866
+ // Close out any changes that have been output (or join overlapping)
867
+ if (lines.length <= options.context * 2 && i < diff.length - 2) {
868
+ // Overlapping
869
+ curRange.push.apply(curRange, contextLines(lines));
870
+ } else {
871
+ // end the range and output
872
+ var contextSize = Math.min(lines.length, options.context);
873
+ curRange.push.apply(curRange, contextLines(lines.slice(0, contextSize)));
874
+
875
+ var hunk = {
876
+ oldStart: oldRangeStart,
877
+ oldLines: oldLine - oldRangeStart + contextSize,
878
+ newStart: newRangeStart,
879
+ newLines: newLine - newRangeStart + contextSize,
880
+ lines: curRange
881
+ };
882
+ if (i >= diff.length - 2 && lines.length <= options.context) {
883
+ // EOF is inside this hunk
884
+ var oldEOFNewline = /\n$/.test(oldStr);
885
+ var newEOFNewline = /\n$/.test(newStr);
886
+ if (lines.length == 0 && !oldEOFNewline) {
887
+ // special case: old has no eol and no trailing context; no-nl can end up before adds
888
+ curRange.splice(hunk.oldLines, 0, '\');
889
+ } else if (!oldEOFNewline || !newEOFNewline) {
890
+ curRange.push('\');
891
+ }
892
+ }
893
+ hunks.push(hunk);
894
+
895
+ oldRangeStart = 0;
896
+ newRangeStart = 0;
897
+ curRange = [];
898
+ }
899
+ }
900
+ oldLine += lines.length;
901
+ newLine += lines.length;
902
+ }
903
+ };
904
+
905
+ for (var i = 0; i < diff.length; i++) {
906
+ _loop(i);
907
+ }
908
+
909
+ return {
910
+ oldFileName: oldFileName, newFileName: newFileName,
911
+ oldHeader: oldHeader, newHeader: newHeader,
912
+ hunks: hunks
913
+ };
914
+ }
915
+
916
+ function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
917
+ var diff = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options);
918
+
919
+ var ret = [];
920
+ if (oldFileName == newFileName) {
921
+ ret.push('Index: ' + oldFileName);
922
+ }
923
+ ret.push('===================================================================');
924
+ ret.push('--- ' + diff.oldFileName + (typeof diff.oldHeader === 'undefined' ? '' : '\t' + diff.oldHeader));
925
+ ret.push('+++ ' + diff.newFileName + (typeof diff.newHeader === 'undefined' ? '' : '\t' + diff.newHeader));
926
+
927
+ for (var i = 0; i < diff.hunks.length; i++) {
928
+ var hunk = diff.hunks[i];
929
+ ret.push('@@ -' + hunk.oldStart + ',' + hunk.oldLines + ' +' + hunk.newStart + ',' + hunk.newLines + ' @@');
930
+ ret.push.apply(ret, hunk.lines);
931
+ }
932
+
933
+ return ret.join('\n') + '\n';
934
+ }
935
+
936
+ function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options) {
937
+ return createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options);
938
+ }
939
+
940
+
941
+ /***/ },
942
+ /* 11 */
943
+ /***/ function(module, exports, __webpack_require__) {
944
+
945
+ 'use strict';
946
+
947
+ exports.__esModule = true;
948
+ // istanbul ignore next
949
+
950
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
951
+
952
+ var _base = __webpack_require__(1);
953
+
954
+ var _base2 = _interopRequireDefault(_base);
955
+
956
+ var patchDiff = new _base2['default']();
957
+ exports.patchDiff = patchDiff;
958
+ patchDiff.tokenize = function (value) {
959
+ var ret = [],
960
+ linesAndNewlines = value.split(/(\n|\r\n)/);
961
+
962
+ // Ignore the final empty token that occurs if the string ends with a new line
963
+ if (!linesAndNewlines[linesAndNewlines.length - 1]) {
964
+ linesAndNewlines.pop();
965
+ }
966
+
967
+ // Merge the content and line separators into single tokens
968
+ for (var i = 0; i < linesAndNewlines.length; i++) {
969
+ var line = linesAndNewlines[i];
970
+
971
+ if (i % 2) {
972
+ ret[ret.length - 1] += line;
973
+ } else {
974
+ ret.push(line);
975
+ }
976
+ }
977
+ return ret;
978
+ };
979
+
980
+
981
+ /***/ },
982
+ /* 12 */
983
+ /***/ function(module, exports) {
984
+
985
+ // See: http://code.google.com/p/google-diff-match-patch/wiki/API
986
+ "use strict";
987
+
988
+ exports.__esModule = true;
989
+ exports.convertChangesToDMP = convertChangesToDMP;
990
+
991
+ function convertChangesToDMP(changes) {
992
+ var ret = [],
993
+ change = undefined,
994
+ operation = undefined;
995
+ for (var i = 0; i < changes.length; i++) {
996
+ change = changes[i];
997
+ if (change.added) {
998
+ operation = 1;
999
+ } else if (change.removed) {
1000
+ operation = -1;
1001
+ } else {
1002
+ operation = 0;
1003
+ }
1004
+
1005
+ ret.push([operation, change.value]);
1006
+ }
1007
+ return ret;
1008
+ }
1009
+
1010
+
1011
+ /***/ },
1012
+ /* 13 */
1013
+ /***/ function(module, exports) {
1014
+
1015
+ 'use strict';
1016
+
1017
+ exports.__esModule = true;
1018
+ exports.convertChangesToXML = convertChangesToXML;
1019
+
1020
+ function convertChangesToXML(changes) {
1021
+ var ret = [];
1022
+ for (var i = 0; i < changes.length; i++) {
1023
+ var change = changes[i];
1024
+ if (change.added) {
1025
+ ret.push('<ins>');
1026
+ } else if (change.removed) {
1027
+ ret.push('<del>');
1028
+ }
1029
+
1030
+ ret.push(escapeHTML(change.value));
1031
+
1032
+ if (change.added) {
1033
+ ret.push('</ins>');
1034
+ } else if (change.removed) {
1035
+ ret.push('</del>');
1036
+ }
1037
+ }
1038
+ return ret.join('');
1039
+ }
1040
+
1041
+ function escapeHTML(s) {
1042
+ var n = s;
1043
+ n = n.replace(/&/g, '&amp;');
1044
+ n = n.replace(/</g, '&lt;');
1045
+ n = n.replace(/>/g, '&gt;');
1046
+ n = n.replace(/"/g, '&quot;');
1047
+
1048
+ return n;
1049
+ }
1050
+
1051
+
1052
+ /***/ }
1053
+ /******/ ])
1054
+ });
1055
+ ;