spec_views 1.1.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +111 -5
  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 +35 -87
  8. data/app/models/spec_views/base_matcher.rb +66 -0
  9. data/app/models/spec_views/capybara_session_extractor.rb +30 -0
  10. data/app/models/spec_views/directory.rb +149 -0
  11. data/app/models/spec_views/html_matcher.rb +41 -0
  12. data/app/models/spec_views/http_response_extractor.rb +30 -0
  13. data/app/models/spec_views/mail_message_extractor.rb +31 -0
  14. data/app/models/spec_views/pdf_matcher.rb +53 -0
  15. data/app/models/spec_views/view_sanitizer.rb +20 -0
  16. data/app/views/layouts/spec_views.html.erb +261 -0
  17. data/app/views/spec_views/views/_actions.html.erb +11 -0
  18. data/app/views/spec_views/views/_directory_footer.html.erb +14 -0
  19. data/app/views/spec_views/views/compare.html.erb +11 -0
  20. data/app/views/spec_views/views/diff.html.erb +16 -0
  21. data/app/views/spec_views/views/index.html.erb +48 -0
  22. data/app/views/spec_views/views/preview.html.erb +32 -0
  23. data/config/routes.rb +3 -0
  24. data/lib/spec_views/configuration.rb +3 -2
  25. data/lib/spec_views/engine.rb +10 -0
  26. data/lib/spec_views/support.rb +61 -174
  27. data/lib/spec_views/version.rb +3 -1
  28. data/lib/spec_views.rb +3 -1
  29. data/lib/tasks/spec_views_tasks.rake +1 -0
  30. metadata +28 -15
  31. data/app/views/layouts/spec_views.html.haml +0 -200
  32. data/app/views/spec_views/views/compare.html.haml +0 -16
  33. data/app/views/spec_views/views/index.html.haml +0 -29
  34. 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
+ ;