pax_global_header00006660000000000000000000000064130146467210014516gustar00rootroot0000000000000052 comment=da0efa86cd017bb92ff032f66a45b0f9875cd140 gulp-sourcemaps-1.9.1/000077500000000000000000000000001301464672100146545ustar00rootroot00000000000000gulp-sourcemaps-1.9.1/.editorconfig000066400000000000000000000005661301464672100173400ustar00rootroot00000000000000# EditorConfig helps developers define and maintain consistent # coding styles between different editors and IDEs # editorconfig.org root = true [*] # Change these settings to your own preference indent_style = space indent_size = 2 # We recommend you to keep these unchanged end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true gulp-sourcemaps-1.9.1/.gitignore000066400000000000000000000000661301464672100166460ustar00rootroot00000000000000.DS_Store node_modules reports *.tgz .idea *.lock tmp gulp-sourcemaps-1.9.1/.jsbeautifyrc000066400000000000000000000002761301464672100173540ustar00rootroot00000000000000{ "js":{ "indent_level": 0, "indent_with_tabs": false, "preserve_newlines": true, "max_preserve_newlines": 2, "jslint_happy": true, "indent_handlebars": true } } gulp-sourcemaps-1.9.1/.jshintrc000066400000000000000000000001051301464672100164750ustar00rootroot00000000000000{ "node": true, "strict": true, "unused": true, "undef": true } gulp-sourcemaps-1.9.1/.travis.yml000066400000000000000000000002251301464672100167640ustar00rootroot00000000000000sudo: false language: node_js node_js: - '6' - '4' - '0.12' - '0.10' after_script: - npm run coveralls branches: except: - /^v[0-9]/ gulp-sourcemaps-1.9.1/LICENSE.md000066400000000000000000000013571301464672100162660ustar00rootroot00000000000000## ISC License Copyright (c) 2014, Florian Reiterer Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. gulp-sourcemaps-1.9.1/README.md000066400000000000000000000300771301464672100161420ustar00rootroot00000000000000## gulp-sourcemaps [![NPM version][npm-image]][npm-url] [![build status][travis-image]][travis-url] [![Test coverage][coveralls-image]][coveralls-url] ### Branching - master: is latest currently (2.X) - node > 4.X - 1.X: is node 0.X - only issues appear to be es6 Preferably, we would like move on from node 0.X as much as possible as some of the dependencies are doing so as well. Meaning for features please target master for PRs. If bugs are found to be relvant to both 1.X and master then please target PRs for the 1.X branch to make git merging easier. ### Usage #### Write inline source maps Inline source maps are embedded in the source file. Example: ```javascript var gulp = require('gulp'); var plugin1 = require('gulp-plugin1'); var plugin2 = require('gulp-plugin2'); var sourcemaps = require('gulp-sourcemaps'); gulp.task('javascript', function() { gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write()) .pipe(gulp.dest('dist')); }); ``` All plugins between `sourcemaps.init()` and `sourcemaps.write()` need to have support for `gulp-sourcemaps`. You can find a list of such plugins in the [wiki](https://github.com/floridoo/gulp-sourcemaps/wiki/Plugins-with-gulp-sourcemaps-support). #### Write external source map files To write external source map files, pass a path relative to the destination to `sourcemaps.write()`. Example: ```javascript var gulp = require('gulp'); var plugin1 = require('gulp-plugin1'); var plugin2 = require('gulp-plugin2'); var sourcemaps = require('gulp-sourcemaps'); gulp.task('javascript', function() { gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write('../maps')) .pipe(gulp.dest('dist')); }); ``` #### Load existing source maps To load existing source maps, pass the option `loadMaps: true` to `sourcemaps.init()`. Example: ```javascript var gulp = require('gulp'); var plugin1 = require('gulp-plugin1'); var plugin2 = require('gulp-plugin2'); var sourcemaps = require('gulp-sourcemaps'); gulp.task('javascript', function() { gulp.src('src/**/*.js') .pipe(sourcemaps.init({loadMaps: true})) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write()) .pipe(gulp.dest('dist')); }); ``` #### Handle large files To handle large files, pass the option `largeFile: true` to `sourcemaps.init()`. Example: ```javascript var gulp = require('gulp'); var plugin1 = require('gulp-plugin1'); var plugin2 = require('gulp-plugin2'); var sourcemaps = require('gulp-sourcemaps'); gulp.task('javascript', function() { gulp.src('src/**/*.js') .pipe(sourcemaps.init({largeFile: true})) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write()) .pipe(gulp.dest('dist')); }); ``` #### Handle source files from different directories Use the `base` option on `gulp.src` to make sure all files are relative to a common base directory. Example: ```javascript var gulp = require('gulp'); var plugin1 = require('gulp-plugin1'); var plugin2 = require('gulp-plugin2'); var sourcemaps = require('gulp-sourcemaps'); gulp.task('javascript', function() { gulp.src(['src/test.js', 'src/testdir/test2.js'], { base: 'src' }) .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write('../maps')) .pipe(gulp.dest('dist')); }); ``` ### Init Options - `loadMaps` Set to true to load existing maps for source files. Supports the following: - inline source maps - source map files referenced by a `sourceMappingURL=` comment - source map files with the same name (plus .map) in the same directory - `identityMap` Set to true to generate a full valid source map encoding no changes (slower, only for Javascript and CSS) instead of the default empty source map (no mappings, fast). Use this option if you get missing or incorrect mappings, e.g. when debugging. - `debug` Set this to `true` to output debug messages (e.g. about missing source content). ### Write Options - `addComment` By default a comment containing / referencing the source map is added. Set this to `false` to disable the comment (e.g. if you want to load the source maps by header). Example: ```javascript gulp.task('javascript', function() { var stream = gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write('../maps', {addComment: false})) .pipe(gulp.dest('dist')); }); ``` - `includeContent` By default the source maps include the source code. Pass `false` to use the original files. Including the content is the recommended way, because it "just works". When setting this to `false` you have to host the source files and set the correct `sourceRoot`. - `sourceRoot` Set the location where the source files are hosted (use this when `includeContent` is set to `false`). This is usually a URL (or an absolute URL path), not a local file system path. By default the source root is '' or in case `destPath` is set, the relative path from the source map to the source base directory (this should work for many dev environments). If a relative path is used (empty string or one starting with a `.`), it is interpreted as a path relative to the destination. The plugin rewrites it to a path relative to each source map. Example: ```javascript gulp.task('javascript', function() { var stream = gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write({includeContent: false, sourceRoot: '/src'})) .pipe(gulp.dest('dist')); }); ``` Example (using a function): ```javascript gulp.task('javascript', function() { var stream = gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write({ includeContent: false, sourceRoot: function(file) { return '/src'; } })) .pipe(gulp.dest('dist')); }); ``` Example (relative path): ```javascript gulp.task('javascript', function() { var stream = gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: '../src'})) .pipe(gulp.dest('dist')); }); ``` In this case for a file written to `dist/subdir/example.js`, the source map is written to `dist/subdir/example.js.map` and the sourceRoot will be `../../src` (resulting in the full source path `../../src/subdir/example.js`). - `destPath` Set the destination path (the same you pass to `gulp.dest()`). If the source map destination path is not a subpath of the destination path, this is needed to get the correct path in the `file` property of the source map. In addition, it allows to automatically set a relative `sourceRoot` if none is set explicitly. - `sourceMappingURLPrefix` Specify a prefix to be prepended onto the source map URL when writing external source maps. Relative paths will have their leading dots stripped. Example: ```javascript gulp.task('javascript', function() { var stream = gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write('../maps', { sourceMappingURLPrefix: 'https://asset-host.example.com/assets' })) .pipe(gulp.dest('public/scripts')); }); ``` This will result in a source mapping URL comment like `sourceMappingURL=https://asset-host.example.com/assets/maps/helloworld.js.map`. - `sourceMappingURL` If you need full control over the source map URL you can pass a function to this option. The output of the function must be the full URL to the source map (in function of the output file). Example: ```javascript gulp.task('javascript', function() { var stream = gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write('../maps', { sourceMappingURL: function(file) { return 'https://asset-host.example.com/' + file.relative + '.map'; } })) .pipe(gulp.dest('public/scripts')); }); ``` This will result in a source mapping URL comment like `sourceMappingURL=https://asset-host.example.com/helloworld.js.map`. - `mapFile` This option allows to rename the map file. It takes a function that is called for every map and receives the default map path as a parameter. Example: ```javascript gulp.task('javascript', function() { var stream = gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write('../maps', { mapFile: function(mapFilePath) { // source map files are named *.map instead of *.js.map return mapFilePath.replace('.js.map', '.map'); } })) .pipe(gulp.dest('public/scripts')); }); ``` - `mapSources` This option gives full control over the source paths. It takes a function that is called for every source and receives the default source path as a parameter. Example: ```javascript gulp.task('javascript', function() { var stream = gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write('../maps', { mapSources: function(sourcePath) { // source paths are prefixed with '../src/' return '../src/' + sourcePath; } })) .pipe(gulp.dest('public/scripts')); }); ``` - `debug` Set this to `true` to output debug messages (e.g. about missing source content). - `charset` Sets the charset for inline source maps. Default: `utf8` - `clone` Clones the original file for creation of the map file. Could be important if file history is important. See [file.clone()](https://github.com/gulpjs/vinyl#filecloneoptions) for possible options. Default: `{deep:false, contents:false}` ### Plugin developers only: - **How to add source map support to plugins** - Generate a source map for the transformation the plugin is applying - **Important**: Make sure the paths in the generated source map (`file` and `sources`) are relative to `file.base` (e.g. use `file.relative`). - Apply this source map to the vinyl `file`. E.g. by using [vinyl-sourcemaps-apply](https://github.com/floridoo/vinyl-sourcemaps-apply). This combines the source map of this plugin with the source maps coming from plugins further up the chain. - Add your plugin to the [wiki page](https://github.com/floridoo/gulp-sourcemaps/wiki/Plugins-with-gulp-sourcemaps-support) #### Example: ```js var through = require('through2'); var applySourceMap = require('vinyl-sourcemaps-apply'); var myTransform = require('myTransform'); module.exports = function(options) { function transform(file, encoding, callback) { // generate source maps if plugin source-map present if (file.sourceMap) { options.makeSourceMaps = true; } // do normal plugin logic var result = myTransform(file.contents, options); file.contents = new Buffer(result.code); // apply source map to the chain if (file.sourceMap) { applySourceMap(file, result.map); } this.push(file); callback(); } return through.obj(transform); }; ``` - **Very sourcemaps is working** See example below or refer to [test/write.js](./test/write.js) #### Example: ```js var stream = plugin(); var init = sourcemaps.init(); var write = sourcemaps.write(); init.pipe(stream).pipe(write); write.on('data', function (file) { assert(...); cb(); }); init.write(new gutil.File(...)); init.end(); ``` [npm-image]: https://img.shields.io/npm/v/gulp-sourcemaps.svg [npm-url]: https://www.npmjs.com/package/gulp-sourcemaps [travis-image]: https://img.shields.io/travis/floridoo/gulp-sourcemaps.svg [travis-url]: https://travis-ci.org/floridoo/gulp-sourcemaps [coveralls-image]: https://img.shields.io/coveralls/floridoo/gulp-sourcemaps.svg [coveralls-url]: https://coveralls.io/r/floridoo/gulp-sourcemaps?branch=master gulp-sourcemaps-1.9.1/index.js000066400000000000000000000001441301464672100163200ustar00rootroot00000000000000'use strict'; module.exports = { init: require('./src/init'), write: require('./src/write') }; gulp-sourcemaps-1.9.1/package.json000066400000000000000000000024231301464672100171430ustar00rootroot00000000000000{ "name": "gulp-sourcemaps", "version": "1.9.1", "description": "Source map support for Gulp.js", "homepage": "http://github.com/floridoo/gulp-sourcemaps", "repository": "git://github.com/floridoo/gulp-sourcemaps.git", "main": "index.js", "scripts": { "test": "jshint *.js test/*.js && faucet test/*.js", "tap": "tape test/*.js", "cover": "istanbul cover --dir reports/coverage tape \"test/*.js\"", "coveralls": "istanbul cover tape \"test/*.js\" --report lcovonly && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage" }, "keywords": [ "gulpplugin", "gulp", "source maps", "sourcemaps" ], "author": "Florian Reiterer ", "license": "ISC", "dependencies": { "acorn": "4.X", "convert-source-map": "1.X", "css": "2.X", "debug-fabulous": "0.0.X", "detect-newline": "2.X", "graceful-fs": "4.X", "source-map": "0.X", "strip-bom": "2.X", "through2": "2.X", "vinyl": "1.X" }, "devDependencies": { "coveralls": "2.X", "faucet": "0.0.X", "gulp": "3.X", "hook-std": "0.2.X", "istanbul": "0.X", "jshint": "2.X", "object-assign": "^4.1.0", "tape": "4.X" }, "files": [ "index.js", "src" ], "engines": { "node": ">=0.10.0" } } gulp-sourcemaps-1.9.1/scripts/000077500000000000000000000000001301464672100163435ustar00rootroot00000000000000gulp-sourcemaps-1.9.1/scripts/mockPublish000077500000000000000000000001571301464672100205540ustar00rootroot00000000000000#!/bin/bash set -e set -o pipefail mkdir -p ./tmp npm pack mv *.tgz ./tmp tar xvzf tmp/*.tgz -C ./tmp exit 0 gulp-sourcemaps-1.9.1/scripts/publish000077500000000000000000000002761301464672100177440ustar00rootroot00000000000000#!/bin/bash set -e set -o pipefail echo 'Testing Package for publishing...' ./node_modules/.bin/tape ./test/publish.js echo 'Attempting npm publish...' npm publish echo 'Success' exit 0 gulp-sourcemaps-1.9.1/src/000077500000000000000000000000001301464672100154435ustar00rootroot00000000000000gulp-sourcemaps-1.9.1/src/init.js000066400000000000000000000152121301464672100167450ustar00rootroot00000000000000'use strict'; var utils = require('./utils'), unixStylePath = utils.unixStylePath, PLUGIN_NAME = utils.PLUGIN_NAME, urlRegex = utils.urlRegex, through = require('through2'), fs = require('graceful-fs'), path = require('path'), convert = require('convert-source-map'), stripBom = require('strip-bom'), acorn = require('acorn'), SourceMapGenerator = require('source-map').SourceMapGenerator, css = require('css'); /** * Initialize source mapping chain */ 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; var preExisting = utils.getPreExisting(fileContent); 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] }; } else if(preExisting !== null && typeof preExisting !== 'undefined') sourceMap.preExisting = preExisting sourceMap.file = unixStylePath(file.relative); file.sourceMap = sourceMap; this.push(file); callback(); } return through.obj(sourceMapInit); } module.exports = init; gulp-sourcemaps-1.9.1/src/utils.js000066400000000000000000000037401301464672100171450ustar00rootroot00000000000000'use strict'; var path = require('path'), detectNewline = require('detect-newline'); function unixStylePath(filePath) { return filePath.split(path.sep).join('/'); } var PLUGIN_NAME = require('../package.json').name; var urlRegex = /^(https?|webpack(-[^:]+)?):\/\//; var debug = require('debug-fabulous')()(PLUGIN_NAME + ':utils'); /* So reusing the same ref for a regex (with global (g)) is from a poor decision in js. See http://stackoverflow.com/questions/10229144/bug-with-regexp-in-javascript-when-do-global-search So we either need to use a new instance of a regex everywhere. */ var sourceMapUrlRegEx = function(){ return /\/\/\# sourceMappingURL\=.*/g;} var getCommentFormatter = function (file) { var extension = file.relative.split('.').pop(), fileContents = file.contents.toString(), newline = detectNewline.graceful(fileContents || ''), commentFormatter = function(url) { return ''; }; if (file.sourceMap.preExisting){ debug('preExisting commentFormatter'); commentFormatter = function(url) { return file.sourceMap.preExisting; }; return commentFormatter } switch (extension) { case 'css': debug('css commentFormatter'); commentFormatter = function(url) { return newline + "/*# sourceMappingURL=" + url + " */" + newline; }; break; case 'js': debug('js commentFormatter'); commentFormatter = function(url) { return newline + "//# sourceMappingURL=" + url + newline; }; break; default: debug('unknown commentFormatter') } return commentFormatter; } var getPreExisting = function(fileContent){ if(sourceMapUrlRegEx().test(fileContent)){ debug('has preExisting'); return fileContent.match(sourceMapUrlRegEx())[0]; } } module.exports = { unixStylePath: unixStylePath, PLUGIN_NAME: PLUGIN_NAME, urlRegex: urlRegex, sourceMapUrlRegEx: sourceMapUrlRegEx, getCommentFormatter: getCommentFormatter, getPreExisting: getPreExisting }; gulp-sourcemaps-1.9.1/src/write.js000066400000000000000000000143641301464672100171430ustar00rootroot00000000000000'use strict'; var utils = require('./utils'), unixStylePath = utils.unixStylePath, PLUGIN_NAME = utils.PLUGIN_NAME, through = require('through2'), fs = require('graceful-fs'), path = require('path'), File = require('vinyl'), stripBom = require('strip-bom'); /** * Write the source map * * @param options options to change the way the source map is written * */ function write(destPath, options) { var debug = require('debug-fabulous')()(PLUGIN_NAME + ':write'); if (options === undefined && typeof destPath !== 'string') { 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 comment, commentFormatter = utils.getCommentFormatter(file); if (destPath === undefined || destPath === null) { // encode source map into comment var base64Map = new Buffer(JSON.stringify(sourceMap)).toString('base64'); debug("basic comment") 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)); } } var sourceMapFile; sourceMapFile = file.clone(options.clone || {deep:false, contents:false}); sourceMapFile.path = sourceMapPath; sourceMapFile.contents = new Buffer(JSON.stringify(sourceMap)); sourceMapFile.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); } debug("destPath comment") comment = commentFormatter(unixStylePath(sourceMapPathRelative)); if (options.sourceMappingURL && typeof options.sourceMappingURL === 'function') { debug("options.sourceMappingURL comment") comment = commentFormatter(options.sourceMappingURL(file)); } } var preExisting = options.preExisting && utils.getPreExisting(String(file.contents)); // append source map comment if (options.addComment && !preExisting){ file.contents = Buffer.concat([file.contents, new Buffer(comment)]); } this.push(file); callback(); } return through.obj(sourceMapWrite); } module.exports = write; gulp-sourcemaps-1.9.1/test/000077500000000000000000000000001301464672100156335ustar00rootroot00000000000000gulp-sourcemaps-1.9.1/test/assets/000077500000000000000000000000001301464672100171355ustar00rootroot00000000000000gulp-sourcemaps-1.9.1/test/assets/helloworld.js000066400000000000000000000001121301464672100216400ustar00rootroot00000000000000'use strict'; function helloWorld() { console.log('Hello world!'); } gulp-sourcemaps-1.9.1/test/assets/helloworld.map.js000066400000000000000000000006131301464672100224220ustar00rootroot00000000000000'use strict'; function helloWorld() { console.log('Hello world!'); } //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJoZWxsb3dvcmxkLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gaGVsbG9Xb3JsZCgpIHtcbiAgICBjb25zb2xlLmxvZygnSGVsbG8gd29ybGQhJyk7XG59XG4iXSwiZmlsZSI6ImhlbGxvd29ybGQuanMifQ== gulp-sourcemaps-1.9.1/test/assets/helloworld2.js.map000066400000000000000000000002431301464672100225030ustar00rootroot00000000000000{ "version":3, "file":"helloworld2.js", "names":[], "mappings":"", "sources":["helloworld2.js"], "sourcesContent":["source content from source map"] } gulp-sourcemaps-1.9.1/test/assets/helloworld3.js.map000066400000000000000000000001731301464672100225060ustar00rootroot00000000000000{ "version": 3, "file": "helloworld.js", "names": [], "mappings": "", "sources": ["helloworld.js", "test1.js"] } gulp-sourcemaps-1.9.1/test/assets/helloworld4.js.map000066400000000000000000000001761301464672100225120ustar00rootroot00000000000000{ "version": 3, "file": "helloworld.js", "names": [], "mappings": "", "sources": ["helloworld.js", "missingfile"] } gulp-sourcemaps-1.9.1/test/assets/helloworld5.js.map000066400000000000000000000002311301464672100225030ustar00rootroot00000000000000{ "version": 3, "file": "helloworld.js", "names": [], "mappings": "", "sources": ["../helloworld.js", "../test1.js"], "sourceRoot": "test" } gulp-sourcemaps-1.9.1/test/assets/helloworld6.js.map000066400000000000000000000002661301464672100225140ustar00rootroot00000000000000{ "version": 3, "file": "helloworld.js", "names": [], "mappings": "", "sources": ["helloworld.js", "http://example2.com/test1.js"], "sourceRoot": "http://example.com/" } gulp-sourcemaps-1.9.1/test/assets/test.css000066400000000000000000000000541301464672100206250ustar00rootroot00000000000000body { background: #eee; color: #888; } gulp-sourcemaps-1.9.1/test/assets/test1.js000066400000000000000000000000061301464672100205270ustar00rootroot00000000000000test1 gulp-sourcemaps-1.9.1/test/assets/test2.js000066400000000000000000000000061301464672100205300ustar00rootroot00000000000000test2 gulp-sourcemaps-1.9.1/test/init.js000066400000000000000000000405731301464672100171450ustar00rootroot00000000000000'use strict'; var test = require('tape'); var sourcemaps = require('..'); var File = require('vinyl'); var ReadableStream = require('stream').Readable; var path = require('path'); var fs = require('fs'); var hookStd = require('hook-std'); var debug = require('debug-fabulous')(); var sourceContent = fs.readFileSync(path.join(__dirname, 'assets/helloworld.js')).toString(); var sourceContentCSS = fs.readFileSync(path.join(__dirname, 'assets/test.css')).toString(); function makeFile() { return new File({ cwd: __dirname, base: path.join(__dirname, 'assets'), path: path.join(__dirname, 'assets', 'helloworld.js'), contents: new Buffer(sourceContent) }); } function makeNullFile() { var junkBuffer = new Buffer([]); junkBuffer.toString = function() { return null; }; return new File({ cwd: __dirname, base: path.join(__dirname, 'assets'), path: path.join(__dirname, 'assets', 'helloworld.js'), contents: junkBuffer }); } function makeStreamFile() { return new File({ cwd: __dirname, base: path.join(__dirname, 'assets'), path: path.join(__dirname, 'assets', 'helloworld.js'), contents: new ReadableStream() }); } function makeFileWithInlineSourceMap() { return new File({ cwd: __dirname, base: path.join(__dirname, 'assets'), path: path.join(__dirname, 'assets', 'all.js'), contents: new Buffer('console.log("line 1.1"),console.log("line 1.2"),console.log("line 2.1"),console.log("line 2.2");\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxsLmpzIiwic291cmNlcyI6WyJ0ZXN0MS5qcyIsInRlc3QyLmpzIl0sIm5hbWVzIjpbImNvbnNvbGUiLCJsb2ciXSwibWFwcGluZ3MiOiJBQUFBQSxRQUFBQyxJQUFBLFlBQ0FELFFBQUFDLElBQUEsWUNEQUQsUUFBQUMsSUFBQSxZQUNBRCxRQUFBQyxJQUFBIiwic291cmNlc0NvbnRlbnQiOlsiY29uc29sZS5sb2coJ2xpbmUgMS4xJyk7XG5jb25zb2xlLmxvZygnbGluZSAxLjInKTtcbiIsImNvbnNvbGUubG9nKCdsaW5lIDIuMScpO1xuY29uc29sZS5sb2coJ2xpbmUgMi4yJyk7Il0sInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9') }); } function makeFileCSS() { return new File({ cwd: __dirname, base: path.join(__dirname, 'assets'), path: path.join(__dirname, 'assets', 'test.css'), contents: new Buffer(sourceContentCSS) }); } test('init: should pass through when file is null', function(t) { // Begin inner conflict with self here.. // nmccready: // // // bliss: Turning debug on here clutters the test output; // but, having debug off in portions results in not having 100% test coverage. // // touche: If we demand 100% coverage, then we need clutter logging :_( // // partial-bliss: The alternative is to have ignore cover statements on some of the logging. // touche: However, those logging statements could potentially fail debug.save('gulp-sourcemaps:init'); debug.enable(debug.load()); // end inner conflict var file = new File(); var pipeline = sourcemaps.init(); pipeline.on('data', function(data) { t.ok(data, 'should pass something through'); t.ok(data instanceof File, 'should pass a vinyl file through'); t.ok(!data.sourceMap, 'should not add a source map object'); t.deepEqual(data, file, 'should not change file'); t.end(); }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('init: should emit an error if file content is a stream', function(t) { var pipeline = sourcemaps.init(); pipeline.on('data', function() { t.fail('should emit an error'); t.end(); }).on('error', function() { t.ok('should emit an error'); t.end(); }).write(makeStreamFile()); }); test('init: should add an empty source map', function(t) { var pipeline = sourcemaps.init(); pipeline.on('data', function(data) { t.ok(data, 'should pass something through'); t.ok(data instanceof File, 'should pass a vinyl file through'); t.ok(data.sourceMap, 'should add a source map object'); t.equal(String(data.sourceMap.version), '3', 'should have version 3'); t.equal(data.sourceMap.sources[0], 'helloworld.js', 'should add file to sources'); t.equal(data.sourceMap.sourcesContent[0], sourceContent, 'should add file content to sourcesContent'); t.deepEqual(data.sourceMap.names, [], 'should add empty names'); t.equal(data.sourceMap.mappings, '', 'should add empty mappings'); t.end(); }).on('error', function() { t.fail('emitted error'); t.end(); }).write(makeFile()); }); test('init: should add a valid source map if wished', function(t) { var pipeline = sourcemaps.init({identityMap: true}); pipeline.on('data', function(data) { t.ok(data, 'should pass something through'); t.ok(data instanceof File, 'should pass a vinyl file through'); t.ok(data.sourceMap, 'should add a source map object'); t.equal(String(data.sourceMap.version), '3', 'should have version 3'); t.equal(data.sourceMap.sources[0], 'helloworld.js', 'should add file to sources'); t.equal(data.sourceMap.sourcesContent[0], sourceContent, 'should add file content to sourcesContent'); t.deepEqual(data.sourceMap.names, [ 'helloWorld', 'console', 'log' ], 'should add correct names'); t.equal(data.sourceMap.mappings, 'AAAA,YAAY;;AAEZ,SAASA,UAAU,CAAC,EAAE;IAClBC,OAAO,CAACC,GAAG,CAAC,cAAc,CAAC;AAC/B', 'should add correct mappings'); t.end(); }).on('error', function() { t.fail('emitted error'); t.end(); }).write(makeFile()); }); test('init: should add a valid source map for css if wished', function(t) { var pipeline = sourcemaps.init({identityMap: true}); pipeline.on('data', function(data) { t.ok(data, 'should pass something through'); t.ok(data instanceof File, 'should pass a vinyl file through'); t.ok(data.sourceMap, 'should add a source map object'); t.equal(String(data.sourceMap.version), '3', 'should have version 3'); t.equal(data.sourceMap.sources[0], 'test.css', 'should add file to sources'); t.equal(data.sourceMap.sourcesContent[0], sourceContentCSS, 'should add file content to sourcesContent'); t.deepEqual(data.sourceMap.names, [], 'should add correct names'); t.equal(data.sourceMap.mappings, 'CAAC;GACE;GACA', 'should add correct mappings'); t.end(); }).on('error', function() { t.fail('emitted error'); t.end(); }).write(makeFileCSS()); }); test('init: should import an existing inline source map', function(t) { var pipeline = sourcemaps.init({loadMaps: true}); pipeline.on('data', function(data) { t.ok(data, 'should pass something through'); t.ok(data instanceof File, 'should pass a vinyl file through'); t.ok(data.sourceMap, 'should add a source map object'); t.notOk(/sourceMappingURL/.test(data.contents.toString()), 'should not have sourcemapping in data.contents'); t.equal(String(data.sourceMap.version), '3', 'should have version 3'); t.deepEqual(data.sourceMap.sources, [ 'test1.js', 'test2.js' ], 'should have right sources'); t.deepEqual(data.sourceMap.sourcesContent, [ 'console.log(\'line 1.1\');\nconsole.log(\'line 1.2\');\n', 'console.log(\'line 2.1\');\nconsole.log(\'line 2.2\');' ], 'should have right sourcesContent'); t.equal(data.sourceMap.mappings, 'AAAAA,QAAAC,IAAA,YACAD,QAAAC,IAAA,YCDAD,QAAAC,IAAA,YACAD,QAAAC,IAAA', 'should have right mappings'); t.end(); }).on('error', function() { t.fail('emitted error'); t.end(); }).write(makeFileWithInlineSourceMap()); }); test('init: should load external source map file referenced in comment with the \/\/# syntax', function(t) { var file = makeFile(); file.contents = new Buffer(sourceContent + '\n//# sourceMappingURL=helloworld2.js.map'); var pipeline = sourcemaps.init({loadMaps: true}); pipeline.on('data', function(data) { t.ok(data.sourceMap, 'should add a source map object'); t.equal(String(data.sourceMap.version), '3', 'should have version 3'); t.deepEqual(data.sourceMap.sources, ['helloworld2.js'], 'should have right sources'); t.deepEqual(data.sourceMap.sourcesContent, ['source content from source map'], 'should have right sourcesContent'); t.equal(data.sourceMap.mappings, '', 'should have right mappings'); t.end(); }).write(file); }); test('init: should remove source map comment with the \/\/# syntax', function(t) { var file = makeFile(); file.contents = new Buffer(sourceContent + '\n//# sourceMappingURL=helloworld2.js.map'); var pipeline = sourcemaps.init({loadMaps: true}); pipeline.on('data', function(data) { t.notOk(/sourceMappingURL/.test(data.contents.toString()), 'should not have sourcemapping'); t.end(); }).write(file); }); test('init: should load external source map file referenced in comment with the \/*# *\/ syntax', function(t) { var file = makeFile(); file.contents = new Buffer(sourceContent + '\n/*# sourceMappingURL=helloworld2.js.map */'); var pipeline = sourcemaps.init({loadMaps: true}); pipeline.on('data', function(data) { t.ok(data.sourceMap, 'should add a source map object'); t.equal(String(data.sourceMap.version), '3', 'should have version 3'); t.deepEqual(data.sourceMap.sources, ['helloworld2.js'], 'should have right sources'); t.deepEqual(data.sourceMap.sourcesContent, ['source content from source map'], 'should have right sourcesContent'); t.equal(data.sourceMap.mappings, '', 'should have right mappings'); t.end(); }).write(file); }); test('init: should remove source map comment with the \/\/# syntax', function(t) { var file = makeFile(); file.contents = new Buffer(sourceContent + '\n/*# sourceMappingURL=helloworld2.js.map */'); var pipeline = sourcemaps.init({loadMaps: true}); pipeline.on('data', function(data) { t.notOk(/sourceMappingURL/.test(data.contents.toString()), 'should not have sourcemapping'); t.end(); }).write(file); }); test('init: should load external source map if no source mapping comment', function(t) { var file = makeFile(); file.path = file.path.replace('helloworld.js', 'helloworld2.js'); var pipeline = sourcemaps.init({loadMaps: true}); pipeline.on('data', function(data) { t.ok(data.sourceMap, 'should add a source map object'); t.equal(String(data.sourceMap.version), '3', 'should have version 3'); t.deepEqual(data.sourceMap.sources, ['helloworld2.js'], 'should have right sources'); t.deepEqual(data.sourceMap.sourcesContent, ['source content from source map'], 'should have right sourcesContent'); t.equal(data.sourceMap.mappings, '', 'should have right mappings'); t.end(); }).write(file); }); test('init: should load external source map and add sourceContent if missing', function(t) { var file = makeFile(); file.contents = new Buffer(sourceContent + '\n//# sourceMappingURL=helloworld3.js.map'); var pipeline = sourcemaps.init({loadMaps: true}); pipeline.on('data', function(data) { t.ok(data.sourceMap, 'should add a source map object'); t.equal(String(data.sourceMap.version), '3', 'should have version 3'); t.deepEqual(data.sourceMap.sources, [ 'helloworld.js', 'test1.js' ], 'should have right sources'); t.deepEqual(data.sourceMap.sourcesContent, [ file.contents.toString(), 'test1\n' ], 'should have right sourcesContent'); t.equal(data.sourceMap.mappings, '', 'should have right mappings'); t.end(); }).write(file); }); test('init: should not throw when source file for sourceContent not found', function(t) { var file = makeFile(); file.contents = new Buffer(sourceContent + '\n//# sourceMappingURL=helloworld4.js.map'); var pipeline = sourcemaps.init({loadMaps: true}); pipeline.on('data', function(data) { t.ok(data.sourceMap, 'should add a source map object'); t.equal(String(data.sourceMap.version), '3', 'should have version 3'); t.deepEqual(data.sourceMap.sources, [ 'helloworld.js', 'missingfile' ], 'should have right sources'); t.deepEqual(data.sourceMap.sourcesContent, [ file.contents.toString(), null ], 'should have right sourcesContent'); t.equal(data.sourceMap.mappings, '', 'should have right mappings'); t.end(); }).write(file); }); // vinyl 2.X breaks this spec, not exactly sure why but it is due to the following commit // https://github.com/gulpjs/vinyl/commit/ece4abf212c83aa3e2613c57a4a0fe96171d5755 test('init: should use unix style paths in sourcemap', function(t) { var file = makeFile(); file.base = file.cwd; var pipeline = sourcemaps.init(); pipeline.on('data', function(data) { t.equal(data.sourceMap.file, 'assets/helloworld.js', 'should have right file'); t.deepEqual(data.sourceMap.sources, ['assets/helloworld.js'], 'should have right sources'); t.end(); }).write(file); }); test('init: should use sourceRoot when resolving path to sources', function(t) { var file = makeFile(); file.contents = new Buffer(sourceContent + '\n//# sourceMappingURL=helloworld5.js.map'); var pipeline = sourcemaps.init({loadMaps: true}); pipeline.on('data', function(data) { t.ok(data.sourceMap, 'should add a source map object'); t.equal(String(data.sourceMap.version), '3', 'should have version 3'); t.deepEqual(data.sourceMap.sources, [ '../helloworld.js', '../test1.js' ], 'should have right sources'); t.deepEqual(data.sourceMap.sourcesContent, [ file.contents.toString(), 'test1\n' ], 'should have right sourcesContent'); t.equal(data.sourceMap.mappings, '', 'should have right mappings'); t.equal(data.sourceMap.sourceRoot, 'test', 'should have right sourceRoot'); t.end(); }).write(file); }); test('init: should not load source content if the path is a url', function(t) { var file = makeFile(); file.contents = new Buffer(sourceContent + '\n//# sourceMappingURL=helloworld6.js.map'); var pipeline = sourcemaps.init({loadMaps: true}); pipeline.on('data', function(data) { t.ok(data.sourceMap, 'should add a source map object'); t.equal(String(data.sourceMap.version), '3', 'should have version 3'); t.deepEqual(data.sourceMap.sources, [ 'helloworld.js', 'http://example2.com/test1.js' ], 'should have right sources'); t.deepEqual(data.sourceMap.sourcesContent, [null, null]); t.equal(data.sourceMap.mappings, '', 'should have right mappings'); t.end(); }).write(file); }); test('init: should pass through when file already has a source map', function(t) { var sourceMap = { version: 3, names: [], mappings: '', sources: ['test.js'], sourcesContent: ['testContent'] }; var file = makeFile(); file.sourceMap = sourceMap; var pipeline = sourcemaps.init({loadMaps: true}); pipeline.on('data', function(data) { t.ok(data, 'should pass something through'); t.ok(data instanceof File, 'should pass a vinyl file through'); t.equal(data.sourceMap, sourceMap, 'should not change the source map'); t.deepEqual(data, file, 'should not change file'); t.end(); }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('init: handle null contents', function(t) { var pipeline = sourcemaps.init({addComment: true}); pipeline.on('data', function(data) { t.ok(data, 'should pass something through'); t.ok(data instanceof File, 'should pass a vinyl file through'); t.ok(data.sourceMap, 'should add a source map object'); t.equal(String(data.sourceMap.version), '3', 'should have version 3'); t.equal(data.sourceMap.sources[0], 'helloworld.js', 'should add file to sources'); t.equal(data.sourceMap.sourcesContent[0], null, 'should add file content to sourcesContent'); t.deepEqual(data.sourceMap.names, [], 'should add empty names'); t.equal(data.sourceMap.mappings, '', 'should add empty mappings'); t.end(); }).on('error', function() { t.fail('emitted error'); t.end(); }).write(makeNullFile()); }); //should always be last as disabling a debug namespace does not work test('init: should output an error message if debug option is set and sourceContent is missing', function(t) { var file = makeFile(); file.contents = new Buffer(sourceContent + '\n//# sourceMappingURL=helloworld4.js.map'); var history = []; console.log('HOOKING'); var unhook = hookStd.stderr(function(s) { history.push(s); }); var pipeline = sourcemaps.init({loadMaps: true, debug: true}); pipeline.on('data', function() { unhook(); var hasRegex = function(regex){ return function(s){ return regex.test(s); }; }; t.ok( history.some( hasRegex(/No source content for \"missingfile\". Loading from file./)), 'should log missing source content'); t.ok(history.some(hasRegex(/source file not found: /)), 'should warn about missing file'); t.end(); }).write(file); }); gulp-sourcemaps-1.9.1/test/integration.js000066400000000000000000000042061301464672100205160ustar00rootroot00000000000000'use strict'; var gulp = require('gulp'); var test = require('tape'); var $ = require('..'); var PLUGIN_NAME = require('../src/utils').PLUGIN_NAME; var debug = require('debug-fabulous')()(PLUGIN_NAME + ':test:integration'); var join = require('path').join; var fs = require('fs'); var sourceContent = fs.readFileSync(join(__dirname, 'assets/helloworld.js')).toString(); debug('running'); test('creates inline mapping', function(t) { gulp.src(join(__dirname, './assets/helloworld.js')) .pipe($.init()) .pipe($.write()) // .pipe(gulp.dest('tmp')) .on('data', function(data) { t.ok(data.sourceMap, 'should add a source map object'); t.deepEqual( data.contents.toString(), sourceContent + "\n//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJoZWxsb3dvcmxkLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gaGVsbG9Xb3JsZCgpIHtcbiAgICBjb25zb2xlLmxvZygnSGVsbG8gd29ybGQhJyk7XG59XG4iXSwiZmlsZSI6ImhlbGxvd29ybGQuanMifQ==\n", 'file should be sourcemapped' ); t.end(); }) .on('error', function() { t.fail('emitted error'); t.end(); }) .on('close', function() { t.end(); }); }); test('creates re-uses existing mapping', function(t) { gulp.src(join(__dirname, './assets/helloworld.map.js')) .pipe($.init({loadMaps:true})) .pipe($.write()) // .pipe(gulp.dest('tmp')) .on('data', function(data) { t.ok(data.sourceMap, 'should add a source map object'); t.ok(!!data.sourceMap.preExisting, 'should know the sourcemap pre-existed'); t.deepEqual( data.contents.toString(), sourceContent + "\n//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJoZWxsb3dvcmxkLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gaGVsbG9Xb3JsZCgpIHtcbiAgICBjb25zb2xlLmxvZygnSGVsbG8gd29ybGQhJyk7XG59XG4iXSwiZmlsZSI6ImhlbGxvd29ybGQuanMifQ==", 'file should be sourcemapped' ); t.end(); }) .on('error', function() { t.fail('emitted error'); t.end(); }) .on('close', function() { t.end(); }); }); gulp-sourcemaps-1.9.1/test/publish.js000066400000000000000000000014021301464672100176340ustar00rootroot00000000000000'use strict'; var test = require('tape'); var exec = require('child_process').exec; function cleanUp(cb) { return exec('rm -rf ./tmp', cb); } function makeTestPackage(cb) { return exec('./scripts/mockPublish', cb); } // with regards to averting npm publishing disasters https://github.com/floridoo/gulp-sourcemaps/issues/246 test('publish: can load a published version', function(t) { // return t.fail("mock fail"); cleanUp(function() { makeTestPackage(function() { try { // attempt to load a packed / unpacked potential deployed version require('../tmp/package/index'); } catch (error){ t.fail(error); } finally{ cleanUp(function() { t.end(); }); } }); }); }); gulp-sourcemaps-1.9.1/test/write.js000066400000000000000000000532751301464672100173370ustar00rootroot00000000000000'use strict'; var test = require('tape'); var sourcemaps = require('..'); var File = require('vinyl'); var ReadableStream = require('stream').Readable; var path = require('path'); var fs = require('fs'); var hookStd = require('hook-std'); var debug = require('debug-fabulous')(); var assign = require('object-assign'); var utils = require('../src/utils'); var sourceContent = fs.readFileSync(path.join(__dirname, 'assets/helloworld.js')).toString(); var mappedContent = fs.readFileSync(path.join(__dirname, 'assets/helloworld.map.js')).toString(); function makeSourceMap(custom) { var obj = { version: 3, file: 'helloworld.js', names: [], mappings: '', sources: ['helloworld.js'], sourcesContent: [sourceContent] }; if (custom) assign(obj,custom); return obj; } function base64JSON(object) { return 'data:application/json;charset=utf8;base64,' + new Buffer(JSON.stringify(object)).toString('base64'); } function makeFile(custom) { var file = new File({ cwd: __dirname, base: path.join(__dirname, 'assets'), path: path.join(__dirname, 'assets', 'helloworld.js'), contents: new Buffer(sourceContent) }); file.sourceMap = makeSourceMap(custom); return file; } function makeMappedFile() { var file = new File({ cwd: __dirname, base: path.join(__dirname, 'assets'), path: path.join(__dirname, 'assets', 'helloworld.map.js'), contents: new Buffer(mappedContent) }); file.sourceMap = makeSourceMap({preExisting:utils.getPreExisting(mappedContent)}); return file; } function makeNestedFile() { var file = new File({ cwd: __dirname, base: path.join(__dirname, 'assets'), path: path.join(__dirname, 'assets', 'dir1', 'dir2', 'helloworld.js'), contents: new Buffer(sourceContent) }); file.sourceMap = makeSourceMap(); return file; } function makeStreamFile() { var file = new File({ cwd: __dirname, base: path.join(__dirname, 'assets'), path: path.join(__dirname, 'assets', 'helloworld.js'), contents: new ReadableStream() }); file.sourceMap = {}; return file; } test('write: should pass through when file is null', function(t) { var file = new File(); var pipeline = sourcemaps.write(); pipeline.on('data', function(data) { t.ok(data, 'should pass something through'); t.ok(data instanceof File, 'should pass a vinyl file through'); t.deepEqual(data, file, 'should not change file'); t.equal(data.contents, null, 'should not change file content'); t.end(); }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('write: should pass through when file has no source map', function(t) { var file = makeFile(); delete file.sourceMap; var pipeline = sourcemaps.write(); pipeline.on('data', function(data) { t.ok(data, 'should pass something through'); t.ok(data instanceof File, 'should pass a vinyl file through'); t.deepEqual(data, file, 'should not change file'); t.equal(String(data.contents), sourceContent, 'should not change file content'); t.end(); }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('write: should emit an error if file content is a stream', function(t) { var pipeline = sourcemaps.write(); pipeline.on('data', function() { t.fail('should emit an error'); t.end(); }).on('error', function() { t.ok('should emit an error'); t.end(); }).write(makeStreamFile()); }); test('write: should write an inline source map', function(t) { var file = makeFile(); var pipeline = sourcemaps.write(); pipeline.on('data', function(data) { t.ok(data, 'should pass something through'); t.ok(data instanceof File, 'should pass a vinyl file through'); t.deepEqual(data, file, 'should not change file'); t.equal(String(data.contents), sourceContent + '\n//# sourceMappingURL=' + base64JSON(data.sourceMap) + '\n', 'should add source map as comment'); t.end(); }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('write: should use CSS comments if CSS file', function(t) { var file = makeFile(); file.path = file.path.replace('.js', '.css'); var pipeline = sourcemaps.write(); pipeline.on('data', function(data) { t.equal(String(data.contents), sourceContent + '\n/*# sourceMappingURL=' + base64JSON(data.sourceMap) + ' */\n', 'should add source map with CSS comment'); t.end(); }).write(file); }); test('write: should write no comment if not JS or CSS file', function(t) { var file = makeFile(); file.path = file.path.replace('.js', '.txt'); var pipeline = sourcemaps.write(); pipeline.on('data', function(data) { t.equal(String(data.contents), sourceContent); t.end(); }).write(file); }); test('write: should detect whether a file uses \\n or \\r\\n and follow the existing style', function(t) { var file = makeFile(); file.contents = new Buffer(file.contents.toString().replace(/\n/g, '\r\n')); var pipeline = sourcemaps.write(); pipeline.on('data', function(data) { t.ok(data, 'should pass something through'); t.equal(String(data.contents), sourceContent.replace(/\n/g, '\r\n') + '\r\n//# sourceMappingURL=' + base64JSON(data.sourceMap) + '\r\n', 'should add source map as comment'); t.end(); }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('write: preExisting', function(t) { var file = makeMappedFile(); file.contents = new Buffer(file.contents.toString()); sourcemaps.write({preExisting:true}) .on('data', function(data) { t.ok(data, 'should pass something through'); t.ok(!!data.sourceMap.preExisting, 'should mark as preExisting'); t.equal( String(data.contents), mappedContent,'should add source map as comment'); t.end(); }) .on('error', function() { t.fail('emitted error'); t.end(); }) .write(file); }); test('write: should write external map files', function(t) { var file = makeFile(); var pipeline = sourcemaps.write('../maps', {destPath: 'dist'}); var fileCount = 0; var outFiles = []; var sourceMap; pipeline.on('data', function(data) { outFiles.push(data); fileCount++; if (fileCount == 2) { outFiles.reverse().map(function(data) { if (data.path === path.join(__dirname, 'assets/helloworld.js')) { sourceMap = data.sourceMap; t.ok(data instanceof File, 'should pass a vinyl file through'); t.deepEqual(data, file, 'should not change file'); t.equal(String(data.contents), sourceContent + '\n//# sourceMappingURL=../maps/helloworld.js.map\n', 'should add a comment referencing the source map file'); t.equal(sourceMap.file, '../dist/helloworld.js'); } else { t.ok(data instanceof File, 'should pass a vinyl file through'); t.equal(data.path, path.join(__dirname, 'maps/helloworld.js.map')); t.deepEqual(JSON.parse(data.contents), sourceMap, 'should have the file\'s source map as content'); t.equal(data.stat.isFile(), true, "should have correct stats"); t.equal(data.stat.isDirectory(), false, "should have correct stats"); t.equal(data.stat.isBlockDevice(), false, "should have correct stats"); t.equal(data.stat.isCharacterDevice(), false, "should have correct stats"); t.equal(data.stat.isSymbolicLink(), false, "should have correct stats"); t.equal(data.stat.isFIFO(), false, "should have correct stats"); t.equal(data.stat.isSocket(), false, "should have correct stats"); } }); t.end(); } }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('write:clone - should keep original file history', function(t) { var file = makeFile(); var pipeline = sourcemaps.write('../maps', {destPath: 'dist'}); var outFiles = []; var fileCount = 0; pipeline .on('data', function(data) { outFiles.push(data); fileCount++; if (fileCount == 2) { outFiles.reverse().map(function (data) { if (data.path === path.join(__dirname, 'maps/helloworld.js.map')) { t.equal(data.history[0], path.join(__dirname, 'assets', 'helloworld.js'), 'should keep file history'); } }); t.end(); } }) .on('error', function() { t.fail('emitted error'); t.end(); }) .write(file); }); test('write: should allow to rename map file', function(t) { var file = makeFile(); var pipeline = sourcemaps.write('../maps', { mapFile: function(mapFile) { return mapFile.replace('.js.map', '.map'); }, destPath: 'dist' }); var fileCount = 0; var outFiles = []; var sourceMap; pipeline.on('data', function(data) { outFiles.push(data); fileCount++; if (fileCount == 2) { outFiles.reverse().map(function(data) { if (data.path === path.join(__dirname, 'assets/helloworld.js')) { sourceMap = data.sourceMap; t.ok(data instanceof File, 'should pass a vinyl file through'); t.deepEqual(data, file, 'should not change file'); t.equal(String(data.contents), sourceContent + '\n//# sourceMappingURL=../maps/helloworld.map\n', 'should add a comment referencing the source map file'); t.equal(sourceMap.file, '../dist/helloworld.js'); } else { t.ok(data instanceof File, 'should pass a vinyl file through'); t.equal(data.path, path.join(__dirname, 'maps/helloworld.map')); t.deepEqual(JSON.parse(data.contents), sourceMap, 'should have the file\'s source map as content'); } }); t.end(); } }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('write: should create shortest path to map in file comment', function(t) { var file = makeNestedFile(); var pipeline = sourcemaps.write('dir1/maps'); var fileCount = 0; var outFiles = []; pipeline.on('data', function(data) { outFiles.push(data); fileCount++; if (fileCount == 2) { outFiles.reverse().map(function(data) { if (data.path === path.join(__dirname, 'assets/dir1/dir2/helloworld.js')) { t.equal(String(data.contents), sourceContent + '\n//# sourceMappingURL=../maps/dir1/dir2/helloworld.js.map\n', 'should add a comment referencing the source map file'); } }); t.end(); } }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('write: should write no comment with option addComment=false', function(t) { var file = makeFile(); var pipeline = sourcemaps.write({addComment: false}); pipeline.on('data', function(data) { t.equal(String(data.contents), sourceContent, 'should not change file content'); t.end(); }).write(file); }); test('write: should not include source content with option includeContent=false', function(t) { var file = makeFile(); var pipeline = sourcemaps.write({includeContent: false}); pipeline.on('data', function(data) { t.equal(data.sourceMap.sourcesContent, undefined, 'should not have source content'); t.end(); }).write(file); }); test('write: should fetch missing sourceContent', function(t) { var file = makeFile(); delete file.sourceMap.sourcesContent; var pipeline = sourcemaps.write(); pipeline.on('data', function(data) { t.notEqual(data.sourceMap.sourcesContent, undefined, 'should have source content'); t.deepEqual(data.sourceMap.sourcesContent, [sourceContent], 'should have correct source content'); t.end(); }).write(file); }); test('write: should not throw when unable to fetch missing sourceContent', function(t) { var file = makeFile(); file.sourceMap.sources[0] += '.invalid'; delete file.sourceMap.sourcesContent; var pipeline = sourcemaps.write(); pipeline.on('data', function(data) { t.notEqual(data.sourceMap.sourcesContent, undefined, 'should have source content'); t.deepEqual(data.sourceMap.sourcesContent, [], 'should have correct source content'); t.end(); }).write(file); }); test('write: should set the sourceRoot by option sourceRoot', function(t) { var file = makeFile(); var pipeline = sourcemaps.write({sourceRoot: '/testSourceRoot'}); pipeline.on('data', function(data) { t.equal(data.sourceMap.sourceRoot, '/testSourceRoot', 'should set sourceRoot'); t.end(); }).write(file); }); test('write: should set the sourceRoot by option sourceRoot, as a function', function(t) { var file = makeFile(); var pipeline = sourcemaps.write({ sourceRoot: function() { return '/testSourceRoot'; } }); pipeline.on('data', function(data) { t.equal(data.sourceMap.sourceRoot, '/testSourceRoot', 'should set sourceRoot'); t.end(); }).write(file); }); test('write: should automatically determine sourceRoot if destPath is set', function(t) { var file = makeNestedFile(); var pipeline = sourcemaps.write('.', { destPath: 'dist', includeContent: false }); var fileCount = 0; var outFiles = []; pipeline.on('data', function(data) { outFiles.push(data); fileCount++; if (fileCount == 2) { outFiles.reverse().map(function(data) { if (data.path === path.join(__dirname, 'assets/dir1/dir2/helloworld.js')) { t.equal(data.sourceMap.sourceRoot, '../../../assets', 'should set correct sourceRoot'); t.equal(data.sourceMap.file, 'helloworld.js'); } else { t.equal(data.path, path.join(__dirname, 'assets/dir1/dir2/helloworld.js.map')); } }); t.end(); } }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('write: should interpret relative path in sourceRoot as relative to destination', function(t) { var file = makeNestedFile(); var pipeline = sourcemaps.write('.', {sourceRoot: '../src'}); var fileCount = 0; var outFiles = []; pipeline.on('data', function(data) { outFiles.push(data); fileCount++; if (fileCount == 2) { outFiles.reverse().map(function(data) { if (data.path === path.join(__dirname, 'assets/dir1/dir2/helloworld.js')) { t.equal(data.sourceMap.sourceRoot, '../../../src', 'should set relative sourceRoot'); t.equal(data.sourceMap.file, 'helloworld.js'); } else { t.equal(data.path, path.join(__dirname, 'assets/dir1/dir2/helloworld.js.map')); } }); t.end(); } }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('write: should interpret relative path in sourceRoot as relative to destination (part 2)', function(t) { var file = makeNestedFile(); var pipeline = sourcemaps.write('.', {sourceRoot: ''}); var fileCount = 0; var outFiles = []; pipeline.on('data', function(data) { outFiles.push(data); fileCount++; if (fileCount == 2) { outFiles.reverse().map(function(data) { if (data.path === path.join(__dirname, 'assets/dir1/dir2/helloworld.js')) { t.equal(data.sourceMap.sourceRoot, '../..', 'should set relative sourceRoot'); t.equal(data.sourceMap.file, 'helloworld.js'); } else { t.equal(data.path, path.join(__dirname, 'assets/dir1/dir2/helloworld.js.map')); } }); t.end(); } }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('write: should interpret relative path in sourceRoot as relative to destination (part 3)', function(t) { var file = makeNestedFile(); var pipeline = sourcemaps.write('maps', {sourceRoot: '../src'}); var fileCount = 0; var outFiles = []; pipeline.on('data', function(data) { outFiles.push(data); fileCount++; if (fileCount == 2) { outFiles.reverse().map(function(data) { if (data.path === path.join(__dirname, 'assets/dir1/dir2/helloworld.js')) { t.equal(data.sourceMap.sourceRoot, '../../../../src', 'should set relative sourceRoot'); t.equal(data.sourceMap.file, '../../../dir1/dir2/helloworld.js'); } else { t.equal(data.path, path.join(__dirname, 'assets/maps/dir1/dir2/helloworld.js.map')); } }); t.end(); } }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('write: should interpret relative path in sourceRoot as relative to destination (part 4)', function(t) { var file = makeNestedFile(); var pipeline = sourcemaps.write('../maps', { sourceRoot: '../src', destPath: 'dist' }); var fileCount = 0; var outFiles = []; pipeline.on('data', function(data) { outFiles.push(data); fileCount++; if (fileCount == 2) { outFiles.reverse().map(function(data) { if (data.path === path.join(__dirname, 'assets/dir1/dir2/helloworld.js')) { t.equal(data.sourceMap.sourceRoot, '../../../src', 'should set relative sourceRoot'); t.equal(data.sourceMap.file, '../../../dist/dir1/dir2/helloworld.js'); } else { t.equal(data.path, path.join(__dirname, 'maps/dir1/dir2/helloworld.js.map')); } }); t.end(); } }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); test('write: should accept a sourceMappingURLPrefix', function(t) { var file = makeFile(); var pipeline = sourcemaps.write('../maps', {sourceMappingURLPrefix: 'https://asset-host.example.com'}); pipeline.on('data', function(data) { if (/helloworld\.js$/.test(data.path)) { t.equal(String(data.contents).match(/sourceMappingURL.*\n$/)[0], 'sourceMappingURL=https://asset-host.example.com/maps/helloworld.js.map\n'); t.end(); } }).write(file); }); test('write: should accept a sourceMappingURLPrefix, as a function', function(t) { var file = makeFile(); var pipeline = sourcemaps.write('../maps', { sourceMappingURLPrefix: function() { return 'https://asset-host.example.com'; } }); pipeline.on('data', function(data) { if (/helloworld\.js$/.test(data.path)) { t.equal(String(data.contents).match(/sourceMappingURL.*\n$/)[0], 'sourceMappingURL=https://asset-host.example.com/maps/helloworld.js.map\n'); t.end(); } }).write(file); }); test('write: should invoke sourceMappingURLPrefix every time', function(t) { var times = 0; var pipeline = sourcemaps.write('../maps', { sourceMappingURLPrefix: function() { ++times; return 'https://asset-host.example.com/' + times; } }); pipeline.on('data', function(data) { if (/helloworld\.js$/.test(data.path)) { t.equal(String(data.contents).match(/sourceMappingURL.*\n$/)[0], 'sourceMappingURL=https://asset-host.example.com/' + times + '/maps/helloworld.js.map\n'); if (times >= 3) { t.end(); return; } pipeline.write(makeFile()); } }).write(makeFile()); }); test('write: null as sourceRoot should not set the sourceRoot', function(t) { var file = makeFile(); var pipeline = sourcemaps.write({sourceRoot: null}); pipeline.on('data', function(data) { t.equal(data.sourceMap.sourceRoot, undefined, 'should not set sourceRoot'); t.end(); }).write(file); }); test('write: function returning null as sourceRoot should not set the sourceRoot', function(t) { var file = makeFile(); var pipeline = sourcemaps.write({ sourceRoot: function() { return null; } }); pipeline.on('data', function(data) { t.equal(data.sourceMap.sourceRoot, undefined, 'should set sourceRoot'); t.end(); }).write(file); }); test('write: empty string as sourceRoot should be kept', function(t) { var file = makeFile(); var pipeline = sourcemaps.write({sourceRoot: ''}); pipeline.on('data', function(data) { t.equal(data.sourceMap.sourceRoot, '', 'should keep empty string as sourceRoot'); t.end(); }).write(file); }); test('write: should be able to fully control sourceMappingURL by the option sourceMappingURL', function(t) { var file = makeNestedFile(); var pipeline = sourcemaps.write('../aaa/bbb/', { sourceMappingURL: function(file) { return 'http://maps.example.com/' + file.relative + '.map'; } }); pipeline.on('data', function(data) { if (/helloworld\.js$/.test(data.path)) { t.equal(String(data.contents), sourceContent + '\n//# sourceMappingURL=http://maps.example.com/dir1/dir2/helloworld.js.map\n', 'should add source map comment with custom url'); t.end(); } }).write(file); }); test('write: should allow to change sources', function(t) { var file = makeFile(); var pipeline = sourcemaps.write({ mapSources: function(sourcePath) { return '../src/' + sourcePath; } }); pipeline.on('data', function(data) { t.deepEqual(data.sourceMap.sources, ['../src/helloworld.js'], 'should have the correct sources'); t.end(); }).on('error', function() { t.fail('emitted error'); t.end(); }).write(file); }); //should always be last as disabling a debug namespace does not work test('write: should output an error message if debug option is set and sourceContent is missing', function(t) { debug.save('gulp-sourcemaps:write'); debug.enable(debug.load()); var file = makeFile(); file.sourceMap.sources[0] += '.invalid'; delete file.sourceMap.sourcesContent; var history = []; var unhook = hookStd.stderr(function(s) { history.push(s); }); var pipeline = sourcemaps.write({debug: true}); var hasRegex = function(regex){ return function(s){ return regex.test(s); }; }; pipeline.on('data', function() { unhook(); debug.save(null); // console.log(JSON.stringify(history)) t.ok(history.some(hasRegex(/No source content for "helloworld.js.invalid". Loading from file./)), 'should log missing source content'); t.ok(history.some(hasRegex(/source file not found: /)), 'should warn about missing file'); t.end(); }).write(file); });