mocha 2.0.1 → 2.1.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.
- package/README.md +226 -0
- package/bin/_mocha +21 -7
- package/bin/mocha +7 -0
- package/lib/browser/diff.js +369 -0
- package/lib/mocha.js +20 -8
- package/lib/reporters/base.js +11 -12
- package/lib/reporters/html.js +2 -2
- package/lib/reporters/markdown.js +14 -5
- package/lib/reporters/nyan.js +13 -13
- package/lib/reporters/xunit.js +41 -9
- package/lib/runnable.js +4 -3
- package/lib/runner.js +4 -3
- package/lib/suite.js +2 -2
- package/lib/utils.js +190 -30
- package/mocha.js +317 -88
- package/package.json +2 -3
- package/Readme.md +0 -203
package/README.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
[](http://travis-ci.org/mochajs/mocha)
|
|
2
|
+
|
|
3
|
+
[](http://mochajs.org)
|
|
4
|
+
|
|
5
|
+
Mocha is a simple, flexible, fun JavaScript test framework for node.js and the browser. For more information view the [documentation](http://mochajs.org).
|
|
6
|
+
|
|
7
|
+
## Contributors
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
project : mocha
|
|
11
|
+
repo age : 3 years, 4 months
|
|
12
|
+
active : 509 days
|
|
13
|
+
commits : 1575
|
|
14
|
+
files : 153
|
|
15
|
+
authors :
|
|
16
|
+
977 TJ Holowaychuk 62.0%
|
|
17
|
+
132 Travis Jeffery 8.4%
|
|
18
|
+
63 Christopher Hiller 4.0%
|
|
19
|
+
31 Guillermo Rauch 2.0%
|
|
20
|
+
27 Joshua Appelman 1.7%
|
|
21
|
+
13 Attila Domokos 0.8%
|
|
22
|
+
10 John Firebaugh 0.6%
|
|
23
|
+
8 Nathan Rajlich 0.5%
|
|
24
|
+
8 Jo Liss 0.5%
|
|
25
|
+
6 Mike Pennisi 0.4%
|
|
26
|
+
6 Brendan Nee 0.4%
|
|
27
|
+
6 James Carr 0.4%
|
|
28
|
+
5 Aaron Heckmann 0.3%
|
|
29
|
+
5 Raynos 0.3%
|
|
30
|
+
5 Ryunosuke SATO 0.3%
|
|
31
|
+
4 hokaccha 0.3%
|
|
32
|
+
4 Jonathan Ong 0.3%
|
|
33
|
+
4 Joshua Krall 0.3%
|
|
34
|
+
4 Domenic Denicola 0.3%
|
|
35
|
+
4 Forbes Lindesay 0.3%
|
|
36
|
+
4 Xavier Antoviaque 0.3%
|
|
37
|
+
4 David da Silva 0.3%
|
|
38
|
+
3 Ariel Mashraki 0.2%
|
|
39
|
+
3 Ben Bradley 0.2%
|
|
40
|
+
3 Merrick Christensen 0.2%
|
|
41
|
+
3 Andreas Lind Petersen 0.2%
|
|
42
|
+
3 Nathan Bowser 0.2%
|
|
43
|
+
3 Cory Thomas 0.2%
|
|
44
|
+
3 Benjie Gillam 0.2%
|
|
45
|
+
3 Wil Moore III 0.2%
|
|
46
|
+
3 Ben Lindsey 0.2%
|
|
47
|
+
3 Tyson Tate 0.2%
|
|
48
|
+
3 Paul Miller 0.2%
|
|
49
|
+
3 eiji.ienaga 0.2%
|
|
50
|
+
3 Mathieu Desvé 0.2%
|
|
51
|
+
3 Jesse Dailey 0.2%
|
|
52
|
+
3 fool2fish 0.2%
|
|
53
|
+
3 Fredrik Enestad 0.2%
|
|
54
|
+
3 Sindre Sorhus 0.2%
|
|
55
|
+
3 Valentin Agachi 0.2%
|
|
56
|
+
2 jsdevel 0.1%
|
|
57
|
+
2 Arian Stolwijk 0.1%
|
|
58
|
+
2 Juzer Ali 0.1%
|
|
59
|
+
2 David Henderson 0.1%
|
|
60
|
+
2 Justin DuJardin 0.1%
|
|
61
|
+
2 Paul Armstrong 0.1%
|
|
62
|
+
2 Pete Hawkins 0.1%
|
|
63
|
+
2 Jonas Westerlund 0.1%
|
|
64
|
+
2 Quang Van 0.1%
|
|
65
|
+
2 Simon Gaeremynck 0.1%
|
|
66
|
+
2 travis jeffery 0.1%
|
|
67
|
+
2 Dominique Quatravaux 0.1%
|
|
68
|
+
2 Jacob Wejendorp 0.1%
|
|
69
|
+
2 Shawn Krisman 0.1%
|
|
70
|
+
2 FARKAS Máté 0.1%
|
|
71
|
+
2 Konstantin Käfer 0.1%
|
|
72
|
+
2 Timo Tijhof 0.1%
|
|
73
|
+
2 Sean Lang 0.1%
|
|
74
|
+
2 Quanlong He 0.1%
|
|
75
|
+
2 Glen Mailer 0.1%
|
|
76
|
+
2 Alexander Early 0.1%
|
|
77
|
+
2 Ian Storm Taylor 0.1%
|
|
78
|
+
2 Brian Beck 0.1%
|
|
79
|
+
2 Michael Riley 0.1%
|
|
80
|
+
2 Michael Schoonmaker 0.1%
|
|
81
|
+
2 domenic 0.1%
|
|
82
|
+
2 fcrisci 0.1%
|
|
83
|
+
2 Buck Doyle 0.1%
|
|
84
|
+
2 Nathan Alderson 0.1%
|
|
85
|
+
1 Mal Graty 0.1%
|
|
86
|
+
1 Marc Kuo 0.1%
|
|
87
|
+
1 Matija Marohnić 0.1%
|
|
88
|
+
1 Matt Robenolt 0.1%
|
|
89
|
+
1 Matt Smith 0.1%
|
|
90
|
+
1 Matthew Shanley 0.1%
|
|
91
|
+
1 Mattias Tidlund 0.1%
|
|
92
|
+
1 Michael Jackson 0.1%
|
|
93
|
+
1 Michael Olson 0.1%
|
|
94
|
+
1 Michal Charemza 0.1%
|
|
95
|
+
1 Nathan Black 0.1%
|
|
96
|
+
1 Nick Fitzgerald 0.1%
|
|
97
|
+
1 Noshir Patel 0.1%
|
|
98
|
+
1 Panu Horsmalahti 0.1%
|
|
99
|
+
1 Phil Sung 0.1%
|
|
100
|
+
1 R56 0.1%
|
|
101
|
+
1 Refael Ackermann 0.1%
|
|
102
|
+
1 Richard Dingwall 0.1%
|
|
103
|
+
1 Richard Knop 0.1%
|
|
104
|
+
1 Rob Wu 0.1%
|
|
105
|
+
1 Romain Prieto 0.1%
|
|
106
|
+
1 Roman Neuhauser 0.1%
|
|
107
|
+
1 Roman Shtylman 0.1%
|
|
108
|
+
1 Russ Bradberry 0.1%
|
|
109
|
+
1 Russell Munson 0.1%
|
|
110
|
+
1 Rustem Mustafin 0.1%
|
|
111
|
+
1 Salehen Shovon Rahman 0.1%
|
|
112
|
+
1 Sasha Koss 0.1%
|
|
113
|
+
1 Seiya Konno 0.1%
|
|
114
|
+
1 Shaine Hatch 0.1%
|
|
115
|
+
1 Simon Goumaz 0.1%
|
|
116
|
+
1 Standa Opichal 0.1%
|
|
117
|
+
1 Stephen Mathieson 0.1%
|
|
118
|
+
1 Steve Mason 0.1%
|
|
119
|
+
1 Tapiwa Kelvin 0.1%
|
|
120
|
+
1 Teddy Zeenny 0.1%
|
|
121
|
+
1 Tim Ehat 0.1%
|
|
122
|
+
1 Vadim Nikitin 0.1%
|
|
123
|
+
1 Victor Costan 0.1%
|
|
124
|
+
1 Will Langstroth 0.1%
|
|
125
|
+
1 Yanis Wang 0.1%
|
|
126
|
+
1 Yuest Wang 0.1%
|
|
127
|
+
1 Zsolt Takács 0.1%
|
|
128
|
+
1 abrkn 0.1%
|
|
129
|
+
1 airportyh 0.1%
|
|
130
|
+
1 badunk 0.1%
|
|
131
|
+
1 claudyus 0.1%
|
|
132
|
+
1 dasilvacontin 0.1%
|
|
133
|
+
1 fengmk2 0.1%
|
|
134
|
+
1 gaye 0.1%
|
|
135
|
+
1 grasGendarme 0.1%
|
|
136
|
+
1 lakmeer 0.1%
|
|
137
|
+
1 lodr 0.1%
|
|
138
|
+
1 mrShturman 0.1%
|
|
139
|
+
1 nishigori 0.1%
|
|
140
|
+
1 omardelarosa 0.1%
|
|
141
|
+
1 qiuzuhui 0.1%
|
|
142
|
+
1 samuel goldszmidt 0.1%
|
|
143
|
+
1 sebv 0.1%
|
|
144
|
+
1 startswithaj 0.1%
|
|
145
|
+
1 tgautier@yahoo.com 0.1%
|
|
146
|
+
1 traleig1 0.1%
|
|
147
|
+
1 vlad 0.1%
|
|
148
|
+
1 yuitest 0.1%
|
|
149
|
+
1 zhiyelee 0.1%
|
|
150
|
+
1 Adam Crabtree 0.1%
|
|
151
|
+
1 Andreas Brekken 0.1%
|
|
152
|
+
1 Andrew Nesbitt 0.1%
|
|
153
|
+
1 Andrey Popp 0.1%
|
|
154
|
+
1 Arnaud Brousseau 0.1%
|
|
155
|
+
1 Atsuya Takagi 0.1%
|
|
156
|
+
1 Austin Birch 0.1%
|
|
157
|
+
1 Ben Noordhuis 0.1%
|
|
158
|
+
1 Bjørge Næss 0.1%
|
|
159
|
+
1 Brian Lalor 0.1%
|
|
160
|
+
1 Brian M. Carlson 0.1%
|
|
161
|
+
1 Brian Moore 0.1%
|
|
162
|
+
1 Bryan Donovan 0.1%
|
|
163
|
+
1 C. Scott Ananian 0.1%
|
|
164
|
+
1 Casey Foster 0.1%
|
|
165
|
+
1 ChrisWren 0.1%
|
|
166
|
+
1 Connor Dunn 0.1%
|
|
167
|
+
1 Corey Butler 0.1%
|
|
168
|
+
1 Daniel Stockman 0.1%
|
|
169
|
+
1 Dave McKenna 0.1%
|
|
170
|
+
1 Denis Bardadym 0.1%
|
|
171
|
+
1 Devin Weaver 0.1%
|
|
172
|
+
1 Di Wu 0.1%
|
|
173
|
+
1 Diogo Monteiro 0.1%
|
|
174
|
+
1 Dmitry Shirokov 0.1%
|
|
175
|
+
1 Dr. Travis Jeffery 0.1%
|
|
176
|
+
1 Fedor Indutny 0.1%
|
|
177
|
+
1 Florian Margaine 0.1%
|
|
178
|
+
1 Frederico Silva 0.1%
|
|
179
|
+
1 Fredrik Lindin 0.1%
|
|
180
|
+
1 Gareth Aye 0.1%
|
|
181
|
+
1 Gareth Murphy 0.1%
|
|
182
|
+
1 Gavin Mogan 0.1%
|
|
183
|
+
1 Giovanni Bassi 0.1%
|
|
184
|
+
1 Glen Huang 0.1%
|
|
185
|
+
1 Greg Perkins 0.1%
|
|
186
|
+
1 Harish 0.1%
|
|
187
|
+
1 Harry Brundage 0.1%
|
|
188
|
+
1 Herman Junge 0.1%
|
|
189
|
+
1 Ian Young 0.1%
|
|
190
|
+
1 Ivan 0.1%
|
|
191
|
+
1 JP Bochi 0.1%
|
|
192
|
+
1 Jaakko Salonen 0.1%
|
|
193
|
+
1 Jakub Nešetřil 0.1%
|
|
194
|
+
1 James Bowes 0.1%
|
|
195
|
+
1 James Lal 0.1%
|
|
196
|
+
1 Jan Kopriva 0.1%
|
|
197
|
+
1 Jason Barry 0.1%
|
|
198
|
+
1 Javier Aranda 0.1%
|
|
199
|
+
1 Jean Ponchon 0.1%
|
|
200
|
+
1 Jeff Kunkle 0.1%
|
|
201
|
+
1 Jeremy Martin 0.1%
|
|
202
|
+
1 Jimmy Cuadra 0.1%
|
|
203
|
+
1 John Doty 0.1%
|
|
204
|
+
1 Jonathan Creamer 0.1%
|
|
205
|
+
1 Jonathan Park 0.1%
|
|
206
|
+
1 Jussi Virtanen 0.1%
|
|
207
|
+
1 Katie Gengler 0.1%
|
|
208
|
+
1 Kazuhito Hokamura 0.1%
|
|
209
|
+
1 Kent C. Dodds 0.1%
|
|
210
|
+
1 Kevin Conway 0.1%
|
|
211
|
+
1 Kirill Korolyov 0.1%
|
|
212
|
+
1 Koen Punt 0.1%
|
|
213
|
+
1 Laszlo Bacsi 0.1%
|
|
214
|
+
1 Liam Newman 0.1%
|
|
215
|
+
1 Linus Unnebäck 0.1%
|
|
216
|
+
1 László Bácsi 0.1%
|
|
217
|
+
1 Maciej Małecki 0.1%
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Links
|
|
221
|
+
|
|
222
|
+
- [Google Group](http://groups.google.com/group/mochajs)
|
|
223
|
+
- [Wiki](https://github.com/mochajs/mocha/wiki)
|
|
224
|
+
- Mocha [Extensions and reporters](https://github.com/mochajs/mocha/wiki)
|
|
225
|
+
|
|
226
|
+
Mocha also has a chat room on [Slack](https://slack.com). If you'd like to join, [shoot us an email](mailto:tj@travisjeffery.com?subject=mocha%20slack%20room%20invite) from the address you want us to invite you under and we'll happily send you an invite!
|
package/bin/_mocha
CHANGED
|
@@ -5,17 +5,13 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
var program = require('commander')
|
|
8
|
-
, sprintf = require('util').format
|
|
9
8
|
, path = require('path')
|
|
10
9
|
, fs = require('fs')
|
|
11
|
-
, glob = require('glob')
|
|
12
10
|
, resolve = path.resolve
|
|
13
11
|
, exists = fs.existsSync || path.existsSync
|
|
14
12
|
, Mocha = require('../')
|
|
15
13
|
, utils = Mocha.utils
|
|
16
|
-
, interfaces = Mocha.interfaces
|
|
17
14
|
, join = path.join
|
|
18
|
-
, basename = path.basename
|
|
19
15
|
, cwd = process.cwd()
|
|
20
16
|
, mocha = new Mocha;
|
|
21
17
|
|
|
@@ -65,6 +61,7 @@ program
|
|
|
65
61
|
.option('-c, --colors', 'force enabling of colors')
|
|
66
62
|
.option('-C, --no-colors', 'force disabling of colors')
|
|
67
63
|
.option('-G, --growl', 'enable growl notification support')
|
|
64
|
+
.option('-O, --reporter-options <k=v,k2=v2,...>', 'reporter-specific options')
|
|
68
65
|
.option('-R, --reporter <name>', 'specify the reporter to use', 'spec')
|
|
69
66
|
.option('-S, --sort', "sort test files")
|
|
70
67
|
.option('-b, --bail', "bail after first test failure")
|
|
@@ -179,7 +176,10 @@ var optsPath = process.argv.indexOf('--opts') !== -1
|
|
|
179
176
|
try {
|
|
180
177
|
var opts = fs.readFileSync(optsPath, 'utf8')
|
|
181
178
|
.trim()
|
|
182
|
-
.split(/\s+/)
|
|
179
|
+
.split(/\s+/)
|
|
180
|
+
.filter(function(value) {
|
|
181
|
+
return value ? true : false;
|
|
182
|
+
});
|
|
183
183
|
|
|
184
184
|
process.argv = process.argv
|
|
185
185
|
.slice(0, 2)
|
|
@@ -196,9 +196,22 @@ program.parse(process.argv);
|
|
|
196
196
|
|
|
197
197
|
Error.stackTraceLimit = Infinity; // TODO: config
|
|
198
198
|
|
|
199
|
+
// reporter options
|
|
200
|
+
|
|
201
|
+
var reporterOptions = {};
|
|
202
|
+
if (program.reporterOptions !== undefined) {
|
|
203
|
+
program.reporterOptions.split(",").forEach(function(opt) {
|
|
204
|
+
var L = opt.split("=");
|
|
205
|
+
if (L.length != 2) {
|
|
206
|
+
throw new Error("invalid reporter option '" + opt + "'");
|
|
207
|
+
}
|
|
208
|
+
reporterOptions[L[0]] = L[1];
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
199
212
|
// reporter
|
|
200
213
|
|
|
201
|
-
mocha.reporter(program.reporter);
|
|
214
|
+
mocha.reporter(program.reporter, reporterOptions);
|
|
202
215
|
|
|
203
216
|
// interface
|
|
204
217
|
|
|
@@ -282,6 +295,7 @@ program.compilers.forEach(function(c) {
|
|
|
282
295
|
if (mod[0] == '.') mod = join(process.cwd(), mod);
|
|
283
296
|
require(mod);
|
|
284
297
|
extensions.push(ext);
|
|
298
|
+
program.watchExtensions.push(ext);
|
|
285
299
|
});
|
|
286
300
|
|
|
287
301
|
// requires
|
|
@@ -325,7 +339,7 @@ if (program.watch) {
|
|
|
325
339
|
});
|
|
326
340
|
|
|
327
341
|
|
|
328
|
-
var watchFiles = utils.files(cwd, [ 'js'
|
|
342
|
+
var watchFiles = utils.files(cwd, [ 'js' ].concat(program.watchExtensions));
|
|
329
343
|
var runAgain = false;
|
|
330
344
|
|
|
331
345
|
function loadAndRun() {
|
package/bin/mocha
CHANGED
|
@@ -54,3 +54,10 @@ proc.on('exit', function (code, signal) {
|
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
});
|
|
57
|
+
|
|
58
|
+
// terminate children.
|
|
59
|
+
process.on('SIGINT', function () {
|
|
60
|
+
proc.kill('SIGINT'); // calls runner.abort()
|
|
61
|
+
proc.kill('SIGTERM'); // if that didn't work, we're probably in an infinite loop, so make it die.
|
|
62
|
+
process.kill(process.pid, 'SIGINT');
|
|
63
|
+
});
|
|
@@ -0,0 +1,369 @@
|
|
|
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
|
+
var retLines = [],
|
|
169
|
+
lines = value.split(/^/m);
|
|
170
|
+
|
|
171
|
+
for(var i = 0; i < lines.length; i++) {
|
|
172
|
+
var line = lines[i],
|
|
173
|
+
lastLine = lines[i - 1];
|
|
174
|
+
|
|
175
|
+
// Merge lines that may contain windows new lines
|
|
176
|
+
if (line == '\n' && lastLine && lastLine[lastLine.length - 1] === '\r') {
|
|
177
|
+
retLines[retLines.length - 1] += '\n';
|
|
178
|
+
} else if (line) {
|
|
179
|
+
retLines.push(line);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return retLines;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
Diff: Diff,
|
|
188
|
+
|
|
189
|
+
diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); },
|
|
190
|
+
diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); },
|
|
191
|
+
diffWordsWithSpace: function(oldStr, newStr) { return WordWithSpaceDiff.diff(oldStr, newStr); },
|
|
192
|
+
diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); },
|
|
193
|
+
|
|
194
|
+
diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); },
|
|
195
|
+
|
|
196
|
+
createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) {
|
|
197
|
+
var ret = [];
|
|
198
|
+
|
|
199
|
+
ret.push('Index: ' + fileName);
|
|
200
|
+
ret.push('===================================================================');
|
|
201
|
+
ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader));
|
|
202
|
+
ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader));
|
|
203
|
+
|
|
204
|
+
var diff = LineDiff.diff(oldStr, newStr);
|
|
205
|
+
if (!diff[diff.length-1].value) {
|
|
206
|
+
diff.pop(); // Remove trailing newline add
|
|
207
|
+
}
|
|
208
|
+
diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier
|
|
209
|
+
|
|
210
|
+
function contextLines(lines) {
|
|
211
|
+
return lines.map(function(entry) { return ' ' + entry; });
|
|
212
|
+
}
|
|
213
|
+
function eofNL(curRange, i, current) {
|
|
214
|
+
var last = diff[diff.length-2],
|
|
215
|
+
isLast = i === diff.length-2,
|
|
216
|
+
isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed);
|
|
217
|
+
|
|
218
|
+
// Figure out if this is the last line for the given file and missing NL
|
|
219
|
+
if (!/\n$/.test(current.value) && (isLast || isLastOfType)) {
|
|
220
|
+
curRange.push('\');
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
var oldRangeStart = 0, newRangeStart = 0, curRange = [],
|
|
225
|
+
oldLine = 1, newLine = 1;
|
|
226
|
+
for (var i = 0; i < diff.length; i++) {
|
|
227
|
+
var current = diff[i],
|
|
228
|
+
lines = current.lines || current.value.replace(/\n$/, '').split('\n');
|
|
229
|
+
current.lines = lines;
|
|
230
|
+
|
|
231
|
+
if (current.added || current.removed) {
|
|
232
|
+
if (!oldRangeStart) {
|
|
233
|
+
var prev = diff[i-1];
|
|
234
|
+
oldRangeStart = oldLine;
|
|
235
|
+
newRangeStart = newLine;
|
|
236
|
+
|
|
237
|
+
if (prev) {
|
|
238
|
+
curRange = contextLines(prev.lines.slice(-4));
|
|
239
|
+
oldRangeStart -= curRange.length;
|
|
240
|
+
newRangeStart -= curRange.length;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?'+':'-') + entry; }));
|
|
244
|
+
eofNL(curRange, i, current);
|
|
245
|
+
|
|
246
|
+
if (current.added) {
|
|
247
|
+
newLine += lines.length;
|
|
248
|
+
} else {
|
|
249
|
+
oldLine += lines.length;
|
|
250
|
+
}
|
|
251
|
+
} else {
|
|
252
|
+
if (oldRangeStart) {
|
|
253
|
+
// Close out any changes that have been output (or join overlapping)
|
|
254
|
+
if (lines.length <= 8 && i < diff.length-2) {
|
|
255
|
+
// Overlapping
|
|
256
|
+
curRange.push.apply(curRange, contextLines(lines));
|
|
257
|
+
} else {
|
|
258
|
+
// end the range and output
|
|
259
|
+
var contextSize = Math.min(lines.length, 4);
|
|
260
|
+
ret.push(
|
|
261
|
+
'@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize)
|
|
262
|
+
+ ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize)
|
|
263
|
+
+ ' @@');
|
|
264
|
+
ret.push.apply(ret, curRange);
|
|
265
|
+
ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));
|
|
266
|
+
if (lines.length <= 4) {
|
|
267
|
+
eofNL(ret, i, current);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
oldRangeStart = 0; newRangeStart = 0; curRange = [];
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
oldLine += lines.length;
|
|
274
|
+
newLine += lines.length;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return ret.join('\n') + '\n';
|
|
279
|
+
},
|
|
280
|
+
|
|
281
|
+
applyPatch: function(oldStr, uniDiff) {
|
|
282
|
+
var diffstr = uniDiff.split('\n');
|
|
283
|
+
var diff = [];
|
|
284
|
+
var remEOFNL = false,
|
|
285
|
+
addEOFNL = false;
|
|
286
|
+
|
|
287
|
+
for (var i = (diffstr[0][0]==='I'?4:0); i < diffstr.length; i++) {
|
|
288
|
+
if(diffstr[i][0] === '@') {
|
|
289
|
+
var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
|
|
290
|
+
diff.unshift({
|
|
291
|
+
start:meh[3],
|
|
292
|
+
oldlength:meh[2],
|
|
293
|
+
oldlines:[],
|
|
294
|
+
newlength:meh[4],
|
|
295
|
+
newlines:[]
|
|
296
|
+
});
|
|
297
|
+
} else if(diffstr[i][0] === '+') {
|
|
298
|
+
diff[0].newlines.push(diffstr[i].substr(1));
|
|
299
|
+
} else if(diffstr[i][0] === '-') {
|
|
300
|
+
diff[0].oldlines.push(diffstr[i].substr(1));
|
|
301
|
+
} else if(diffstr[i][0] === ' ') {
|
|
302
|
+
diff[0].newlines.push(diffstr[i].substr(1));
|
|
303
|
+
diff[0].oldlines.push(diffstr[i].substr(1));
|
|
304
|
+
} else if(diffstr[i][0] === '\\') {
|
|
305
|
+
if (diffstr[i-1][0] === '+') {
|
|
306
|
+
remEOFNL = true;
|
|
307
|
+
} else if(diffstr[i-1][0] === '-') {
|
|
308
|
+
addEOFNL = true;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
var str = oldStr.split('\n');
|
|
314
|
+
for (var i = diff.length - 1; i >= 0; i--) {
|
|
315
|
+
var d = diff[i];
|
|
316
|
+
for (var j = 0; j < d.oldlength; j++) {
|
|
317
|
+
if(str[d.start-1+j] !== d.oldlines[j]) {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines));
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (remEOFNL) {
|
|
325
|
+
while (!str[str.length-1]) {
|
|
326
|
+
str.pop();
|
|
327
|
+
}
|
|
328
|
+
} else if (addEOFNL) {
|
|
329
|
+
str.push('');
|
|
330
|
+
}
|
|
331
|
+
return str.join('\n');
|
|
332
|
+
},
|
|
333
|
+
|
|
334
|
+
convertChangesToXML: function(changes){
|
|
335
|
+
var ret = [];
|
|
336
|
+
for ( var i = 0; i < changes.length; i++) {
|
|
337
|
+
var change = changes[i];
|
|
338
|
+
if (change.added) {
|
|
339
|
+
ret.push('<ins>');
|
|
340
|
+
} else if (change.removed) {
|
|
341
|
+
ret.push('<del>');
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
ret.push(escapeHTML(change.value));
|
|
345
|
+
|
|
346
|
+
if (change.added) {
|
|
347
|
+
ret.push('</ins>');
|
|
348
|
+
} else if (change.removed) {
|
|
349
|
+
ret.push('</del>');
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return ret.join('');
|
|
353
|
+
},
|
|
354
|
+
|
|
355
|
+
// See: http://code.google.com/p/google-diff-match-patch/wiki/API
|
|
356
|
+
convertChangesToDMP: function(changes){
|
|
357
|
+
var ret = [], change;
|
|
358
|
+
for ( var i = 0; i < changes.length; i++) {
|
|
359
|
+
change = changes[i];
|
|
360
|
+
ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]);
|
|
361
|
+
}
|
|
362
|
+
return ret;
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
})();
|
|
366
|
+
|
|
367
|
+
if (typeof module !== 'undefined') {
|
|
368
|
+
module.exports = JsDiff;
|
|
369
|
+
}
|