Skip to content

Commit 66e6d2a

Browse files
authored
Merge pull request #255 from realtymaps/dev/nem/1.X/preExistingSourcemapFlag
PreExisting inline sourceMap checking
2 parents 25f5778 + b7f1dbf commit 66e6d2a

File tree

10 files changed

+208
-52
lines changed

10 files changed

+208
-52
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ reports
44
*.tgz
55
.idea
66
*.lock
7+
tmp

.travis.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
sudo: false
22
language: node_js
33
node_js:
4-
- stable
4+
- '6'
5+
- '4'
56
- '0.12'
67
- '0.10'
78
after_script:

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@
3434
"devDependencies": {
3535
"coveralls": "2.X",
3636
"faucet": "0.0.X",
37+
"gulp": "3.X",
3738
"hook-std": "0.2.X",
3839
"istanbul": "0.X",
3940
"jshint": "2.X",
41+
"object-assign": "^4.1.0",
4042
"tape": "4.X"
4143
},
4244
"files": [

src/init.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ function init(options) {
4040

4141
var fileContent = file.contents.toString();
4242
var sourceMap;
43+
var preExisting = utils.getPreExisting(fileContent);
4344

4445
if (options.loadMaps) {
4546
debug('loadMaps');
@@ -113,11 +114,11 @@ function init(options) {
113114
}
114115
sourceMap.sourcesContent[i] = sourceContent;
115116
}
116-
});
117117

118-
// remove source map comment from source
119-
file.contents = new Buffer(fileContent, 'utf8');
118+
});
120119
}
120+
// remove source map comment from source
121+
file.contents = new Buffer(fileContent, 'utf8');
121122
}
122123

123124
if (!sourceMap && options.identityMap) {
@@ -199,6 +200,8 @@ function init(options) {
199200
sourcesContent: [fileContent]
200201
};
201202
}
203+
else if(preExisting !== null && typeof preExisting !== 'undefined')
204+
sourceMap.preExisting = preExisting
202205

203206
sourceMap.file = unixStylePath(file.relative);
204207
file.sourceMap = sourceMap;

src/utils.js

+60-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
2-
var path = require('path');
2+
var path = require('path'),
3+
detectNewline = require('detect-newline');
34

