gulp-sourcemaps
Advanced tools
Comparing version 1.7.3 to 1.8.1
386
index.js
'use strict'; | ||
var through = require('through2'); | ||
var fs = require('graceful-fs'); | ||
var path = require('path'); | ||
var File = require('vinyl'); | ||
var convert = require('convert-source-map'); | ||
var stripBom = require('strip-bom'); | ||
var detectNewline = require('detect-newline'); | ||
var acorn = require('acorn'); | ||
var SourceMapGenerator = require('source-map').SourceMapGenerator; | ||
var css = require('css'); | ||
var PLUGIN_NAME = 'gulp-sourcemap'; | ||
var urlRegex = /^(https?|webpack(-[^:]+)?):\/\//; | ||
/** | ||
* Initialize source mapping chain | ||
*/ | ||
module.exports.init = function init(options) { | ||
var debug = require('debug-fabulous')()(PLUGIN_NAME + ':init'); | ||
function sourceMapInit(file, encoding, callback) { | ||
/*jshint validthis:true */ | ||
// pass through if file is null or already has a source map | ||
if (file.isNull() || file.sourceMap) { | ||
this.push(file); | ||
return callback(); | ||
} | ||
if (file.isStream()) { | ||
return callback(new Error(PLUGIN_NAME + '-init: Streaming not supported')); | ||
} | ||
if (options === undefined) { | ||
options = {}; | ||
} | ||
debug(function () {return options;}); | ||
var fileContent = file.contents.toString(); | ||
var sourceMap; | ||
if (options.loadMaps) { | ||
debug('loadMaps'); | ||
var sourcePath = ''; //root path for the sources in the map | ||
// Try to read inline source map | ||
sourceMap = convert.fromSource(fileContent, options.largeFile); | ||
if (sourceMap) { | ||
sourceMap = sourceMap.toObject(); | ||
// sources in map are relative to the source file | ||
sourcePath = path.dirname(file.path); | ||
if (!options.largeFile) { | ||
fileContent = convert.removeComments(fileContent); | ||
} | ||
} else { | ||
// look for source map comment referencing a source map file | ||
var mapComment = convert.mapFileCommentRegex.exec(fileContent); | ||
var mapFile; | ||
if (mapComment) { | ||
mapFile = path.resolve(path.dirname(file.path), mapComment[1] || mapComment[2]); | ||
fileContent = convert.removeMapFileComments(fileContent); | ||
// if no comment try map file with same name as source file | ||
} else { | ||
mapFile = file.path + '.map'; | ||
} | ||
// sources in external map are relative to map file | ||
sourcePath = path.dirname(mapFile); | ||
try { | ||
sourceMap = JSON.parse(stripBom(fs.readFileSync(mapFile, 'utf8'))); | ||
} catch(e) {} | ||
} | ||
// fix source paths and sourceContent for imported source map | ||
if (sourceMap) { | ||
sourceMap.sourcesContent = sourceMap.sourcesContent || []; | ||
sourceMap.sources.forEach(function(source, i) { | ||
if (source.match(urlRegex)) { | ||
sourceMap.sourcesContent[i] = sourceMap.sourcesContent[i] || null; | ||
return; | ||
} | ||
var absPath = path.resolve(sourcePath, source); | ||
sourceMap.sources[i] = unixStylePath(path.relative(file.base, absPath)); | ||
if (!sourceMap.sourcesContent[i]) { | ||
var sourceContent = null; | ||
if (sourceMap.sourceRoot) { | ||
if (sourceMap.sourceRoot.match(urlRegex)) { | ||
sourceMap.sourcesContent[i] = null; | ||
return; | ||
} | ||
absPath = path.resolve(sourcePath, sourceMap.sourceRoot, source); | ||
} | ||
// if current file: use content | ||
if (absPath === file.path) { | ||
sourceContent = fileContent; | ||
// else load content from file | ||
} else { | ||
try { | ||
if (options.debug) | ||
debug('No source content for "' + source + '". Loading from file.'); | ||
sourceContent = stripBom(fs.readFileSync(absPath, 'utf8')); | ||
} catch (e) { | ||
if (options.debug) | ||
debug('warn: source file not found: ' + absPath); | ||
} | ||
} | ||
sourceMap.sourcesContent[i] = sourceContent; | ||
} | ||
}); | ||
// remove source map comment from source | ||
file.contents = new Buffer(fileContent, 'utf8'); | ||
} | ||
} | ||
if (!sourceMap && options.identityMap) { | ||
debug(function () { return 'identityMap'; }); | ||
var fileType = path.extname(file.path); | ||
var source = unixStylePath(file.relative); | ||
var generator = new SourceMapGenerator({file: source}); | ||
if (fileType === '.js') { | ||
var tokenizer = acorn.tokenizer(fileContent, {locations: true}); | ||
while (true) { | ||
var token = tokenizer.getToken(); | ||
if (token.type.label === "eof") | ||
break; | ||
var mapping = { | ||
original: token.loc.start, | ||
generated: token.loc.start, | ||
source: source, | ||
}; | ||
if (token.type.label === 'name') { | ||
mapping.name = token.value; | ||
} | ||
generator.addMapping(mapping); | ||
} | ||
generator.setSourceContent(source, fileContent); | ||
sourceMap = generator.toJSON(); | ||
} else if (fileType === '.css') { | ||
debug('css'); | ||
var ast = css.parse(fileContent, {silent: true}); | ||
debug(function () { return ast;}); | ||
var registerTokens = function(ast) { | ||
if (ast.position) { | ||
generator.addMapping({ | ||
original: ast.position.start, | ||
generated: ast.position.start, | ||
source: source, | ||
}); | ||
} | ||
function logAst(key, ast) { | ||
debug(function () { return 'key: ' + key;}); | ||
debug(function () { return ast[key];}); | ||
} | ||
for (var key in ast) { | ||
logAst(key, ast); | ||
if (key !== "position") { | ||
if (Object.prototype.toString.call(ast[key]) === '[object Object]') { | ||
registerTokens(ast[key]); | ||
} else if (Array.isArray(ast[key])) { | ||
debug(function () { return "@@@@ ast[key] isArray @@@@";}); | ||
for (var i = 0; i < ast[key].length; i++) { | ||
registerTokens(ast[key][i]); | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
registerTokens(ast); | ||
generator.setSourceContent(source, fileContent); | ||
sourceMap = generator.toJSON(); | ||
} | ||
} | ||
if (!sourceMap) { | ||
// Make an empty source map | ||
sourceMap = { | ||
version : 3, | ||
names: [], | ||
mappings: '', | ||
sources: [unixStylePath(file.relative)], | ||
sourcesContent: [fileContent] | ||
}; | ||
} | ||
sourceMap.file = unixStylePath(file.relative); | ||
file.sourceMap = sourceMap; | ||
this.push(file); | ||
callback(); | ||
} | ||
return through.obj(sourceMapInit); | ||
module.exports = { | ||
init: require('./src/init'), | ||
write: require('./src/write') | ||
}; | ||
/** | ||
* Write the source map | ||
* | ||
* @param options options to change the way the source map is written | ||
* | ||
*/ | ||
module.exports.write = function write(destPath, options) { | ||
var debug = require('debug-fabulous')()(PLUGIN_NAME + ':write'); | ||
if (options === undefined && Object.prototype.toString.call(destPath) === '[object Object]') { | ||
options = destPath; | ||
destPath = undefined; | ||
} | ||
options = options || {}; | ||
// set defaults for options if unset | ||
if (options.includeContent === undefined) | ||
options.includeContent = true; | ||
if (options.addComment === undefined) | ||
options.addComment = true; | ||
if (options.charset === undefined) | ||
options.charset = "utf8"; | ||
debug(function() {return options;}); | ||
function sourceMapWrite(file, encoding, callback) { | ||
/*jshint validthis:true */ | ||
if (file.isNull() || !file.sourceMap) { | ||
this.push(file); | ||
return callback(); | ||
} | ||
if (file.isStream()) { | ||
return callback(new Error(PLUGIN_NAME + '-write: Streaming not supported')); | ||
} | ||
var sourceMap = file.sourceMap; | ||
// fix paths if Windows style paths | ||
sourceMap.file = unixStylePath(file.relative); | ||
if (options.mapSources && typeof options.mapSources === 'function') { | ||
sourceMap.sources = sourceMap.sources.map(function(filePath) { | ||
return options.mapSources(filePath); | ||
}); | ||
} | ||
sourceMap.sources = sourceMap.sources.map(function(filePath) { | ||
return unixStylePath(filePath); | ||
}); | ||
if (typeof options.sourceRoot === 'function') { | ||
sourceMap.sourceRoot = options.sourceRoot(file); | ||
} else { | ||
sourceMap.sourceRoot = options.sourceRoot; | ||
} | ||
if (sourceMap.sourceRoot === null) { | ||
sourceMap.sourceRoot = undefined; | ||
} | ||
if (options.includeContent) { | ||
sourceMap.sourcesContent = sourceMap.sourcesContent || []; | ||
// load missing source content | ||
for (var i = 0; i < file.sourceMap.sources.length; i++) { | ||
if (!sourceMap.sourcesContent[i]) { | ||
var sourcePath = path.resolve(sourceMap.sourceRoot || file.base, sourceMap.sources[i]); | ||
try { | ||
if (options.debug) | ||
debug('No source content for "' + sourceMap.sources[i] + '". Loading from file.'); | ||
sourceMap.sourcesContent[i] = stripBom(fs.readFileSync(sourcePath, 'utf8')); | ||
} catch (e) { | ||
if (options.debug) | ||
debug('source file not found: ' + sourcePath); | ||
} | ||
} | ||
} | ||
} else { | ||
delete sourceMap.sourcesContent; | ||
} | ||
var extension = file.relative.split('.').pop(); | ||
var newline = detectNewline.graceful(file.contents.toString()); | ||
var commentFormatter; | ||
switch (extension) { | ||
case 'css': | ||
commentFormatter = function(url) { | ||
return newline + "/*# sourceMappingURL=" + url + " */" + newline; | ||
}; | ||
break; | ||
case 'js': | ||
commentFormatter = function(url) { | ||
return newline + "//# sourceMappingURL=" + url + newline; | ||
}; | ||
break; | ||
default: | ||
commentFormatter = function(url) { return ""; }; | ||
} | ||
var comment, sourceMappingURLPrefix; | ||
if (destPath === undefined || destPath === null) { | ||
// encode source map into comment | ||
var base64Map = new Buffer(JSON.stringify(sourceMap)).toString('base64'); | ||
comment = commentFormatter('data:application/json;charset=' + options.charset + ';base64,' + base64Map); | ||
} else { | ||
var mapFile = path.join(destPath, file.relative) + '.map'; | ||
// custom map file name | ||
if (options.mapFile && typeof options.mapFile === 'function') { | ||
mapFile = options.mapFile(mapFile); | ||
} | ||
var sourceMapPath = path.join(file.base, mapFile); | ||
// if explicit destination path is set | ||
if (options.destPath) { | ||
var destSourceMapPath = path.join(file.cwd, options.destPath, mapFile); | ||
var destFilePath = path.join(file.cwd, options.destPath, file.relative); | ||
sourceMap.file = unixStylePath(path.relative(path.dirname(destSourceMapPath), destFilePath)); | ||
if (sourceMap.sourceRoot === undefined) { | ||
sourceMap.sourceRoot = unixStylePath(path.relative(path.dirname(destSourceMapPath), file.base)); | ||
} else if (sourceMap.sourceRoot === '' || (sourceMap.sourceRoot && sourceMap.sourceRoot[0] === '.')) { | ||
sourceMap.sourceRoot = unixStylePath(path.join(path.relative(path.dirname(destSourceMapPath), file.base), sourceMap.sourceRoot)); | ||
} | ||
} else { | ||
// best effort, can be incorrect if options.destPath not set | ||
sourceMap.file = unixStylePath(path.relative(path.dirname(sourceMapPath), file.path)); | ||
if (sourceMap.sourceRoot === '' || (sourceMap.sourceRoot && sourceMap.sourceRoot[0] === '.')) { | ||
sourceMap.sourceRoot = unixStylePath(path.join(path.relative(path.dirname(sourceMapPath), file.base), sourceMap.sourceRoot)); | ||
} | ||
} | ||
// add new source map file to stream | ||
var sourceMapFile = new File({ | ||
cwd: file.cwd, | ||
base: file.base, | ||
path: sourceMapPath, | ||
contents: new Buffer(JSON.stringify(sourceMap)), | ||
stat: { | ||
isFile: function () { return true; }, | ||
isDirectory: function () { return false; }, | ||
isBlockDevice: function () { return false; }, | ||
isCharacterDevice: function () { return false; }, | ||
isSymbolicLink: function () { return false; }, | ||
isFIFO: function () { return false; }, | ||
isSocket: function () { return false; } | ||
} | ||
}); | ||
this.push(sourceMapFile); | ||
var sourceMapPathRelative = path.relative(path.dirname(file.path), sourceMapPath); | ||
if (options.sourceMappingURLPrefix) { | ||
var prefix = ''; | ||
if (typeof options.sourceMappingURLPrefix === 'function') { | ||
prefix = options.sourceMappingURLPrefix(file); | ||
} else { | ||
prefix = options.sourceMappingURLPrefix; | ||
} | ||
sourceMapPathRelative = prefix+path.join('/', sourceMapPathRelative); | ||
} | ||
comment = commentFormatter(unixStylePath(sourceMapPathRelative)); | ||
if (options.sourceMappingURL && typeof options.sourceMappingURL === 'function') { | ||
comment = commentFormatter(options.sourceMappingURL(file)); | ||
} | ||
} | ||
// append source map comment | ||
if (options.addComment) | ||
file.contents = Buffer.concat([file.contents, new Buffer(comment)]); | ||
this.push(file); | ||
callback(); | ||
} | ||
return through.obj(sourceMapWrite); | ||
}; | ||
function unixStylePath(filePath) { | ||
return filePath.split(path.sep).join('/'); | ||
} |
{ | ||
"name": "gulp-sourcemaps", | ||
"version": "1.7.3", | ||
"version": "1.8.1", | ||
"description": "Source map support for Gulp.js", | ||
@@ -43,4 +43,5 @@ "homepage": "http://github.com/floridoo/gulp-sourcemaps", | ||
"files": [ | ||
"index.js" | ||
"index.js", | ||
"src" | ||
] | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
27662
7
389
1