diff options
Diffstat (limited to 'node_modules/gulp-sourcemaps/index.js')
-rw-r--r-- | node_modules/gulp-sourcemaps/index.js | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/node_modules/gulp-sourcemaps/index.js b/node_modules/gulp-sourcemaps/index.js new file mode 100644 index 000000000..be952cd06 --- /dev/null +++ b/node_modules/gulp-sourcemaps/index.js @@ -0,0 +1,269 @@ +'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 PLUGIN_NAME = 'gulp-sourcemap'; +var urlRegex = /^(https?|webpack(-[^:]+)?):\/\//; + +/** + * Initialize source mapping chain + */ +module.exports.init = function init(options) { + 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')); + } + + var fileContent = file.contents.toString(); + var sourceMap; + + if (options && options.loadMaps) { + var sourcePath = ''; //root path for the sources in the map + + // Try to read inline source map + sourceMap = convert.fromSource(fileContent); + if (sourceMap) { + sourceMap = sourceMap.toObject(); + // sources in map are relative to the source file + sourcePath = path.dirname(file.path); + 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) + console.log(PLUGIN_NAME + '-init: No source content for "' + source + '". Loading from file.'); + sourceContent = stripBom(fs.readFileSync(absPath, 'utf8')); + } catch (e) { + if (options.debug) + console.warn(PLUGIN_NAME + '-init: source file not found: ' + absPath); + } + } + sourceMap.sourcesContent[i] = sourceContent; + } + }); + + // remove source map comment from source + file.contents = new Buffer(fileContent, 'utf8'); + } + } + + 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); +}; + +/** + * Write the source map + * + * @param options options to change the way the source map is written + * + */ +module.exports.write = function write(destPath, options) { + 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; + + 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); + 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 (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) + console.log(PLUGIN_NAME + '-write: No source content for "' + sourceMap.sources[i] + '". Loading from file.'); + sourceMap.sourcesContent[i] = stripBom(fs.readFileSync(sourcePath, 'utf8')); + } catch (e) { + if (options.debug) + console.warn(PLUGIN_NAME + '-write: source file not found: ' + sourcePath); + } + } + } + if (sourceMap.sourceRoot === undefined) { + sourceMap.sourceRoot = '/source/'; + } else if (sourceMap.sourceRoot === null) { + sourceMap.sourceRoot = undefined; + } + } else { + delete sourceMap.sourcesContent; + } + + var extension = file.relative.split('.').pop(); + var commentFormatter; + + switch (extension) { + case 'css': + commentFormatter = function(url) { return "\n/*# sourceMappingURL=" + url + " */\n"; }; + break; + case 'js': + commentFormatter = function(url) { return "\n//# sourceMappingURL=" + url + "\n"; }; + break; + default: + commentFormatter = function(url) { return ""; }; + } + + var comment, sourceMappingURLPrefix; + if (!destPath) { + // encode source map into comment + var base64Map = new Buffer(JSON.stringify(sourceMap)).toString('base64'); + comment = commentFormatter('data:application/json;base64,' + base64Map); + } else { + var sourceMapPath = path.join(file.base, destPath, file.relative) + '.map'; + // 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('/'); +} |