45
function unixStylePath(filePath) {
56
return filePath.split(path.sep).join('/');
@@ -9,8 +10,65 @@ var PLUGIN_NAME = require('../package.json').name;
910

1011
var urlRegex = /^(https?|webpack(-[^:]+)?):\/\//;
1112

13+
var debug = require('debug-fabulous')()(PLUGIN_NAME + ':utils');
14+
15+
/*
16+
So reusing the same ref for a regex (with global (g)) is from a poor decision in js.
17+
See http://stackoverflow.com/questions/10229144/bug-with-regexp-in-javascript-when-do-global-search
18+
19+
So we either need to use a new instance of a regex everywhere.
20+
*/
21+
var sourceMapUrlRegEx = function(){ return /\/\/\# sourceMappingURL\=.*/g;}
22+
23+
24+
var getCommentFormatter = function (file) {
25+
var extension = file.relative.split('.').pop(),
26+
fileContents = file.contents.toString(),
27+
newline = detectNewline.graceful(fileContents || ''),
28+
commentFormatter = function(url) {
29+
return '';
30+
};
31+
32+
if (file.sourceMap.preExisting){
33+
debug('preExisting commentFormatter');
34+
commentFormatter = function(url) {
35+
return file.sourceMap.preExisting;
36+
};
37+
return commentFormatter
38+
}
39+
40+
switch (extension) {
41+
case 'css':
42+
debug('css commentFormatter');
43+
commentFormatter = function(url) {
44+
return newline + "/*# sourceMappingURL=" + url + " */" + newline;
45+
};
46+
break;
47+
case 'js':
48+
debug('js commentFormatter');
49+
commentFormatter = function(url) {
50+
return newline + "//# sourceMappingURL=" + url + newline;
51+
};
52+
break;
53+
default:
54+
debug('unknown commentFormatter')
55+
}
56+
57+
return commentFormatter;
58+
}
59+
60+
var getPreExisting = function(fileContent){
61+
if(sourceMapUrlRegEx().test(fileContent)){
62+
debug('has preExisting');
63+
return fileContent.match(sourceMapUrlRegEx())[0];
64+
}
65+
}
66+
1267
module.exports = {
1368
unixStylePath: unixStylePath,
1469
PLUGIN_NAME: PLUGIN_NAME,
15-
urlRegex: urlRegex
70+
urlRegex: urlRegex,
71+
sourceMapUrlRegEx: sourceMapUrlRegEx,
72+
getCommentFormatter: getCommentFormatter,
73+
getPreExisting: getPreExisting
1674
};

src/write.js

+9-27
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ var utils = require('./utils'),
66
fs = require('graceful-fs'),
77
path = require('path'),
88
File = require('vinyl'),
9-
stripBom = require('strip-bom'),
10-
detectNewline = require('detect-newline');
9+
stripBom = require('strip-bom');
1110

1211
/**
1312
* Write the source map
@@ -92,34 +91,13 @@ function write(destPath, options) {
9291
delete sourceMap.sourcesContent;
9392
}
9493

95-
var extension = file.relative.split('.').pop();
96-
var newline = detectNewline.graceful(file.contents.toString());
97-
var commentFormatter;
98-
99-
switch (extension) {
100-
case 'css':
101-
commentFormatter = function(url) {
102-
return newline + "/*# sourceMappingURL=" + url + " */" + newline;
103-
};
104-
break;
105-
case 'js':
106-
commentFormatter = function(url) {
107-
return newline + "//# sourceMappingURL=" + url + newline;
108-
};
109-
break;
110-
default:
111-
/* jshint ignore:start */
112-
commentFormatter = function(url) {
113-
return "";
114-
};
115-
/* jshint ignore:end */
116-
}
117-
118-
var comment;
94+
var comment,
95+
commentFormatter = utils.getCommentFormatter(file);
11996

12097
if (destPath === undefined || destPath === null) {
12198
// encode source map into comment
12299
var base64Map = new Buffer(JSON.stringify(sourceMap)).toString('base64');
100+
debug("basic comment")
123101
comment = commentFormatter('data:application/json;charset=' + options.charset + ';base64,' + base64Map);
124102
} else {
125103
var mapFile = path.join(destPath, file.relative) + '.map';
@@ -174,16 +152,20 @@ function write(destPath, options) {
174152
}
175153
sourceMapPathRelative = prefix + path.join('/', sourceMapPathRelative);
176154
}
155+
debug("destPath comment")
177156
comment = commentFormatter(unixStylePath(sourceMapPathRelative));
178157

179158
if (options.sourceMappingURL && typeof options.sourceMappingURL === 'function') {
159+
debug("options.sourceMappingURL comment")
180160
comment = commentFormatter(options.sourceMappingURL(file));
181161
}
182162
}
183163

164+
var preExisting = options.preExisting && utils.getPreExisting(String(file.contents));
184165
// append source map comment
185-
if (options.addComment)
166+
if (options.addComment && !preExisting){
186167
file.contents = Buffer.concat([file.contents, new Buffer(comment)]);
168+
}
187169

188170
this.push(file);
189171
callback();

test/assets/helloworld.map.js

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/init.js

