mocha 1.18.1 → 1.20.1
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.
- package/LICENSE +22 -0
- package/bin/_mocha +7 -0
- package/lib/interfaces/bdd.js +2 -0
- package/lib/interfaces/exports.js +4 -2
- package/lib/interfaces/qunit.js +2 -0
- package/lib/interfaces/tdd.js +2 -0
- package/lib/reporters/html.js +2 -3
- package/lib/reporters/json.js +9 -8
- package/lib/runner.js +0 -1
- package/lib/suite.js +4 -2
- package/lib/utils.js +1 -1
- package/mocha.js +6 -5
- package/package.json +12 -4
- package/lib/browser/diff.js +0 -354
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
(The MIT License)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2011-2014 TJ Holowaychuk <tj@vision-media.ca>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
'Software'), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
21
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
22
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/bin/_mocha
CHANGED
|
@@ -79,6 +79,13 @@ program
|
|
|
79
79
|
.option('--recursive', 'include sub directories')
|
|
80
80
|
.option('--debug-brk', "enable node's debugger breaking on the first line")
|
|
81
81
|
.option('--globals <names>', 'allow the given comma-delimited global [names]', list, [])
|
|
82
|
+
.option('--harmony', 'enable all harmony features (except typeof)')
|
|
83
|
+
.option('--harmony-proxies', 'enable harmony proxies')
|
|
84
|
+
.option('--harmony-collections', 'enable harmony collections (sets, maps, and weak maps)')
|
|
85
|
+
.option('--harmony-generators', 'enable harmony generators')
|
|
86
|
+
.option('--prof', 'log statistical profiling information')
|
|
87
|
+
.option('-gc', '--expose-gc', 'expose gc extension')
|
|
88
|
+
.option('--trace', 'trace function calls')
|
|
82
89
|
.option('--check-leaks', 'check for global variable leaks')
|
|
83
90
|
.option('--interfaces', 'display available interfaces')
|
|
84
91
|
.option('--reporters', 'display available reporters')
|
package/lib/interfaces/bdd.js
CHANGED
|
@@ -69,6 +69,7 @@ module.exports = function(suite){
|
|
|
69
69
|
|
|
70
70
|
context.describe = context.context = function(title, fn){
|
|
71
71
|
var suite = Suite.create(suites[0], title);
|
|
72
|
+
suite.file = file;
|
|
72
73
|
suites.unshift(suite);
|
|
73
74
|
fn.call(suite);
|
|
74
75
|
suites.shift();
|
|
@@ -109,6 +110,7 @@ module.exports = function(suite){
|
|
|
109
110
|
var suite = suites[0];
|
|
110
111
|
if (suite.pending) var fn = null;
|
|
111
112
|
var test = new Test(title, fn);
|
|
113
|
+
test.file = file;
|
|
112
114
|
suite.addTest(test);
|
|
113
115
|
return test;
|
|
114
116
|
};
|
|
@@ -28,7 +28,7 @@ module.exports = function(suite){
|
|
|
28
28
|
|
|
29
29
|
suite.on('require', visit);
|
|
30
30
|
|
|
31
|
-
function visit(obj) {
|
|
31
|
+
function visit(obj, file) {
|
|
32
32
|
var suite;
|
|
33
33
|
for (var key in obj) {
|
|
34
34
|
if ('function' == typeof obj[key]) {
|
|
@@ -47,7 +47,9 @@ module.exports = function(suite){
|
|
|
47
47
|
suites[0].afterEach(fn);
|
|
48
48
|
break;
|
|
49
49
|
default:
|
|
50
|
-
|
|
50
|
+
var test = new Test(key, fn);
|
|
51
|
+
test.file = file;
|
|
52
|
+
suites[0].addTest(test);
|
|
51
53
|
}
|
|
52
54
|
} else {
|
|
53
55
|
var suite = Suite.create(suites[0], key);
|
package/lib/interfaces/qunit.js
CHANGED
|
@@ -76,6 +76,7 @@ module.exports = function(suite){
|
|
|
76
76
|
context.suite = function(title){
|
|
77
77
|
if (suites.length > 1) suites.shift();
|
|
78
78
|
var suite = Suite.create(suites[0], title);
|
|
79
|
+
suite.file = file;
|
|
79
80
|
suites.unshift(suite);
|
|
80
81
|
return suite;
|
|
81
82
|
};
|
|
@@ -97,6 +98,7 @@ module.exports = function(suite){
|
|
|
97
98
|
|
|
98
99
|
context.test = function(title, fn){
|
|
99
100
|
var test = new Test(title, fn);
|
|
101
|
+
test.file = file;
|
|
100
102
|
suites[0].addTest(test);
|
|
101
103
|
return test;
|
|
102
104
|
};
|
package/lib/interfaces/tdd.js
CHANGED
|
@@ -77,6 +77,7 @@ module.exports = function(suite){
|
|
|
77
77
|
|
|
78
78
|
context.suite = function(title, fn){
|
|
79
79
|
var suite = Suite.create(suites[0], title);
|
|
80
|
+
suite.file = file;
|
|
80
81
|
suites.unshift(suite);
|
|
81
82
|
fn.call(suite);
|
|
82
83
|
suites.shift();
|
|
@@ -113,6 +114,7 @@ module.exports = function(suite){
|
|
|
113
114
|
var suite = suites[0];
|
|
114
115
|
if (suite.pending) var fn = null;
|
|
115
116
|
var test = new Test(title, fn);
|
|
117
|
+
test.file = file;
|
|
116
118
|
suite.addTest(test);
|
|
117
119
|
return test;
|
|
118
120
|
};
|
package/lib/reporters/html.js
CHANGED
|
@@ -42,7 +42,7 @@ var statsTemplate = '<ul id="mocha-stats">'
|
|
|
42
42
|
* @api public
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
|
-
function HTML(runner
|
|
45
|
+
function HTML(runner) {
|
|
46
46
|
Base.call(this, runner);
|
|
47
47
|
|
|
48
48
|
var self = this
|
|
@@ -60,8 +60,7 @@ function HTML(runner, root) {
|
|
|
60
60
|
, stack = [report]
|
|
61
61
|
, progress
|
|
62
62
|
, ctx
|
|
63
|
-
|
|
64
|
-
root = root || document.getElementById('mocha');
|
|
63
|
+
, root = document.getElementById('mocha');
|
|
65
64
|
|
|
66
65
|
if (canvas.getContext) {
|
|
67
66
|
var ratio = window.devicePixelRatio || 1;
|
package/lib/reporters/json.js
CHANGED
|
@@ -42,10 +42,10 @@ function JSONReporter(runner) {
|
|
|
42
42
|
|
|
43
43
|
runner.on('end', function(){
|
|
44
44
|
var obj = {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
stats: self.stats,
|
|
46
|
+
tests: tests.map(clean),
|
|
47
|
+
failures: failures.map(clean),
|
|
48
|
+
passes: passes.map(clean)
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
process.stdout.write(JSON.stringify(obj, null, 2));
|
|
@@ -63,8 +63,9 @@ function JSONReporter(runner) {
|
|
|
63
63
|
|
|
64
64
|
function clean(test) {
|
|
65
65
|
return {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
title: test.title,
|
|
67
|
+
fullTitle: test.fullTitle(),
|
|
68
|
+
duration: test.duration,
|
|
69
|
+
err: test.err
|
|
69
70
|
}
|
|
70
|
-
}
|
|
71
|
+
}
|
package/lib/runner.js
CHANGED
package/lib/suite.js
CHANGED
|
@@ -46,9 +46,11 @@ exports.create = function(parent, title){
|
|
|
46
46
|
* @api private
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
|
-
function Suite(title,
|
|
49
|
+
function Suite(title, parentContext) {
|
|
50
50
|
this.title = title;
|
|
51
|
-
|
|
51
|
+
var context = function() {};
|
|
52
|
+
context.prototype = parentContext;
|
|
53
|
+
this.ctx = new context();
|
|
52
54
|
this.suites = [];
|
|
53
55
|
this.tests = [];
|
|
54
56
|
this.pending = false;
|
package/lib/utils.js
CHANGED
|
@@ -280,7 +280,7 @@ function highlight(js) {
|
|
|
280
280
|
.replace(/('.*?')/gm, '<span class="string">$1</span>')
|
|
281
281
|
.replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
|
|
282
282
|
.replace(/(\d+)/gm, '<span class="number">$1</span>')
|
|
283
|
-
.replace(/\bnew
|
|
283
|
+
.replace(/\bnew[ \t]+(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
|
|
284
284
|
.replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
|
|
285
285
|
}
|
|
286
286
|
|
package/mocha.js
CHANGED
|
@@ -2587,7 +2587,7 @@ var statsTemplate = '<ul id="mocha-stats">'
|
|
|
2587
2587
|
* @api public
|
|
2588
2588
|
*/
|
|
2589
2589
|
|
|
2590
|
-
function HTML(runner
|
|
2590
|
+
function HTML(runner) {
|
|
2591
2591
|
Base.call(this, runner);
|
|
2592
2592
|
|
|
2593
2593
|
var self = this
|
|
@@ -2605,8 +2605,7 @@ function HTML(runner, root) {
|
|
|
2605
2605
|
, stack = [report]
|
|
2606
2606
|
, progress
|
|
2607
2607
|
, ctx
|
|
2608
|
-
|
|
2609
|
-
root = root || document.getElementById('mocha');
|
|
2608
|
+
, root = document.getElementById('mocha');
|
|
2610
2609
|
|
|
2611
2610
|
if (canvas.getContext) {
|
|
2612
2611
|
var ratio = window.devicePixelRatio || 1;
|
|
@@ -5066,9 +5065,11 @@ exports.create = function(parent, title){
|
|
|
5066
5065
|
* @api private
|
|
5067
5066
|
*/
|
|
5068
5067
|
|
|
5069
|
-
function Suite(title,
|
|
5068
|
+
function Suite(title, parentContext) {
|
|
5070
5069
|
this.title = title;
|
|
5071
|
-
|
|
5070
|
+
var context = function () {};
|
|
5071
|
+
context.prototype = parentContext;
|
|
5072
|
+
this.ctx = new context();
|
|
5072
5073
|
this.suites = [];
|
|
5073
5074
|
this.tests = [];
|
|
5074
5075
|
this.pending = false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mocha",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.1",
|
|
4
4
|
"description": "simple, flexible, fun test framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mocha",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"url": "git://github.com/visionmedia/mocha.git"
|
|
16
16
|
},
|
|
17
17
|
"main": "./index",
|
|
18
|
+
"browser": "./mocha.js",
|
|
18
19
|
"bin": {
|
|
19
20
|
"mocha": "./bin/mocha",
|
|
20
21
|
"_mocha": "./bin/_mocha"
|
|
@@ -35,8 +36,8 @@
|
|
|
35
36
|
"glob": "3.2.3"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
|
-
"
|
|
39
|
-
"
|
|
39
|
+
"coffee-script": "1.2",
|
|
40
|
+
"should": "~4.0.0"
|
|
40
41
|
},
|
|
41
42
|
"files": [
|
|
42
43
|
"bin",
|
|
@@ -44,6 +45,13 @@
|
|
|
44
45
|
"lib",
|
|
45
46
|
"index.js",
|
|
46
47
|
"mocha.css",
|
|
47
|
-
"mocha.js"
|
|
48
|
+
"mocha.js",
|
|
49
|
+
"LICENSE"
|
|
50
|
+
],
|
|
51
|
+
"licenses": [
|
|
52
|
+
{
|
|
53
|
+
"type": "MIT",
|
|
54
|
+
"url": "https://raw.github.com/visionmedia/mocha/master/LICENSE"
|
|
55
|
+
}
|
|
48
56
|
]
|
|
49
57
|
}
|
package/lib/browser/diff.js
DELETED
|
@@ -1,354 +0,0 @@
|
|
|
1
|
-
/* See LICENSE file for terms of use */
|
|
2
|
-
|
|
3
|
-
/*
|
|
4
|
-
* Text diff implementation.
|
|
5
|
-
*
|
|
6
|
-
* This library supports the following APIS:
|
|
7
|
-
* JsDiff.diffChars: Character by character diff
|
|
8
|
-
* JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
|
|
9
|
-
* JsDiff.diffLines: Line based diff
|
|
10
|
-
*
|
|
11
|
-
* JsDiff.diffCss: Diff targeted at CSS content
|
|
12
|
-
*
|
|
13
|
-
* These methods are based on the implementation proposed in
|
|
14
|
-
* "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
|
|
15
|
-
* http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
|
|
16
|
-
*/
|
|
17
|
-
var JsDiff = (function() {
|
|
18
|
-
/*jshint maxparams: 5*/
|
|
19
|
-
function clonePath(path) {
|
|
20
|
-
return { newPos: path.newPos, components: path.components.slice(0) };
|
|
21
|
-
}
|
|
22
|
-
function removeEmpty(array) {
|
|
23
|
-
var ret = [];
|
|
24
|
-
for (var i = 0; i < array.length; i++) {
|
|
25
|
-
if (array[i]) {
|
|
26
|
-
ret.push(array[i]);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return ret;
|
|
30
|
-
}
|
|
31
|
-
function escapeHTML(s) {
|
|
32
|
-
var n = s;
|
|
33
|
-
n = n.replace(/&/g, '&');
|
|
34
|
-
n = n.replace(/</g, '<');
|
|
35
|
-
n = n.replace(/>/g, '>');
|
|
36
|
-
n = n.replace(/"/g, '"');
|
|
37
|
-
|
|
38
|
-
return n;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
var Diff = function(ignoreWhitespace) {
|
|
42
|
-
this.ignoreWhitespace = ignoreWhitespace;
|
|
43
|
-
};
|
|
44
|
-
Diff.prototype = {
|
|
45
|
-
diff: function(oldString, newString) {
|
|
46
|
-
// Handle the identity case (this is due to unrolling editLength == 0
|
|
47
|
-
if (newString === oldString) {
|
|
48
|
-
return [{ value: newString }];
|
|
49
|
-
}
|
|
50
|
-
if (!newString) {
|
|
51
|
-
return [{ value: oldString, removed: true }];
|
|
52
|
-
}
|
|
53
|
-
if (!oldString) {
|
|
54
|
-
return [{ value: newString, added: true }];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
newString = this.tokenize(newString);
|
|
58
|
-
oldString = this.tokenize(oldString);
|
|
59
|
-
|
|
60
|
-
var newLen = newString.length, oldLen = oldString.length;
|
|
61
|
-
var maxEditLength = newLen + oldLen;
|
|
62
|
-
var bestPath = [{ newPos: -1, components: [] }];
|
|
63
|
-
|
|
64
|
-
// Seed editLength = 0
|
|
65
|
-
var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
|
|
66
|
-
if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) {
|
|
67
|
-
return bestPath[0].components;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
for (var editLength = 1; editLength <= maxEditLength; editLength++) {
|
|
71
|
-
for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) {
|
|
72
|
-
var basePath;
|
|
73
|
-
var addPath = bestPath[diagonalPath-1],
|
|
74
|
-
removePath = bestPath[diagonalPath+1];
|
|
75
|
-
oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
|
|
76
|
-
if (addPath) {
|
|
77
|
-
// No one else is going to attempt to use this value, clear it
|
|
78
|
-
bestPath[diagonalPath-1] = undefined;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
var canAdd = addPath && addPath.newPos+1 < newLen;
|
|
82
|
-
var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
|
|
83
|
-
if (!canAdd && !canRemove) {
|
|
84
|
-
bestPath[diagonalPath] = undefined;
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Select the diagonal that we want to branch from. We select the prior
|
|
89
|
-
// path whose position in the new string is the farthest from the origin
|
|
90
|
-
// and does not pass the bounds of the diff graph
|
|
91
|
-
if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {
|
|
92
|
-
basePath = clonePath(removePath);
|
|
93
|
-
this.pushComponent(basePath.components, oldString[oldPos], undefined, true);
|
|
94
|
-
} else {
|
|
95
|
-
basePath = clonePath(addPath);
|
|
96
|
-
basePath.newPos++;
|
|
97
|
-
this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath);
|
|
101
|
-
|
|
102
|
-
if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) {
|
|
103
|
-
return basePath.components;
|
|
104
|
-
} else {
|
|
105
|
-
bestPath[diagonalPath] = basePath;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
|
|
111
|
-
pushComponent: function(components, value, added, removed) {
|
|
112
|
-
var last = components[components.length-1];
|
|
113
|
-
if (last && last.added === added && last.removed === removed) {
|
|
114
|
-
// We need to clone here as the component clone operation is just
|
|
115
|
-
// as shallow array clone
|
|
116
|
-
components[components.length-1] =
|
|
117
|
-
{value: this.join(last.value, value), added: added, removed: removed };
|
|
118
|
-
} else {
|
|
119
|
-
components.push({value: value, added: added, removed: removed });
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
extractCommon: function(basePath, newString, oldString, diagonalPath) {
|
|
123
|
-
var newLen = newString.length,
|
|
124
|
-
oldLen = oldString.length,
|
|
125
|
-
newPos = basePath.newPos,
|
|
126
|
-
oldPos = newPos - diagonalPath;
|
|
127
|
-
while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) {
|
|
128
|
-
newPos++;
|
|
129
|
-
oldPos++;
|
|
130
|
-
|
|
131
|
-
this.pushComponent(basePath.components, newString[newPos], undefined, undefined);
|
|
132
|
-
}
|
|
133
|
-
basePath.newPos = newPos;
|
|
134
|
-
return oldPos;
|
|
135
|
-
},
|
|
136
|
-
|
|
137
|
-
equals: function(left, right) {
|
|
138
|
-
var reWhitespace = /\S/;
|
|
139
|
-
if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {
|
|
140
|
-
return true;
|
|
141
|
-
} else {
|
|
142
|
-
return left === right;
|
|
143
|
-
}
|
|
144
|
-
},
|
|
145
|
-
join: function(left, right) {
|
|
146
|
-
return left + right;
|
|
147
|
-
},
|
|
148
|
-
tokenize: function(value) {
|
|
149
|
-
return value;
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
var CharDiff = new Diff();
|
|
154
|
-
|
|
155
|
-
var WordDiff = new Diff(true);
|
|
156
|
-
var WordWithSpaceDiff = new Diff();
|
|
157
|
-
WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) {
|
|
158
|
-
return removeEmpty(value.split(/(\s+|\b)/));
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
var CssDiff = new Diff(true);
|
|
162
|
-
CssDiff.tokenize = function(value) {
|
|
163
|
-
return removeEmpty(value.split(/([{}:;,]|\s+)/));
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
var LineDiff = new Diff();
|
|
167
|
-
LineDiff.tokenize = function(value) {
|
|
168
|
-
return value.split(/^/m);
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
return {
|
|
172
|
-
Diff: Diff,
|
|
173
|
-
|
|
174
|
-
diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); },
|
|
175
|
-
diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); },
|
|
176
|
-
diffWordsWithSpace: function(oldStr, newStr) { return WordWithSpaceDiff.diff(oldStr, newStr); },
|
|
177
|
-
diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); },
|
|
178
|
-
|
|
179
|
-
diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); },
|
|
180
|
-
|
|
181
|
-
createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) {
|
|
182
|
-
var ret = [];
|
|
183
|
-
|
|
184
|
-
ret.push('Index: ' + fileName);
|
|
185
|
-
ret.push('===================================================================');
|
|
186
|
-
ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader));
|
|
187
|
-
ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader));
|
|
188
|
-
|
|
189
|
-
var diff = LineDiff.diff(oldStr, newStr);
|
|
190
|
-
if (!diff[diff.length-1].value) {
|
|
191
|
-
diff.pop(); // Remove trailing newline add
|
|
192
|
-
}
|
|
193
|
-
diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier
|
|
194
|
-
|
|
195
|
-
function contextLines(lines) {
|
|
196
|
-
return lines.map(function(entry) { return ' ' + entry; });
|
|
197
|
-
}
|
|
198
|
-
function eofNL(curRange, i, current) {
|
|
199
|
-
var last = diff[diff.length-2],
|
|
200
|
-
isLast = i === diff.length-2,
|
|
201
|
-
isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed);
|
|
202
|
-
|
|
203
|
-
// Figure out if this is the last line for the given file and missing NL
|
|
204
|
-
if (!/\n$/.test(current.value) && (isLast || isLastOfType)) {
|
|
205
|
-
curRange.push('\');
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
var oldRangeStart = 0, newRangeStart = 0, curRange = [],
|
|
210
|
-
oldLine = 1, newLine = 1;
|
|
211
|
-
for (var i = 0; i < diff.length; i++) {
|
|
212
|
-
var current = diff[i],
|
|
213
|
-
lines = current.lines || current.value.replace(/\n$/, '').split('\n');
|
|
214
|
-
current.lines = lines;
|
|
215
|
-
|
|
216
|
-
if (current.added || current.removed) {
|
|
217
|
-
if (!oldRangeStart) {
|
|
218
|
-
var prev = diff[i-1];
|
|
219
|
-
oldRangeStart = oldLine;
|
|
220
|
-
newRangeStart = newLine;
|
|
221
|
-
|
|
222
|
-
if (prev) {
|
|
223
|
-
curRange = contextLines(prev.lines.slice(-4));
|
|
224
|
-
oldRangeStart -= curRange.length;
|
|
225
|
-
newRangeStart -= curRange.length;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?'+':'-') + entry; }));
|
|
229
|
-
eofNL(curRange, i, current);
|
|
230
|
-
|
|
231
|
-
if (current.added) {
|
|
232
|
-
newLine += lines.length;
|
|
233
|
-
} else {
|
|
234
|
-
oldLine += lines.length;
|
|
235
|
-
}
|
|
236
|
-
} else {
|
|
237
|
-
if (oldRangeStart) {
|
|
238
|
-
// Close out any changes that have been output (or join overlapping)
|
|
239
|
-
if (lines.length <= 8 && i < diff.length-2) {
|
|
240
|
-
// Overlapping
|
|
241
|
-
curRange.push.apply(curRange, contextLines(lines));
|
|
242
|
-
} else {
|
|
243
|
-
// end the range and output
|
|
244
|
-
var contextSize = Math.min(lines.length, 4);
|
|
245
|
-
ret.push(
|
|
246
|
-
'@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize)
|
|
247
|
-
+ ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize)
|
|
248
|
-
+ ' @@');
|
|
249
|
-
ret.push.apply(ret, curRange);
|
|
250
|
-
ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));
|
|
251
|
-
if (lines.length <= 4) {
|
|
252
|
-
eofNL(ret, i, current);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
oldRangeStart = 0; newRangeStart = 0; curRange = [];
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
oldLine += lines.length;
|
|
259
|
-
newLine += lines.length;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
return ret.join('\n') + '\n';
|
|
264
|
-
},
|
|
265
|
-
|
|
266
|
-
applyPatch: function(oldStr, uniDiff) {
|
|
267
|
-
var diffstr = uniDiff.split('\n');
|
|
268
|
-
var diff = [];
|
|
269
|
-
var remEOFNL = false,
|
|
270
|
-
addEOFNL = false;
|
|
271
|
-
|
|
272
|
-
for (var i = (diffstr[0][0]==='I'?4:0); i < diffstr.length; i++) {
|
|
273
|
-
if(diffstr[i][0] === '@') {
|
|
274
|
-
var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
|
|
275
|
-
diff.unshift({
|
|
276
|
-
start:meh[3],
|
|
277
|
-
oldlength:meh[2],
|
|
278
|
-
oldlines:[],
|
|
279
|
-
newlength:meh[4],
|
|
280
|
-
newlines:[]
|
|
281
|
-
});
|
|
282
|
-
} else if(diffstr[i][0] === '+') {
|
|
283
|
-
diff[0].newlines.push(diffstr[i].substr(1));
|
|
284
|
-
} else if(diffstr[i][0] === '-') {
|
|
285
|
-
diff[0].oldlines.push(diffstr[i].substr(1));
|
|
286
|
-
} else if(diffstr[i][0] === ' ') {
|
|
287
|
-
diff[0].newlines.push(diffstr[i].substr(1));
|
|
288
|
-
diff[0].oldlines.push(diffstr[i].substr(1));
|
|
289
|
-
} else if(diffstr[i][0] === '\\') {
|
|
290
|
-
if (diffstr[i-1][0] === '+') {
|
|
291
|
-
remEOFNL = true;
|
|
292
|
-
} else if(diffstr[i-1][0] === '-') {
|
|
293
|
-
addEOFNL = true;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
var str = oldStr.split('\n');
|
|
299
|
-
for (var i = diff.length - 1; i >= 0; i--) {
|
|
300
|
-
var d = diff[i];
|
|
301
|
-
for (var j = 0; j < d.oldlength; j++) {
|
|
302
|
-
if(str[d.start-1+j] !== d.oldlines[j]) {
|
|
303
|
-
return false;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines));
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
if (remEOFNL) {
|
|
310
|
-
while (!str[str.length-1]) {
|
|
311
|
-
str.pop();
|
|
312
|
-
}
|
|
313
|
-
} else if (addEOFNL) {
|
|
314
|
-
str.push('');
|
|
315
|
-
}
|
|
316
|
-
return str.join('\n');
|
|
317
|
-
},
|
|
318
|
-
|
|
319
|
-
convertChangesToXML: function(changes){
|
|
320
|
-
var ret = [];
|
|
321
|
-
for ( var i = 0; i < changes.length; i++) {
|
|
322
|
-
var change = changes[i];
|
|
323
|
-
if (change.added) {
|
|
324
|
-
ret.push('<ins>');
|
|
325
|
-
} else if (change.removed) {
|
|
326
|
-
ret.push('<del>');
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
ret.push(escapeHTML(change.value));
|
|
330
|
-
|
|
331
|
-
if (change.added) {
|
|
332
|
-
ret.push('</ins>');
|
|
333
|
-
} else if (change.removed) {
|
|
334
|
-
ret.push('</del>');
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
return ret.join('');
|
|
338
|
-
},
|
|
339
|
-
|
|
340
|
-
// See: http://code.google.com/p/google-diff-match-patch/wiki/API
|
|
341
|
-
convertChangesToDMP: function(changes){
|
|
342
|
-
var ret = [], change;
|
|
343
|
-
for ( var i = 0; i < changes.length; i++) {
|
|
344
|
-
change = changes[i];
|
|
345
|
-
ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]);
|
|
346
|
-
}
|
|
347
|
-
return ret;
|
|
348
|
-
}
|
|
349
|
-
};
|
|
350
|
-
})();
|
|
351
|
-
|
|
352
|
-
if (typeof module !== 'undefined') {
|
|
353
|
-
module.exports = JsDiff;
|
|
354
|
-
}
|