This repository has been archived by the owner on May 12, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
dynoSrc-diff.js
125 lines (107 loc) · 3.04 KB
/
dynoSrc-diff.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/**
* dynoSrc-diff
*/
(function (dynoSrc) {
var callbackCount = -1,
callbacks = [],
endpoint = '/dynoSrc',
callbackPrefix = '__dynoSrcCb',
contextDiffDetect = /^@@ -\d+,\d+ \+\d+,\d+ @@$/m;
/*
* applyPatch(oldStr, diffStr)
*
* Applies diff. Taken from jsdiff. :D
*/
function applyPatch (oldStr, uniDiff) {
var diffstr = uniDiff.split('\n');
var diff = [];
var remEOFNL = false,
addEOFNL = false;
// i = 4 in order to skip diff headers.
for (var i = 4; i < diffstr.length; i++) {
if(diffstr[i][0] === '@') {
var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
diff.unshift({
start:meh[3],
oldlength:meh[2],
oldlines:[],
newlength:meh[4],
newlines:[]
});
} else if(diffstr[i][0] === '+') {
diff[0].newlines.push(diffstr[i].substr(1));
} else if(diffstr[i][0] === '-') {
diff[0].oldlines.push(diffstr[i].substr(1));
} else if(diffstr[i][0] === ' ') {
diff[0].newlines.push(diffstr[i].substr(1));
diff[0].oldlines.push(diffstr[i].substr(1));
} else if(diffstr[i][0] === '\\') {
if (diffstr[i-1][0] === '+') {
remEOFNL = true;
} else if(diffstr[i-1][0] === '-') {
addEOFNL = true;
}
}
}
var str = oldStr.split('\n');
for (i = diff.length - 1; i >= 0; i--) {
var d = diff[i];
for (var j = 0; j < d.oldlength; j++) {
if(str[d.start-1+j] !== d.oldlines[j]) {
return false;
}
}
Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines));
}
if (remEOFNL) {
while (!str[str.length-1]) {
str.pop();
}
} else if (addEOFNL) {
str.push('');
}
return str.join('\n');
}
/*
* fetch(moduleName, revisionHash)
*
* Given a moduleName and revisionHash, will request a diff from the server via
* JSONP. The callback will then patch the local copy of the module.
*/
dynoSrc.fetch = function fetch (name, version, cb) {
var currentRev = this.getRevision(name) || '',
callbackId = ++callbackCount,
callbackName = callbackPrefix + callbackId,
path = endpoint + '?',
script = document.createElement('script');
window[callbackName] = function (name, version, patchSrc) {
var updated = dynoSrc.add(name, version, patchSrc);
if (cb) {
cb(name, version, updatedSrc, patchSrc);
}
};
path += 'id=' + name +
'&from=' + currentRev +
'&to=' + version +
'&fmt=js' +
'&callback=' + callbackName;
document.head.appendChild(script);
script.src = path;
return script;
};
/**
* Replace the `add` function with a version that can detect contextual
* diffs and apply patches before storing in the browser and evaluating.
* @override add
*/
var oldAdd = dynoSrc.add;
dynoSrc.add = function add (name, version, src, andEval) {
var srcToAdd = src,
existing;
if (contextDiffDetect.test(src)) {
var existing = this.storage.get(name) || '';
srcToAdd = applyPatch(existing, src);
}
return oldAdd.call(this, name, version, srcToAdd, andEval);
};
})(window.dynoSrc);