+11-12
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ test('init: should import an existing inline source map', function(t) {
164164
t.ok(data, 'should pass something through');
165165
t.ok(data instanceof File, 'should pass a vinyl file through');
166166
t.ok(data.sourceMap, 'should add a source map object');
167+
t.notOk(/sourceMappingURL/.test(data.contents.toString()), 'should not have sourcemapping in data.contents');
167168
t.equal(String(data.sourceMap.version), '3', 'should have version 3');
168169
t.deepEqual(data.sourceMap.sources, [
169170
'test1.js', 'test2.js'
@@ -179,14 +180,6 @@ test('init: should import an existing inline source map', function(t) {
179180
}).write(makeFileWithInlineSourceMap());
180181
});
181182

182-
test('init: should remove inline sourcemap', function(t) {
183-
var pipeline = sourcemaps.init({loadMaps: true});
184-
pipeline.on('data', function(data) {
185-
t.notOk(/sourceMappingURL/.test(data.contents.toString()), 'should not have sourcemapping');
186-
t.end();
187-
}).write(makeFileWithInlineSourceMap());
188-
});
189-
190183
test('init: should load external source map file referenced in comment with the \/\/# syntax', function(t) {
191184
var file = makeFile();
192185
file.contents = new Buffer(sourceContent + '\n//# sourceMappingURL=helloworld2.js.map');
@@ -400,10 +393,16 @@ test('init: should output an error message if debug option is set and sourceCont
400393

401394
pipeline.on('data', function() {
402395
unhook();
403-
// debug.save(null);
404-
t.ok(history.length == 4, 'history len');
405-
t.ok(history[2].match(/No source content for \"missingfile\". Loading from file./), 'should log missing source content');
406-
t.ok(history[3].match(/source file not found: /), 'should warn about missing file');
396+
var hasRegex = function(regex){
397+
return function(s){
398+
return regex.test(s);
399+
};
400+
};
401+
t.ok(
402+
history.some(
403+
hasRegex(/No source content for \"missingfile\". Loading from file./)),
404+
'should log missing source content');
405+
t.ok(history.some(hasRegex(/source file not found: /)), 'should warn about missing file');
407406
t.end();
408407
}).write(file);
409408

test/integration.js

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
'use strict';
2+
var gulp = require('gulp');
3+
var test = require('tape');
4+
var $ = require('..');
5+
var PLUGIN_NAME = require('../src/utils').PLUGIN_NAME;
6+
var debug = require('debug-fabulous')()(PLUGIN_NAME + ':test:integration');
7+
var join = require('path').join;
8+
var fs = require('fs');
9+
var sourceContent = fs.readFileSync(join(__dirname, 'assets/helloworld.js')).toString();
10+
11+
debug('running');
12+
13+
test('creates inline mapping', function(t) {
14+
15+
gulp.src(join(__dirname, './assets/helloworld.js'))
16+
.pipe($.init())
17+
.pipe($.write())
18+
// .pipe(gulp.dest('tmp'))
19+
.on('data', function(data) {
20+
t.ok(data.sourceMap, 'should add a source map object');
21+
t.deepEqual(
22+
data.contents.toString(),
23+
sourceContent + "\n//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJoZWxsb3dvcmxkLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gaGVsbG9Xb3JsZCgpIHtcbiAgICBjb25zb2xlLmxvZygnSGVsbG8gd29ybGQhJyk7XG59XG4iXSwiZmlsZSI6ImhlbGxvd29ybGQuanMifQ==\n",
24+
'file should be sourcemapped'
25+
);
26+
t.end();
27+
})
28+
.on('error', function() {
29+
t.fail('emitted error');
30+
t.end();
31+
})
32+
.on('close', function() {
33+
t.end();
34+
});
35+
});
36+
37+
test('creates re-uses existing mapping', function(t) {
38+
gulp.src(join(__dirname, './assets/helloworld.map.js'))
39+
.pipe($.init({loadMaps:true}))
40+
.pipe($.write())
41+
// .pipe(gulp.dest('tmp'))
42+
.on('data', function(data) {
43+
t.ok(data.sourceMap, 'should add a source map object');
44+
t.ok(!!data.sourceMap.preExisting, 'should know the sourcemap pre-existed');
45+
t.deepEqual(
46+
data.contents.toString(),
47+
sourceContent + "\n//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJoZWxsb3dvcmxkLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gaGVsbG9Xb3JsZCgpIHtcbiAgICBjb25zb2xlLmxvZygnSGVsbG8gd29ybGQhJyk7XG59XG4iXSwiZmlsZSI6ImhlbGxvd29ybGQuanMifQ==",
48+
'file should be sourcemapped'
49+
);
50+
t.end();
51+
})
52+
.on('error', function() {
53+
t.fail('emitted error');
54+
t.end();
55+
})
56+
.on('close', function() {
57+
t.end();
58+
});
59+
});

0 commit comments

Comments
 (0)