pax_global_header00006660000000000000000000000064137527737740014540gustar00rootroot0000000000000052 comment=2bcfcbb11085d1d6ef54239abd156bf7a7e72cfe gulp-sourcemaps-3.0.0/000077500000000000000000000000001375277377400146665ustar00rootroot00000000000000gulp-sourcemaps-3.0.0/.editorconfig000066400000000000000000000003261375277377400173440ustar00rootroot00000000000000# http://editorconfig.org root = true [*] indent_style = space indent_size = 2 charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true end_of_line = lf [*.md] trim_trailing_whitespace = false gulp-sourcemaps-3.0.0/.eslintignore000066400000000000000000000000151375277377400173650ustar00rootroot00000000000000test/assets/ gulp-sourcemaps-3.0.0/.eslintrc000066400000000000000000000002461375277377400165140ustar00rootroot00000000000000{ "extends": "gulp", "rules": { "max-depth": [1, 5], "max-statements": [1, 50], "max-len": [1, { "code": 140 }], "no-constant-condition": 0 } } gulp-sourcemaps-3.0.0/.gitattributes000066400000000000000000000000161375277377400175560ustar00rootroot00000000000000* text eol=lf gulp-sourcemaps-3.0.0/.gitignore000066400000000000000000000011551375277377400166600ustar00rootroot00000000000000# Logs logs *.log # Runtime data pids *.pid *.seed # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directory # Commenting this out is preferred by some people, see # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- node_modules # Users Environment Variables .lock-wscript # Garbage files .DS_Store *.lock gulp-sourcemaps-3.0.0/.npmrc000066400000000000000000000000371375277377400160060ustar00rootroot00000000000000package-lock=false audit=false gulp-sourcemaps-3.0.0/.travis.yml000066400000000000000000000001551375277377400170000ustar00rootroot00000000000000sudo: false language: node_js node_js: - '12' - '10' - '8' - '6' after_script: - npm run coveralls gulp-sourcemaps-3.0.0/LICENSE.md000066400000000000000000000013571375277377400163000ustar00rootroot00000000000000## 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-3.0.0/README.md000066400000000000000000000333741375277377400161570ustar00rootroot00000000000000# gulp-sourcemaps [![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Travis Build Status][travis-image]][travis-url] [![AppVeyor Build Status][appveyor-image]][appveyor-url] [![Coveralls Status][coveralls-image]][coveralls-url] Sourcemap support for gulpjs. ### Usage All the examples here works with Gulp 4. To see examples related to Gulp 3, [you can read them here](https://github.com/gulp-sourcemaps/gulp-sourcemaps/blob/v2.6.5/README.md). #### 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'); function javascript() { gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write()) .pipe(gulp.dest('dist')); }; exports.javascript = javascript; ``` 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/gulp-sourcemaps/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'); function javascript() { gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write('../maps')) .pipe(gulp.dest('dist')); }; exports.javascript = javascript; ``` #### 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'); function javascript() { gulp.src('src/**/*.js') .pipe(sourcemaps.init({loadMaps: true})) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write()) .pipe(gulp.dest('dist')); }; exports.javascript = javascript; ``` #### 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'); function javascript() { gulp.src('src/**/*.js') .pipe(sourcemaps.init({largeFile: true})) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write()) .pipe(gulp.dest('dist')); }; exports.javascript = javascript; ``` #### 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'); function javascript() { 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')); }; exports.javascript = javascript; ``` #### Alter `sources` property on sourcemaps The exported `mapSources` method 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 and the original vinyl file. Example: ```javascript function javascript() { var stream = gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) // be careful with the sources returned otherwise contents might not be loaded properly .pipe(sourcemaps.mapSources(function(sourcePath, file) { // source paths are prefixed with '../src/' return '../src/' + sourcePath; })) .pipe(sourcemaps.write('../maps') .pipe(gulp.dest('public/scripts')); }; exports.javascript = javascript; ``` #### Generate Identity Sourcemap The exported `identityMap` method allows you 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.__ Example: ```javascript function javascript() { var stream = gulp.src('src/**/*.js') .pipe(sourcemaps.init()) // An identity sourcemap will be generated at this step .pipe(sourcemaps.identityMap()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write('../maps') .pipe(gulp.dest('public/scripts')); }; exports.javascript = javascript; ``` ### 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` __This option is deprecated. Upgrade to use our [`sourcemap.identityMap`](#generate-identity-sourcemap) API.__ ### 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 function javascript() { var stream = gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write('../maps', {addComment: false})) .pipe(gulp.dest('dist')); }; exports.javascript = javascript; ``` - `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 function javascript() { var stream = gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write({includeContent: false, sourceRoot: '/src'})) .pipe(gulp.dest('dist')); }; exports.javascript = javascript; ``` Example (using a function): ```javascript function javascript() { 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')); }; exports.javascript = javascript; ``` Example (relative path): ```javascript function javascript() { var stream = gulp.src('src/**/*.js') .pipe(sourcemaps.init()) .pipe(plugin1()) .pipe(plugin2()) .pipe(sourcemaps.write('.', {includeContent: false, sourceRoot: '../src'})) .pipe(gulp.dest('dist')); }; exports.javascript = javascript; ``` 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 sub path 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 function javascript() { 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')); }; exports.javascript = javascript; ``` 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 function javascript() { 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')); }; exports.javascript = javascript; ``` 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 function javascript() { 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')); }; exports.javascript = javascript; ``` - `mapSources` __This option is deprecated. Upgrade to use our [`sourcemap.mapSources`](#alter-sources-property-on-sourcemaps) API.__ - `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/gulp-sourcemaps/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/gulp-sourcemaps/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); }; ``` - **Verify sourcemaps are 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(); ``` ### Debugging All debugging output relies on [visionmedia/debug](https://github.com/visionmedia/debug). Follow the directions to set the environment variable `$DEBUG`. For a few examples of debug you could use: ```sh DEBUG='gulp-sourcemaps:*' #everything DEBUG='gulp-sourcemaps:init' #init/index.js DEBUG='gulp-sourcemaps:init:*' #init/index.internals.js DEBUG='gulp-sourcemaps:write:' #write/index.js DEBUG='gulp-sourcemaps:write:*' #write/index.internals.js DEBUG='gulp-sourcemaps:write:,gulp-sourcemaps:init:**' #write/index.internals.js and init/index.internals.js ``` [downloads-image]: http://img.shields.io/npm/dm/gulp-sourcemaps.svg [npm-url]: https://www.npmjs.com/package/gulp-sourcemaps [npm-image]: http://img.shields.io/npm/v/gulp-sourcemaps.svg [travis-url]: https://travis-ci.org/gulp-sourcemaps/gulp-sourcemaps [travis-image]: http://img.shields.io/travis/gulp-sourcemaps/gulp-sourcemaps.svg?label=travis-ci [appveyor-url]: https://ci.appveyor.com/project/phated/gulp-sourcemaps [appveyor-image]: https://img.shields.io/appveyor/ci/phated/gulp-sourcemaps.svg?label=appveyor [coveralls-url]: https://coveralls.io/r/gulp-sourcemaps/gulp-sourcemaps [coveralls-image]: http://img.shields.io/coveralls/gulp-sourcemaps/gulp-sourcemaps/master.svg gulp-sourcemaps-3.0.0/appveyor.yml000066400000000000000000000006631375277377400172630ustar00rootroot00000000000000# http://www.appveyor.com/docs/appveyor-yml # http://www.appveyor.com/docs/lang/nodejs-iojs environment: matrix: # node.js - nodejs_version: "6" - nodejs_version: "8" - nodejs_version: "10" - nodejs_version: "12" install: - ps: Install-Product node $env:nodejs_version - npm install test_script: - node --version - npm --version - cmd: npm test build: off # build version format version: "{build}" gulp-sourcemaps-3.0.0/index.js000066400000000000000000000003251375277377400163330ustar00rootroot00000000000000'use strict'; module.exports = { init: require('./src/init'), write: require('./src/write'), mapSources: require('@gulp-sourcemaps/map-sources'), identityMap: require('@gulp-sourcemaps/identity-map'), }; gulp-sourcemaps-3.0.0/package.json000066400000000000000000000031021375277377400171500ustar00rootroot00000000000000{ "name": "gulp-sourcemaps", "version": "3.0.0", "description": "Sourcemap support for gulpjs.", "homepage": "http://github.com/gulp-sourcemaps/gulp-sourcemaps", "repository": "git://github.com/gulp-sourcemaps/gulp-sourcemaps.git", "main": "index.js", "scripts": { "lint": "eslint .", "pretest": "npm run lint", "test": "mocha --async-only", "cover": "istanbul cover _mocha --report lcovonly", "coveralls": "npm run cover && istanbul-coveralls" }, "keywords": [ "gulpplugin", "gulp", "source maps", "sourcemaps" ], "author": "Florian Reiterer ", "license": "ISC", "dependencies": { "@gulp-sourcemaps/identity-map": "^2.0.1", "@gulp-sourcemaps/map-sources": "^1.0.0", "acorn": "^6.4.1", "convert-source-map": "^1.0.0", "css": "^3.0.0", "debug-fabulous": "^1.0.0", "detect-newline": "^2.0.0", "graceful-fs": "^4.0.0", "source-map": "^0.6.0", "strip-bom-string": "^1.0.0", "through2": "^2.0.0" }, "devDependencies": { "bootstrap": "^3.4.1", "eslint": "^5.16.0", "eslint-config-gulp": "^3.0.1", "expect": "^1.20.2", "gulp": "^4.0.0", "gulp-concat": "^2.6.1", "gulp-if": "^2.0.2", "gulp-less": "^3.0.0", "gulp-load-plugins": "^1.5.0", "hook-std": "0.2.X", "istanbul": "^0.4.3", "istanbul-coveralls": "^1.0.3", "mississippi": "1.X", "mocha": "^3.5.3", "object-assign": "^4.1.1", "rimraf": "^2.6.3", "vinyl": "^2.2.0" }, "files": [ "index.js", "src" ], "engines": { "node": ">= 6" } } gulp-sourcemaps-3.0.0/scripts/000077500000000000000000000000001375277377400163555ustar00rootroot00000000000000gulp-sourcemaps-3.0.0/scripts/mockPublish000077500000000000000000000001571375277377400205660ustar00rootroot00000000000000#!/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-3.0.0/scripts/publish000077500000000000000000000002761375277377400177560ustar00rootroot00000000000000#!/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-3.0.0/src/000077500000000000000000000000001375277377400154555ustar00rootroot00000000000000gulp-sourcemaps-3.0.0/src/debug.js000066400000000000000000000001271375277377400171010ustar00rootroot00000000000000module.exports = require('debug-fabulous').spawnable(require('../package.json').name); gulp-sourcemaps-3.0.0/src/init/000077500000000000000000000000001375277377400164205ustar00rootroot00000000000000gulp-sourcemaps-3.0.0/src/init/index.internals.js000066400000000000000000000100071375277377400220610ustar00rootroot00000000000000'use strict'; var utils = require('../utils'); var rootDebug = require('../debug'); var convert = require('convert-source-map'); var stripBom = require('strip-bom-string'); var urlRegex = utils.urlRegex; var fs = require('graceful-fs'); var path = require('path'); var unixStylePath = utils.unixStylePath; var exceptionToString = utils.exceptionToString; module.exports = function(options, file, fileContent) { function loadMaps() { var sources = { path: '', map: null, content: fileContent, preExistingComment: null, }; _getInlineSources(sources); if (!sources.map) { // ahh not inline, so try file _getFileSources(sources); } _fixSources(sources); return sources; } function _fixSources(sources) { var debug = rootDebug.spawn('init:internals:loadMaps:_fixSources'); // fix source paths and sourceContent for imported source map if (sources.map) { sources.map.sourcesContent = sources.map.sourcesContent || []; sources.map.sources.forEach(function(source, i) { if (source.match(urlRegex)) { sources.map.sourcesContent[i] = sources.map.sourcesContent[i] || null; return; } var absPath = path.resolve(sources.path, source); sources.map.sources[i] = unixStylePath(path.relative(file.base, absPath)); if (!sources.map.sourcesContent[i]) { var sourceContent = null; if (sources.map.sourceRoot) { if (sources.map.sourceRoot.match(urlRegex)) { sources.map.sourcesContent[i] = null; return; } absPath = path.resolve(sources.path, sources.map.sourceRoot, source); } // if current file: use content if (absPath === file.path) { sourceContent = sources.content; } else { // attempt load content from file try { debug(function() { return 'No source content for "' + source + '". Loading from file.'; }); sourceContent = stripBom(fs.readFileSync(absPath, 'utf8')); } catch (e) { debug(function() { return 'warn: source file not found: ' + absPath; }); } } sources.map.sourcesContent[i] = sourceContent; } }); // remove source map comment from source file.contents = new Buffer(sources.content, 'utf8'); } } function _getInlineSources(sources) { var debug = rootDebug.spawn('init:internals:loadMaps:_getInlineSources'); sources.preExistingComment = utils.getInlinePreExisting(sources.content); // Try to read inline source map sources.map = convert.fromSource(sources.content, options.largeFile); if (!sources.map) { return sources; } sources.map = sources.map.toObject(); // sources in map are relative to the source file sources.path = path.dirname(file.path); if (!options.largeFile) { debug('comment REMOVED'); sources.content = convert.removeComments(sources.content); } } function _getFileSources(sources) { var debug = rootDebug.spawn('init:internals:loadMaps:_getFileSources'); // look for source map comment referencing a source map file var mapComment = convert.mapFileCommentRegex.exec(sources.content); var mapFile; if (mapComment) { sources.preExistingComment = mapComment[1] || mapComment[2]; mapFile = path.resolve(path.dirname(file.path), sources.preExistingComment); sources.content = convert.removeMapFileComments(sources.content); // 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 sources.path = path.dirname(mapFile); try { sources.map = JSON.parse(stripBom(fs.readFileSync(mapFile, 'utf8'))); } catch (e) { debug(function() { return 'warn: external source map not found or invalid: ' + mapFile + ' ' + exceptionToString(e); }); } } return { loadMaps: loadMaps, }; }; gulp-sourcemaps-3.0.0/src/init/index.js000066400000000000000000000100721375277377400200650ustar00rootroot00000000000000'use strict'; var utils = require('../utils'); var unixStylePath = utils.unixStylePath; var through = require('through2'); var path = require('path'); var acorn = require('acorn'); var SourceMapGenerator = require('source-map').SourceMapGenerator; var css = require('css'); var initInternals = require('./index.internals'); /** * Initialize source mapping chain */ function init(options) { var debug = require('../debug').spawn('init'); function sourceMapInit(file, encoding, callback) { // 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(utils.PLUGIN_NAME + '-init: Streaming not supported')); } if (options === undefined) { options = {}; } debug(function() { return options; }); var fileContent = file.contents.toString(); var sourceMap, preExistingComment; var internals = initInternals(options, file, fileContent); if (options.loadMaps) { var result = internals.loadMaps(); sourceMap = result.map; fileContent = result.content; preExistingComment = result.preExistingComment; } if (!sourceMap && options.identityMap) { debug(function() { return '**identityMap option is deprecated, update to use sourcemap.identityMap stream**'; }); 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 (preExistingComment !== null && typeof preExistingComment !== 'undefined') { sourceMap.preExistingComment = preExistingComment; } sourceMap.file = unixStylePath(file.relative); file.sourceMap = sourceMap; this.push(file); callback(); } return through.obj(sourceMapInit); } module.exports = init; gulp-sourcemaps-3.0.0/src/utils.js000066400000000000000000000043761375277377400171650ustar00rootroot00000000000000'use strict'; var path = require('path'); var 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').spawn('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. */ function sourceMapUrlRegEx() { return /\/\/# sourceMappingURL=.*/g; } var commentFormatters = { css: function cssCommentFormatter(preLine, newline, url) { return preLine + '/*# sourceMappingURL=' + url + ' */' + newline; }, js: function jsCommentFormatter(preLine, newline, url) { return preLine + '//# sourceMappingURL=' + url + newline; }, default: function defaultFormatter() { return ''; }, }; function getCommentFormatter(file) { var extension = file.relative.split('.').pop(); var fileContents = file.contents.toString(); var newline = detectNewline.graceful(fileContents || ''); var commentFormatter = commentFormatters.default; if (file.sourceMap.preExistingComment) { commentFormatter = (commentFormatters[extension] || commentFormatter).bind(undefined, '', newline); debug(function() { return 'preExistingComment commentFormatter ' + commentFormatter.name; }); } else { commentFormatter = (commentFormatters[extension] || commentFormatter).bind(undefined, newline, newline); } debug(function() { return 'commentFormatter ' + commentFormatter.name; }); return commentFormatter; } function getInlinePreExisting(fileContent) { if (sourceMapUrlRegEx().test(fileContent)) { debug(function() { return 'has preExisting'; }); return fileContent.match(sourceMapUrlRegEx())[0]; } } function exceptionToString(exception) { return exception.message || ''; } module.exports = { unixStylePath: unixStylePath, PLUGIN_NAME: PLUGIN_NAME, urlRegex: urlRegex, sourceMapUrlRegEx: sourceMapUrlRegEx, getCommentFormatter: getCommentFormatter, getInlinePreExisting: getInlinePreExisting, exceptionToString: exceptionToString, }; gulp-sourcemaps-3.0.0/src/write/000077500000000000000000000000001375277377400166075ustar00rootroot00000000000000gulp-sourcemaps-3.0.0/src/write/index.internals.js000066400000000000000000000154141375277377400222570ustar00rootroot00000000000000'use strict'; module.exports = function(destPath, options) { var utils = require('../utils'); var unixStylePath = utils.unixStylePath; var fs = require('graceful-fs'); var path = require('path'); var stripBom = require('strip-bom-string'); var rootDebug = require('../debug').spawn('write:internals'); rootDebug(function() { return 'options'; }); rootDebug(function() { return options; }); function setSourceRoot(file) { var debug = rootDebug.spawn('setSourceRoot'); var sourceMap = file.sourceMap; if (typeof options.sourceRoot === 'function') { debug(function() { return 'is function'; }); sourceMap.sourceRoot = options.sourceRoot(file); } else { debug(function() { return 'from options'; }); sourceMap.sourceRoot = options.sourceRoot; } if (sourceMap.sourceRoot === null) { debug(function() { return 'undefined'; }); sourceMap.sourceRoot = undefined; } } function mapSources(file) { var debug = rootDebug.spawn('mapSources'); // NOTE: make sure source mapping happens after content has been loaded if (options.mapSources && typeof options.mapSources === 'function') { debug(function() { return '**Option is deprecated, update to use sourcemap.mapSources stream**'; }); debug(function() { return 'function'; }); file.sourceMap.sources = file.sourceMap.sources.map(function(filePath) { return options.mapSources(filePath, file); }); return; } debug(function() { return 'file.path: ' + file.path; }); debug(function() { return 'file.cwd: ' + file.cwd; }); debug(function() { return 'file.base: ' + file.base; }); file.sourceMap.sources = file.sourceMap.sources.map(function(filePath) { // keep the references files like ../node_modules within the sourceRoot debug(function() { return 'filePath: ' + filePath; }); if (options.mapSourcesAbsolute === true) { debug(function() { return 'mapSourcesAbsolute'; }); if (!file.dirname) { debug(function() { return '!file.dirname'; }); filePath = path.join(file.base, filePath).replace(file.cwd, ''); } else { debug(function() { return 'file.dirname: ' + file.dirname; }); filePath = path.resolve(file.dirname, filePath).replace(file.cwd, ''); } } return unixStylePath(filePath); }); } function loadContent(file) { var debug = rootDebug.spawn('loadContent'); var sourceMap = file.sourceMap; if (options.includeContent) { sourceMap.sourcesContent = sourceMap.sourcesContent || []; // load missing source content for (var i = 0; i < sourceMap.sources.length; i++) { if (!sourceMap.sourcesContent[i]) { var sourcePath = path.resolve(file.base, sourceMap.sources[i]); try { debug('No source content for "' + sourceMap.sources[i] + '". Loading from file.'); sourceMap.sourcesContent[i] = stripBom(fs.readFileSync(sourcePath, 'utf8')); } catch (e) { debug('source file not found: ' + sourcePath); } } } } else { delete sourceMap.sourcesContent; } } function mapDestPath(file, stream) { var debug = rootDebug.spawn('mapDestPath'); var sourceMap = file.sourceMap; var comment; var commentFormatter = utils.getCommentFormatter(file); 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)); } } var 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; }, }; stream.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(function() { return 'destPath comment'; }); comment = commentFormatter(unixStylePath(sourceMapPathRelative)); if (options.sourceMappingURL && typeof options.sourceMappingURL === 'function') { debug(function() { return 'options.sourceMappingURL comment'; }); comment = commentFormatter(options.sourceMappingURL(file)); } } // append source map comment if (options.addComment) { file.contents = Buffer.concat([file.contents, new Buffer(comment)]); } } return { setSourceRoot: setSourceRoot, loadContent: loadContent, mapSources: mapSources, mapDestPath: mapDestPath, }; }; gulp-sourcemaps-3.0.0/src/write/index.js000066400000000000000000000033101375277377400202510ustar00rootroot00000000000000'use strict'; var utils = require('../utils'); var through = require('through2'); var unixStylePath = utils.unixStylePath; var internalsInit = require('./index.internals'); /** * Write the source map * * @param options options to change the way the source map is written * */ function write(destPath, options) { var debug = require('../debug').spawn('write'); debug(function() { return 'destPath'; }); debug(function() { return destPath; }); debug(function() { return 'original options';}); debug(function() { return options; }); 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 'derrived options'; }); debug(function() { return options; }); var internals = internalsInit(destPath, options); function sourceMapWrite(file, encoding, callback) { if (file.isNull() || !file.sourceMap) { this.push(file); return callback(); } if (file.isStream()) { return callback(new Error(utils.PLUGIN_NAME + '-write: Streaming not supported')); } // fix paths if Windows style paths file.sourceMap.file = unixStylePath(file.relative); internals.setSourceRoot(file); internals.loadContent(file); internals.mapSources(file); internals.mapDestPath(file, this); this.push(file); callback(); } return through.obj(sourceMapWrite); } module.exports = write; gulp-sourcemaps-3.0.0/test/000077500000000000000000000000001375277377400156455ustar00rootroot00000000000000gulp-sourcemaps-3.0.0/test/.eslintrc000066400000000000000000000001031375277377400174630ustar00rootroot00000000000000{ "extends": "gulp/test", "rules": { "no-console": 0 } } gulp-sourcemaps-3.0.0/test/assets/000077500000000000000000000000001375277377400171475ustar00rootroot00000000000000gulp-sourcemaps-3.0.0/test/assets/helloworld.js000066400000000000000000000001121375277377400216520ustar00rootroot00000000000000'use strict'; function helloWorld() { console.log('Hello world!'); } gulp-sourcemaps-3.0.0/test/assets/helloworld.map.js000066400000000000000000000006131375277377400224340ustar00rootroot00000000000000'use strict'; function helloWorld() { console.log('Hello world!'); } //# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJoZWxsb3dvcmxkLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gaGVsbG9Xb3JsZCgpIHtcbiAgICBjb25zb2xlLmxvZygnSGVsbG8gd29ybGQhJyk7XG59XG4iXSwiZmlsZSI6ImhlbGxvd29ybGQuanMifQ== gulp-sourcemaps-3.0.0/test/assets/helloworld2.js000066400000000000000000000001151375277377400217370ustar00rootroot00000000000000'use strict'; function helloWorld2() { console.log('Hello world 2!'); } gulp-sourcemaps-3.0.0/test/assets/helloworld2.js.map000066400000000000000000000002431375277377400225150ustar00rootroot00000000000000{ "version":3, "file":"helloworld2.js", "names":[], "mappings":"", "sources":["helloworld2.js"], "sourcesContent":["source content from source map"] } gulp-sourcemaps-3.0.0/test/assets/helloworld3.js.map000066400000000000000000000001731375277377400225200ustar00rootroot00000000000000{ "version": 3, "file": "helloworld.js", "names": [], "mappings": "", "sources": ["helloworld.js", "test1.js"] } gulp-sourcemaps-3.0.0/test/assets/helloworld4.js.map000066400000000000000000000001761375277377400225240ustar00rootroot00000000000000{ "version": 3, "file": "helloworld.js", "names": [], "mappings": "", "sources": ["helloworld.js", "missingfile"] } gulp-sourcemaps-3.0.0/test/assets/helloworld5.js.map000066400000000000000000000002311375277377400225150ustar00rootroot00000000000000{ "version": 3, "file": "helloworld.js", "names": [], "mappings": "", "sources": ["../helloworld.js", "../test1.js"], "sourceRoot": "test" } gulp-sourcemaps-3.0.0/test/assets/helloworld6.js.map000066400000000000000000000002661375277377400225260ustar00rootroot00000000000000{ "version": 3, "file": "helloworld.js", "names": [], "mappings": "", "sources": ["helloworld.js", "http://example2.com/test1.js"], "sourceRoot": "http://example.com/" } gulp-sourcemaps-3.0.0/test/assets/helloworld7.js000066400000000000000000000001151375277377400217440ustar00rootroot00000000000000'use strict'; function helloWorld2() { console.log('Hello world 7!'); } gulp-sourcemaps-3.0.0/test/assets/index.html000066400000000000000000000005061375277377400211450ustar00rootroot00000000000000 Open Browser gulp-sourcemaps-3.0.0/test/assets/test.css000066400000000000000000000000541375277377400206370ustar00rootroot00000000000000body { background: #eee; color: #888; } gulp-sourcemaps-3.0.0/test/assets/test.css.map000066400000000000000000000002001375277377400214040ustar00rootroot00000000000000{ "version": 3, "file": "test.css", "names": [], "mappings": "", "sources": ["../test.css"], "sourceRoot": "test" } gulp-sourcemaps-3.0.0/test/assets/test.less000066400000000000000000000002671375277377400210230ustar00rootroot00000000000000@import "../../node_modules/bootstrap/less/bootstrap.less"; body { background: #eee; color: #888; .some-class { font-size: 12px; } div { background: black; } } gulp-sourcemaps-3.0.0/test/assets/test1.js000066400000000000000000000000061375277377400205410ustar00rootroot00000000000000test1 gulp-sourcemaps-3.0.0/test/assets/test2.js000066400000000000000000000000061375277377400205420ustar00rootroot00000000000000test2 gulp-sourcemaps-3.0.0/test/assets/test3.js000066400000000000000000000000261375277377400205450ustar00rootroot00000000000000console.log('three'); gulp-sourcemaps-3.0.0/test/assets/test4.js000066400000000000000000000000251375277377400205450ustar00rootroot00000000000000console.log('four'); gulp-sourcemaps-3.0.0/test/init.test.js000066400000000000000000000417211375277377400201310ustar00rootroot00000000000000'use strict'; var expect = require('expect'); // BEGIN PRE-HOOK of debug var debug = require('debug-fabulous')(); var miss = require('mississippi'); var from = miss.from; var pipe = miss.pipe; var concat = miss.concat; var ignoreLogTests = process.argv.indexOf('--ignore-log-tests') !== -1; if (!ignoreLogTests) { debug.save('gulp-sourcemaps:*'); debug.enable(debug.load()); } // END PRE-HOOK of debug (must be loaded before our main module (sourcemaps)) var sourcemaps = require('..'); var File = require('vinyl'); var hookStd = require('hook-std'); var helpers = require('./test-helpers'); describe('init', function() { it('should pass through when file is null', function(done) { // end inner conflict var file = new File(); function assert(results) { var data = results[0]; expect(data).toExist(); expect(data instanceof File).toEqual(true); expect(data.sourceMap).toNotExist(); expect(data).toEqual(file); } pipe([ from.obj([file]), sourcemaps.init(), concat(assert), ], done); }); it('should emit an error if file content is a stream', function(done) { var file = helpers.makeStreamFile(); function assert(err) { expect(err).toExist(); done(); } pipe([ from.obj([file]), sourcemaps.init(), concat(), ], assert); }); it('should add an empty source map', function(done) { var file = helpers.makeFile(); function assert(results) { var data = results[0]; expect(data).toExist(); expect(data instanceof File).toEqual(true); expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources[0]).toEqual('helloworld.js'); expect(data.sourceMap.sourcesContent[0]).toEqual(helpers.sourceContent); expect(data.sourceMap.names).toEqual([]); expect(data.sourceMap.mappings).toEqual(''); } pipe([ from.obj([file]), sourcemaps.init(), concat(assert), ], done); }); it('should add a valid source map if wished', function(done) { var file = helpers.makeFile(); function assert(results) { var data = results[0]; expect(data).toExist(); expect(data instanceof File).toEqual(true); expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources[0]).toEqual('helloworld.js'); expect(data.sourceMap.sourcesContent[0]).toEqual(helpers.sourceContent); expect(data.sourceMap.names).toEqual(['helloWorld', 'console', 'log']); expect(data.sourceMap.mappings).toEqual('AAAA,YAAY;;AAEZ,SAASA,UAAU,CAAC,EAAE;IAClBC,OAAO,CAACC,GAAG,CAAC,cAAc,CAAC;AAC/B'); } pipe([ from.obj([file]), sourcemaps.init({ identityMap: true }), concat(assert), ], done); }); it('should add a valid source map for css if wished', function(done) { var file = helpers.makeFileCSS(); function assert(results) { var data = results[0]; expect(data).toExist(); expect(data instanceof File).toEqual(true); expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources[0]).toEqual('test.css'); expect(data.sourceMap.sourcesContent[0]).toEqual(helpers.sourceContentCSS); expect(data.sourceMap.names).toEqual([]); expect(data.sourceMap.mappings).toEqual('CAAC;GACE;GACA'); } pipe([ from.obj([file]), sourcemaps.init({ identityMap: true }), concat(assert), ], done); }); it('init: can replace `identityMap` option with sourcemap.identityMap stream (js file)', function(done) { var file = helpers.makeFile(); function assert(results) { var data = results[0]; expect(data).toExist(); expect(data instanceof File).toEqual(true); expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources[0]).toEqual('helloworld.js'); expect(data.sourceMap.sourcesContent[0]).toEqual(helpers.sourceContent); expect(data.sourceMap.names).toEqual(['helloWorld', 'console', 'log']); expect(data.sourceMap.mappings).toEqual('AAAA,YAAY;;AAEZ,SAASA,UAAU,CAAC,EAAE;IAClBC,OAAO,CAACC,GAAG,CAAC,cAAc,CAAC;AAC/B'); } pipe([ from.obj([file]), sourcemaps.init(), sourcemaps.identityMap(), concat(assert), ], done); }); it('can replace `identityMap` option with sourcemap.identityMap stream (css file)', function(done) { var file = helpers.makeFileCSS(); function assert(results) { var data = results[0]; expect(data).toExist(); expect(data instanceof File).toEqual(true); expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources[0]).toEqual('test.css'); expect(data.sourceMap.sourcesContent[0]).toEqual(helpers.sourceContentCSS); expect(data.sourceMap.names).toEqual([]); expect(data.sourceMap.mappings).toEqual('AAAA;EACE,gBAAgB;EAChB,WAAW;AACb'); } pipe([ from.obj([file]), sourcemaps.init(), sourcemaps.identityMap(), concat(assert), ], done); }); it('should import an existing inline source map', function(done) { var file = helpers.makeFileWithInlineSourceMap(); function assert(results) { var data = results[0]; expect(data).toExist(); expect(data instanceof File).toEqual(true); expect(data.sourceMap).toExist(); expect(/sourceMappingURL/.test(data.contents.toString())).toEqual(false); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources).toEqual(['test1.js', 'test2.js']); expect(data.sourceMap.sourcesContent).toEqual([ 'console.log(\'line 1.1\');\nconsole.log(\'line 1.2\');\n', 'console.log(\'line 2.1\');\nconsole.log(\'line 2.2\');', ]); expect(data.sourceMap.mappings).toEqual('AAAAA,QAAAC,IAAA,YACAD,QAAAC,IAAA,YCDAD,QAAAC,IAAA,YACAD,QAAAC,IAAA'); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); it('should load external source map file referenced in comment with the //# syntax', function(done) { var file = helpers.makeFile(); file.contents = new Buffer(helpers.sourceContent + '\n//# sourceMappingURL=helloworld2.js.map'); function assert(results) { var data = results[0]; expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources).toEqual(['helloworld2.js']); expect(data.sourceMap.sourcesContent).toEqual(['source content from source map']); expect(data.sourceMap.mappings).toEqual(''); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); it('css: should load external source map file referenced in comment with the //*# syntax', function(done) { var file = helpers.makeFileCSS(); file.contents = new Buffer(helpers.sourceContentCSS + '\n/*# sourceMappingURL=test.css.map */'); function assert(results) { var data = results[0]; expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources).toEqual(['../test.css']); expect(data.sourceMap.sourcesContent).toEqual(['body {\n background: #eee;\n color: #888;\n}\n\n']); expect(data.sourceMap.mappings).toEqual(''); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); it('should remove source map comment with the //# syntax', function(done) { var file = helpers.makeFile(); file.contents = new Buffer(helpers.sourceContent + '\n//# sourceMappingURL=helloworld2.js.map'); function assert(results) { var data = results[0]; expect(/sourceMappingURL/.test(data.contents.toString())).toEqual(false); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); it('init: css: should remove source map comment with the //*# syntax', function(done) { var file = helpers.makeFileCSS(); file.contents = new Buffer(helpers.sourceContentCSS + '\n/*# sourceMappingURL=test.css.map */'); function assert(results) { var data = results[0]; var actualContents = data.contents.toString(); expect(/sourceMappingURL/.test(actualContents)).toEqual(false); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); it('should load external source map file referenced in comment with the /*# */ syntax', function(done) { var file = helpers.makeFile(); file.contents = new Buffer(helpers.sourceContent + '\n/*# sourceMappingURL=helloworld2.js.map */'); function assert(results) { var data = results[0]; expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources).toEqual(['helloworld2.js']); expect(data.sourceMap.sourcesContent).toEqual(['source content from source map']); expect(data.sourceMap.mappings).toEqual(''); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); it('should remove source map comment with the //# syntax', function(done) { var file = helpers.makeFile(); file.contents = new Buffer(helpers.sourceContent + '\n/*# sourceMappingURL=helloworld2.js.map */'); function assert(results) { var data = results[0]; expect(/sourceMappingURL/.test(data.contents.toString())).toEqual(false); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); it('should load external source map if no source mapping comment', function(done) { var file = helpers.makeFile(); file.path = file.path.replace('helloworld.js', 'helloworld2.js'); function assert(results) { var data = results[0]; expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources).toEqual(['helloworld2.js']); expect(data.sourceMap.sourcesContent).toEqual(['source content from source map']); expect(data.sourceMap.mappings).toEqual(''); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); it('should load external source map and add sourceContent if missing', function(done) { var file = helpers.makeFile(); file.contents = new Buffer(helpers.sourceContent + '\n//# sourceMappingURL=helloworld3.js.map'); function assert(results) { var data = results[0]; expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources).toEqual(['helloworld.js', 'test1.js']); expect(data.sourceMap.sourcesContent).toEqual([file.contents.toString(), 'test1\n']); expect(data.sourceMap.mappings).toEqual(''); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); it('should not throw when source file for sourceContent not found', function(done) { var file = helpers.makeFile(); file.contents = new Buffer(helpers.sourceContent + '\n//# sourceMappingURL=helloworld4.js.map'); function assert(results) { var data = results[0]; expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources).toEqual(['helloworld.js', 'missingfile']); expect(data.sourceMap.sourcesContent).toEqual([file.contents.toString(), null]); expect(data.sourceMap.mappings).toEqual(''); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); // 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 it('should use unix style paths in sourcemap', function(done) { var file = helpers.makeFile(); file.base = file.cwd; function assert(results) { var data = results[0]; expect(data.sourceMap.file).toEqual('assets/helloworld.js'); expect(data.sourceMap.sources).toEqual(['assets/helloworld.js']); } pipe([ from.obj([file]), sourcemaps.init(), concat(assert), ], done); }); it('should use sourceRoot when resolving path to sources', function(done) { var file = helpers.makeFile(); file.contents = new Buffer(helpers.sourceContent + '\n//# sourceMappingURL=helloworld5.js.map'); function assert(results) { var data = results[0]; expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources).toEqual(['../helloworld.js', '../test1.js']); expect(data.sourceMap.sourcesContent).toEqual([file.contents.toString(), 'test1\n']); expect(data.sourceMap.mappings).toEqual(''); expect(data.sourceMap.sourceRoot).toEqual('test'); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); it('should not load source content if the path is a url', function(done) { var file = helpers.makeFile(); file.contents = new Buffer(helpers.sourceContent + '\n//# sourceMappingURL=helloworld6.js.map'); function assert(results) { var data = results[0]; expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources).toEqual(['helloworld.js', 'http://example2.com/test1.js']); expect(data.sourceMap.sourcesContent).toEqual([null, null]); expect(data.sourceMap.mappings).toEqual(''); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); it('should pass through when file already has a source map', function(done) { var sourceMap = { version: 3, names: [], mappings: '', sources: ['test.js'], sourcesContent: ['testContent'], }; var file = helpers.makeFile(); file.sourceMap = sourceMap; function assert(results) { var data = results[0]; expect(data).toExist(); expect(data instanceof File).toEqual(true); expect(data.sourceMap).toBe(sourceMap); expect(data).toBe(file); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); it('handle null contents', function(done) { var file = helpers.makeNullFile(); function assert(results) { var data = results[0]; expect(data).toExist(); expect(data instanceof File).toEqual(true); expect(data.sourceMap).toExist(); expect(String(data.sourceMap.version)).toEqual('3'); expect(data.sourceMap.sources[0]).toEqual('helloworld.js'); expect(data.sourceMap.sourcesContent[0]).toEqual(null); expect(data.sourceMap.names).toEqual([]); expect(data.sourceMap.mappings).toEqual(''); } pipe([ from.obj([file]), sourcemaps.init({ addComment: true }), concat(assert), ], done); }); if (!ignoreLogTests) { // should always be last as disabling a debug namespace does not work it('should output an error message if debug option is set and sourceContent is missing', function(done) { var file = helpers.makeFile(); file.contents = new Buffer(helpers.sourceContent + '\n//# sourceMappingURL=helloworld4.js.map'); var history = []; var unhook = hookStd.stderr(function(s) { history.push(s); }); function assert() { unhook(); var hasRegex = function(regex) { return function(s) { return regex.test(s); }; }; expect(history.some(hasRegex(/No source content for "missingfile". Loading from file./g))).toEqual(true); expect(history.some(hasRegex(/source file not found: /g))).toEqual(true); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); it('should output an error message if debug option is set, loadMaps: true, and source map file not found', function(done) { var file = helpers.makeFile(); file.contents = new Buffer(helpers.sourceContent + '\n//# sourceMappingURL=not-existent.js.map'); var history = []; var unhook = hookStd.stderr(function(s) { history.push(s); }); function assert() { unhook(); var hasRegex = function(regex) { return function(s) { return regex.test(s); }; }; expect(history.some(hasRegex(/warn: external source map not found or invalid: /g))).toEqual(true); } pipe([ from.obj([file]), sourcemaps.init({ loadMaps: true }), concat(assert), ], done); }); } }); gulp-sourcemaps-3.0.0/test/integration.test.js000066400000000000000000000202451375277377400215070ustar00rootroot00000000000000'use strict'; var expect = require('expect'); var gulp = require('gulp'); var $ = require('gulp-load-plugins')(); var sourcemaps = require('..'); var debug = require('debug-fabulous')(); var miss = require('mississippi'); var rimraf = require('rimraf'); var pipe = miss.pipe; var concat = miss.concat; var ignoreLogTests = process.argv.indexOf('--ignore-log-tests') !== -1; if (!ignoreLogTests) { debug.save('gulp-sourcemaps:*'); debug.enable(debug.load()); } var join = require('path').join; var fs = require('fs'); var sourceContent = fs.readFileSync(join(__dirname, 'assets/helloworld.js')).toString(); function base64JSON(object) { return 'data:application/json;charset=utf8;base64,' + new Buffer(JSON.stringify(object)).toString('base64'); } debug('running'); describe('integrations', function() { after(function(cb) { rimraf('./tmp', cb); }); it('combined: creates inline mapping', function(done) { function assert(results) { var data = results[0]; expect(data.sourceMap).toExist(); expect(data.contents.toString()).toEqual(sourceContent + '\n//# sourceMappingURL=' + base64JSON(data.sourceMap) + '\n'); } pipe([ gulp.src('assets/helloworld.js', { cwd: __dirname }), sourcemaps.init(), sourcemaps.write(), concat(assert), ], done); }); it('combined: creates preExistingComment , no new previous line', function(done) { function assert(results) { var data = results[0]; expect(data.sourceMap).toExist(); expect(data.sourceMap.preExistingComment).toExist(); expect(data.contents.toString()).toEqual(sourceContent + '\n//# sourceMappingURL=' + base64JSON(data.sourceMap) + '\n'); } pipe([ gulp.src('assets/helloworld.map.js', { cwd: __dirname }), sourcemaps.init({ loadMaps: true }), sourcemaps.write(), concat(assert), ], done); }); it('combined mapped: concat files with final combined sourcemap file', function(done) { function assert(results) { var data = results[1]; // TODO: This might be flakey since it grabs index 1 from results expect(/index\.js$/.test(data.path)).toEqual(true); expect(/\/\/# sourceMappingURL=index.js.map/.test(data.contents.toString())).toEqual(true); expect(data.contents.toString().match(/\/\/# sourceMappingURL/g).length).toEqual(1); } pipe([ gulp.src(['assets/*.js', '!assets/test*.js', '!assets/*map.js'], { cwd: __dirname }), sourcemaps.init(), $.if('*.js', $.concat('index.js')), sourcemaps.write('.', { sourceRoot: '../../test/assets' }), concat(assert), ], done); }); it('combined: inline concatenated file', function(done) { function assert(results) { var data = results[0]; expect(/index\.js$/.test(data.path)).toEqual(true); expect(/\/\/# sourceMappingURL=data:application.*/.test(data.contents.toString())).toEqual(true); expect(data.contents.toString().match(/\/\/# sourceMappingURL/g).length).toEqual(1); } pipe([ gulp.src(['assets/*.js', '!assets/test*.js', '!assets/*map.js'], { cwd: __dirname }), sourcemaps.init(), $.if('*.js', $.concat('index.js')), sourcemaps.write({ sourceRoot: '../../test/assets' }), concat(assert), ], done); }); it('combined: less: inline concatenated file', function(done) { // note ~1000 ms is fine locally, travis needs more // note: on travis node 0.12 seems to have the brunt of the slowness this.timeout(6000); // proves that gulp-less compilation is not slow // https://github.com/gulp-sourcemaps/gulp-sourcemaps/issues/215 pipe([ gulp.src('assets/*.less', { cwd: __dirname }), sourcemaps.init(), $.if('*.less', $.less()), sourcemaps.write({ sourceRoot: '../../test/assets' }), concat(), ], done); }); it('combined: mapped preExisting', function(done) { function assert(results) { var data = results[1]; // TODO: This might be flakey since it grabs index 1 from results expect(/index\.js$/.test(data.path)).toEqual(true); expect(/\/\/# sourceMappingURL=index.js.map/.test(data.contents.toString())).toEqual(true); expect(data.contents.toString().match(/\/\/# sourceMappingURL/g).length).toEqual(1); } pipe([ // picking a file with no existing sourcemap, if we use helloworld2 it will attempt to use helloworld2.js.map gulp.src([ 'assets/helloworld7.js', // NO PRE-MAP at all 'assets/helloworld.map.js', // INLINE PRE-MAp ], { cwd: __dirname }), sourcemaps.init({ loadMaps: true }), $.if('*.js', $.concat('index.js')), sourcemaps.write('.', { sourceRoot: '../../test/assets' }), concat(assert), ], done); }); it('combined: inlined preExisting', function(done) { function assert(results) { var data = results[0]; expect(/index\.js$/.test(data.path)).toEqual(true); expect(/\/\/# sourceMappingURL=data:application.*/.test(data.contents.toString())).toEqual(true); expect(data.contents.toString().match(/\/\/# sourceMappingURL/g).length).toEqual(1); } pipe([ // picking a file with no existing sourcemap, if we use helloworld2 it will attempt to use helloworld2.js.map gulp.src([ 'assets/helloworld7.js', // NO PRE-MAP at all 'assets/helloworld.map.js', // INLINE PRE-MAp ], { cwd: __dirname }), sourcemaps.init({ loadMaps: true }), $.if('*.js', $.concat('index.js')), sourcemaps.write({ sourceRoot: '../../test/assets' }), concat(assert), ], done); }); it('combined: mapped preExisting with two tasks', function(done) { function assert(results) { var data = results[1]; // TODO: This might be flakey since it grabs index 1 from results expect(/index\.js$/.test(data.path)).toEqual(true); expect(/\/\/# sourceMappingURL=index.js.map/.test(data.contents.toString())).toEqual(true); expect(data.contents.toString().match(/\/\/# sourceMappingURL/g).length).toEqual(1); } pipe([ gulp.src('assets/helloworld7.js', { cwd: __dirname }), sourcemaps.init(), $.if('*.js', $.concat('h7.js')), sourcemaps.write('.'), gulp.dest('tmp/combined_map_preExisting_two_task/tmp'), ], function(err) { if (err) { done(err); return; } pipe([ gulp.src(['../tmp/combined_map_preExisting_two_task/tmp/h7.js', 'assets/helloworld.map.js'], { cwd: __dirname }), sourcemaps.init({ loadMaps: true }), $.if('*.js', $.concat('index.js')), sourcemaps.write('.', { sourceRoot: '../../test/assets' }), concat(assert), ], done); }); }); // - thanks @twiggy https://github.com/gulp-sourcemaps/gulp-sourcemaps/issues/270#issuecomment-271723208 it('sources: is valid with concat', function(done) { function assert(results) { var data = results[0]; // TODO: This might be flakey since it grabs index 0 from results expect(/.*\.map/.test(data.path)).toEqual(true); var contents = JSON.parse(data.contents.toString()); contents.sources.forEach(function(s, i) { expect(s).toEqual('test' + (i + 3) + '.js'); }); } pipe([ gulp.src(['assets/test3.js', 'assets/test4.js'], { cwd: __dirname }), sourcemaps.init(), $.concat('index.js'), sourcemaps.write('.'), concat(assert), ], done); }); // - thanks @twiggy https://github.com/gulp-sourcemaps/gulp-sourcemaps/issues/270#issuecomment-271723208 it('sources: mapSourcesAbsolute: is valid with concat', function(done) { function assert(results) { var data = results[0]; // TODO: This might be flakey since it grabs index 0 from results expect(/.*\.map/.test(data.path)).toEqual(true); var contents = JSON.parse(data.contents.toString()); contents.sources.forEach(function(s, i) { expect(s).toEqual('/test/assets/test' + (i + 3) + '.js'); }); } pipe([ // This changed to `test/assets/` because join isn't valid globs gulp.src(['test/assets/test3.js', 'test/assets/test4.js']), sourcemaps.init(), $.concat('index.js'), sourcemaps.write('.', { mapSourcesAbsolute: true }), concat(assert), ], done); }); }); gulp-sourcemaps-3.0.0/test/publish.test.js000066400000000000000000000015111375277377400206250ustar00rootroot00000000000000'use strict'; var os = require('os'); var exec = require('child_process').exec; var rimraf = require('rimraf'); var isWindows = (os.platform() === 'win32'); function cleanUp(cb) { rimraf('./tmp', cb); } function makeTestPackage(cb) { if (isWindows) { this.skip(); } return exec('./scripts/mockPublish', cb); } describe('mock publish', function() { beforeEach(makeTestPackage); after(cleanUp); // with regards to averting npm publishing disasters https://github.com/gulp-sourcemaps/gulp-sourcemaps/issues/246 it('can load a published version', function(done) { if (isWindows) { this.skip(); } try { // attempt to load a packed / unpacked potential deployed version require('../tmp/package/index'); } catch (error) { done(error); return; } done(); }); }); gulp-sourcemaps-3.0.0/test/test-helpers.js000066400000000000000000000046771375277377400206400ustar00rootroot00000000000000'use strict'; var fs = require('fs'); var path = require('path'); var File = require('vinyl'); var ReadableStream = require('stream').Readable; 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: Buffer.from ? Buffer.from(sourceContent) : 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() { var contents = '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'; return new File({ cwd: __dirname, base: path.join(__dirname, 'assets'), path: path.join(__dirname, 'assets', 'all.js'), contents: Buffer.from ? Buffer.from(contents) : new Buffer(contents), }); } function makeFileCSS() { return new File({ cwd: __dirname, base: path.join(__dirname, 'assets'), path: path.join(__dirname, 'assets', 'test.css'), contents: Buffer.from ? Buffer.from(sourceContentCSS) : new Buffer(sourceContentCSS), }); } module.exports = { sourceContent: sourceContent, sourceContentCSS: sourceContentCSS, makeFile: makeFile, makeFileCSS: makeFileCSS, makeNullFile: makeNullFile, makeStreamFile: makeStreamFile, makeFileWithInlineSourceMap: makeFileWithInlineSourceMap, }; gulp-sourcemaps-3.0.0/test/utils.test.js000066400000000000000000000016101375277377400203170ustar00rootroot00000000000000'use strict'; var expect = require('expect'); var utils = require('../src/utils'); describe('utils', function() { it('exceptionToString: takes message if present', function(done) { var exception = { message: 'exception message' }; var result = utils.exceptionToString(exception); expect(result).toEqual('exception message'); done(); }); it('exceptionToString: returns empty string if message is not present', function(done) { var exception = { foo: 'bar' }; var result = utils.exceptionToString(exception); expect(result).toEqual(''); done(); }); it('getCommentFormatter: gets a commenter with invalid extension', function(done) { var commenter = utils.getCommentFormatter({ relative: 'some.junk', contents: "var a = 'hello';", sourceMap: { preExistingComment: true }, }); expect(commenter).toExist(); done(); }); }); gulp-sourcemaps-3.0.0/test/write.test.js000066400000000000000000000524061375277377400203220ustar00rootroot00000000000000'use strict'; var expect = require('expect'); 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 miss = require('mississippi'); var from = miss.from; var pipe = miss.pipe; var concat = miss.concat; var ignoreLogTests = process.argv.indexOf('--ignore-log-tests') !== -1; if (!ignoreLogTests) { debug.save('gulp-sourcemaps:*'); debug.enable(debug.load()); } var assign = require('object-assign'); var utils = require('../src/utils'); var convert = require('convert-source-map'); 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({ preExistingComment: utils.getInlinePreExisting(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; } describe('write', function() { it('should pass through when file is null', function(done) { var file = new File(); function assert(results) { var data = results[0]; expect(data).toExist(); expect(data instanceof File).toEqual(true); expect(data).toBe(file); expect(data.contents).toEqual(null); } pipe([ from.obj([file]), sourcemaps.write(), concat(assert), ], done); }); it('should pass through when file has no source map', function(done) { var file = makeFile(); delete file.sourceMap; function assert(results) { var data = results[0]; expect(data).toExist(); expect(data instanceof File).toEqual(true); expect(data).toBe(file); expect(data.contents.toString()).toEqual(sourceContent); } pipe([ from.obj([file]), sourcemaps.write(), concat(assert), ], done); }); it('should emit an error if file content is a stream', function(done) { var file = makeStreamFile(); pipe([ from.obj([file]), sourcemaps.write(), concat(), ], function(err) { expect(err).toExist(); done(); }); }); it('should write an inline source map', function(done) { var file = makeFile(); function assert(results) { var data = results[0]; expect(data).toExist(); expect(data instanceof File).toEqual(true); expect(data).toBe(file); expect(data.contents.toString()).toEqual(sourceContent + '\n//# sourceMappingURL=' + base64JSON(data.sourceMap) + '\n'); } pipe([ from.obj([file]), sourcemaps.write(), concat(assert), ], done); }); it('should use CSS comments if CSS file', function(done) { var file = makeFile(); file.path = file.path.replace('.js', '.css'); function assert(results) { var data = results[0]; expect(data.contents.toString()).toEqual(sourceContent + '\n/*# sourceMappingURL=' + base64JSON(data.sourceMap) + ' */\n'); } pipe([ from.obj([file]), sourcemaps.write(), concat(assert), ], done); }); it('should write no comment if not JS or CSS file', function(done) { var file = makeFile(); file.path = file.path.replace('.js', '.txt'); function assert(results) { var data = results[0]; expect(data.contents.toString()).toEqual(sourceContent); } pipe([ from.obj([file]), sourcemaps.write(), concat(assert), ], done); }); it('should detect whether a file uses \\n or \\r\\n and follow the existing style', function(done) { var file = makeFile(); file.contents = new Buffer(file.contents.toString().replace(/\n/g, '\r\n')); function assert(results) { var data = results[0]; expect(data.contents.toString()).toEqual(sourceContent.replace(/\n/g, '\r\n') + '\r\n//# sourceMappingURL=' + base64JSON(data.sourceMap) + '\r\n'); } pipe([ from.obj([file]), sourcemaps.write(), concat(assert), ], done); }); it('preExistingComment', function(done) { var file = makeMappedFile(); file.contents = new Buffer(convert.removeComments(file.contents.toString())); function assert(results) { var data = results[0]; expect(data).toExist(); expect(data.sourceMap.preExistingComment).toExist(); expect(data.contents.toString()).toEqual(sourceContent + '\n//# sourceMappingURL=' + base64JSON(data.sourceMap) + '\n'); } pipe([ from.obj([file]), sourcemaps.write({ preExistingComment: true }), concat(assert), ], done); }); it('should write external map files', function(done) { var file = makeFile(); function assert(results) { var dataFile = results[1]; console.log('debugging', dataFile.path); expect(dataFile.path).toEqual(path.join(__dirname, 'assets/helloworld.js')); expect(dataFile instanceof File).toEqual(true); expect(dataFile).toBe(file); expect(dataFile.contents.toString()).toEqual(sourceContent + '\n//# sourceMappingURL=../maps/helloworld.js.map\n'); expect(dataFile.sourceMap.file).toEqual('../dist/helloworld.js'); var mapFile = results[0]; expect(mapFile instanceof File).toEqual(true); expect(mapFile.path).toEqual(path.join(__dirname, 'maps/helloworld.js.map')); expect(JSON.parse(mapFile.contents)).toEqual(dataFile.sourceMap); expect(mapFile.stat.isFile()).toEqual(true); expect(mapFile.stat.isDirectory()).toEqual(false); expect(mapFile.stat.isBlockDevice()).toEqual(false); expect(mapFile.stat.isCharacterDevice()).toEqual(false); expect(mapFile.stat.isSymbolicLink()).toEqual(false); expect(mapFile.stat.isFIFO()).toEqual(false); expect(mapFile.stat.isSocket()).toEqual(false); } pipe([ from.obj([file]), sourcemaps.write('../maps', { destPath: 'dist' }), concat(assert), ], done); }); it('clone - should keep original file history', function(done) { var file = makeFile(); function assert(results) { var data = results[0]; expect(data.path).toEqual(path.join(__dirname, 'maps/helloworld.js.map')); expect(data.history[0]).toEqual(path.join(__dirname, 'assets/helloworld.js')); } pipe([ from.obj([file]), sourcemaps.write('../maps', { destPath: 'dist' }), concat(assert), ], done); }); it('should allow to rename map file', function(done) { var file = makeFile(); function assert(results) { var dataFile = results[1]; expect(dataFile.path).toEqual(path.join(__dirname, 'assets/helloworld.js')); expect(dataFile instanceof File).toEqual(true); expect(dataFile).toBe(file); expect(dataFile.contents.toString()).toEqual(sourceContent + '\n//# sourceMappingURL=../maps/helloworld.map\n'); expect(dataFile.sourceMap.file).toEqual('../dist/helloworld.js'); var mapFile = results[0]; expect(mapFile instanceof File).toEqual(true); expect(mapFile.path).toEqual(path.join(__dirname, 'maps/helloworld.map')); expect(JSON.parse(mapFile.contents)).toEqual(dataFile.sourceMap); } pipe([ from.obj([file]), sourcemaps.write('../maps', { mapFile: function(mapFile) { return mapFile.replace('.js.map', '.map'); }, destPath: 'dist', }), concat(assert), ], done); }); it('should create shortest path to map in file comment', function(done) { var file = makeNestedFile(); function assert(results) { var data = results[1]; expect(data.path).toEqual(path.join(__dirname, 'assets/dir1/dir2/helloworld.js')); expect(data.contents.toString()).toEqual(sourceContent + '\n//# sourceMappingURL=../maps/dir1/dir2/helloworld.js.map\n'); } pipe([ from.obj([file]), sourcemaps.write('dir1/maps'), concat(assert), ], done); }); it('should write no comment with option addComment=false', function(done) { var file = makeFile(); function assert(results) { var data = results[0]; expect(data.contents.toString()).toEqual(sourceContent); } pipe([ from.obj([file]), sourcemaps.write({ addComment: false }), concat(assert), ], done); }); it('should not include source content with option includeContent=false', function(done) { var file = makeFile(); function assert(results) { var data = results[0]; expect(data.sourceMap.sourcesContent).toEqual(undefined); } pipe([ from.obj([file]), sourcemaps.write({ includeContent: false }), concat(assert), ], done); }); it('should fetch missing sourceContent', function(done) { var file = makeFile(); delete file.sourceMap.sourcesContent; function assert(results) { var data = results[0]; expect(data.sourceMap.sourcesContent).toExist(); expect(data.sourceMap.sourcesContent).toEqual([sourceContent]); } pipe([ from.obj([file]), sourcemaps.write(), concat(assert), ], done); }); it('should not throw when unable to fetch missing sourceContent', function(done) { var file = makeFile(); file.sourceMap.sources[0] += '.invalid'; delete file.sourceMap.sourcesContent; function assert(results) { var data = results[0]; expect(data.sourceMap.sourcesContent).toExist(); expect(data.sourceMap.sourcesContent).toEqual([]); } pipe([ from.obj([file]), sourcemaps.write(), concat(assert), ], done); }); it('should set the sourceRoot by option sourceRoot', function(done) { var file = makeFile(); function assert(results) { var data = results[0]; expect(data.sourceMap.sources).toEqual(['helloworld.js']); expect(data.sourceMap.sourceRoot).toEqual('/testSourceRoot'); } pipe([ from.obj([file]), sourcemaps.write({ sourceRoot: '/testSourceRoot' }), concat(assert), ], done); }); it('should set the mapSourcesAbsolute by option mapSourcesAbsolute', function(done) { var file = makeFile(); function assert(results) { var data = results[0]; expect(data.sourceMap.sources).toEqual(['/assets/helloworld.js']); expect(data.sourceMap.sourceRoot).toEqual('/testSourceRoot'); } pipe([ from.obj([file]), sourcemaps.write({ sourceRoot: '/testSourceRoot', mapSourcesAbsolute: true }), concat(assert), ], done); }); it('should set the sourceRoot by option sourceRoot, as a function', function(done) { var file = makeFile(); function assert(results) { var data = results[0]; expect(data.sourceMap.sourceRoot).toEqual('/testSourceRoot'); } pipe([ from.obj([file]), sourcemaps.write({ sourceRoot: function() { return '/testSourceRoot'; }, }), concat(assert), ], done); }); it('should automatically determine sourceRoot if destPath is set', function(done) { var file = makeNestedFile(); function assert(results) { var dataFile = results[1]; expect(dataFile.path).toEqual(path.join(__dirname, 'assets/dir1/dir2/helloworld.js')); expect(dataFile.sourceMap.sourceRoot).toEqual('../../../assets'); expect(dataFile.sourceMap.file).toEqual('helloworld.js'); var mapFile = results[0]; expect(mapFile.path).toEqual(path.join(__dirname, 'assets/dir1/dir2/helloworld.js.map')); } pipe([ from.obj([file]), sourcemaps.write('.', { destPath: 'dist', includeContent: false, }), concat(assert), ], done); }); it('should interpret relative path in sourceRoot as relative to destination', function(done) { var file = makeNestedFile(); function assert(results) { var dataFile = results[1]; expect(dataFile.path).toEqual(path.join(__dirname, 'assets/dir1/dir2/helloworld.js')); expect(dataFile.sourceMap.sourceRoot).toEqual('../../../src'); expect(dataFile.sourceMap.file).toEqual('helloworld.js'); var mapFile = results[0]; expect(mapFile.path).toEqual(path.join(__dirname, 'assets/dir1/dir2/helloworld.js.map')); } pipe([ from.obj([file]), sourcemaps.write('.', { sourceRoot: '../src' }), concat(assert), ], done); }); it('should interpret relative path in sourceRoot as relative to destination (part 2)', function(done) { var file = makeNestedFile(); function assert(results) { var dataFile = results[1]; expect(dataFile.path).toEqual(path.join(__dirname, 'assets/dir1/dir2/helloworld.js')); expect(dataFile.sourceMap.sourceRoot).toEqual('../..'); expect(dataFile.sourceMap.file).toEqual('helloworld.js'); var mapFile = results[0]; expect(mapFile.path).toEqual(path.join(__dirname, 'assets/dir1/dir2/helloworld.js.map')); } pipe([ from.obj([file]), sourcemaps.write('.', { sourceRoot: '' }), concat(assert), ], done); }); it('should interpret relative path in sourceRoot as relative to destination (part 3)', function(done) { var file = makeNestedFile(); function assert(results) { var dataFile = results[1]; expect(dataFile.path).toEqual(path.join(__dirname, 'assets/dir1/dir2/helloworld.js')); expect(dataFile.sourceMap.sourceRoot).toEqual('../../../../src'); expect(dataFile.sourceMap.file).toEqual('../../../dir1/dir2/helloworld.js'); var mapFile = results[0]; expect(mapFile.path).toEqual(path.join(__dirname, 'assets/maps/dir1/dir2/helloworld.js.map')); } pipe([ from.obj([file]), sourcemaps.write('maps', { sourceRoot: '../src' }), concat(assert), ], done); }); it('should interpret relative path in sourceRoot as relative to destination (part 4)', function(done) { var file = makeNestedFile(); function assert(results) { var dataFile = results[1]; expect(dataFile.path).toEqual(path.join(__dirname, 'assets/dir1/dir2/helloworld.js')); expect(dataFile.sourceMap.sourceRoot).toEqual('../../../src'); expect(dataFile.sourceMap.file).toEqual('../../../dist/dir1/dir2/helloworld.js'); var mapFile = results[0]; expect(mapFile.path).toEqual(path.join(__dirname, 'maps/dir1/dir2/helloworld.js.map')); } pipe([ from.obj([file]), sourcemaps.write('../maps', { sourceRoot: '../src', destPath: 'dist', }), concat(assert), ], done); }); it('should accept a sourceMappingURLPrefix', function(done) { var file = makeFile(); function assert(results) { var data = results[1]; expect(/helloworld\.js$/.test(data.path)).toEqual(true); expect(data.contents.toString().match(/sourceMappingURL.*\n$/)[0]).toEqual('sourceMappingURL=https://asset-host.example.com/maps/helloworld.js.map\n'); } pipe([ from.obj([file]), sourcemaps.write('../maps', { sourceMappingURLPrefix: 'https://asset-host.example.com' }), concat(assert), ], done); }); it('should accept a sourceMappingURLPrefix, as a function', function(done) { var file = makeFile(); function assert(results) { var data = results[1]; expect(/helloworld\.js$/.test(data.path)).toEqual(true); expect(data.contents.toString().match(/sourceMappingURL.*\n$/)[0]).toEqual('sourceMappingURL=https://asset-host.example.com/maps/helloworld.js.map\n'); } pipe([ from.obj([file]), sourcemaps.write('../maps', { sourceMappingURLPrefix: function() { return 'https://asset-host.example.com'; }, }), concat(assert), ], done); }); it('should invoke sourceMappingURLPrefix every time', function(done) { var times = 0; var files = [ makeFile(), makeFile(), makeFile(), ]; function assert(results) { // Only the files, not maps [results[1], results[3], results[5]].forEach(function(data, idx) { expect(/helloworld\.js$/.test(data.path)).toEqual(true); expect(data.contents.toString().match(/sourceMappingURL.*\n$/)[0]).toEqual('sourceMappingURL=https://asset-host.example.com/' + (idx + 1) + '/maps/helloworld.js.map\n'); }); } pipe([ from.obj(files), sourcemaps.write('../maps', { sourceMappingURLPrefix: function() { ++times; return 'https://asset-host.example.com/' + times; }, }), concat(assert), ], done); }); it('null as sourceRoot should not set the sourceRoot', function(done) { var file = makeFile(); function assert(results) { var data = results[0]; expect(data.sourceMap.sourceRoot).toEqual(undefined); } pipe([ from.obj([file]), sourcemaps.write({ sourceRoot: null }), concat(assert), ], done); }); it('function returning null as sourceRoot should not set the sourceRoot', function(done) { var file = makeFile(); function assert(results) { var data = results[0]; expect(data.sourceMap.sourceRoot).toEqual(undefined); } pipe([ from.obj([file]), sourcemaps.write({ sourceRoot: function() { return null; }, }), concat(assert), ], done); }); it('empty string as sourceRoot should be kept', function(done) { var file = makeFile(); function assert(results) { var data = results[0]; expect(data.sourceMap.sourceRoot).toEqual(''); } pipe([ from.obj([file]), sourcemaps.write({ sourceRoot: '' }), concat(assert), ], done); }); it('should be able to fully control sourceMappingURL by the option sourceMappingURL', function(done) { var file = makeNestedFile(); function assert(results) { var data = results[1]; expect(/helloworld\.js$/.test(data.path)).toEqual(true); expect(data.contents.toString()).toEqual(sourceContent + '\n//# sourceMappingURL=http://maps.example.com/helloworld.js.map\n'); } pipe([ from.obj([file]), sourcemaps.write('../aaa/bbb/', { sourceMappingURL: function(file) { // This avoids file.relative because Windows path separators return 'http://maps.example.com/' + file.basename + '.map'; }, }), concat(assert), ], done); }); it('should allow to change sources', function(done) { var file = makeFile(); function assert(results) { var data = results[0]; expect(data.sourceMap.sources).toEqual(['../src/helloworld.js']); } pipe([ from.obj([file]), sourcemaps.write({ mapSources: function(sourcePath, f) { expect(file).toEqual(f); return '../src/' + sourcePath; }, }), concat(assert), ], done); }); it('can replace `mapSources` option with sourcemap.mapSources stream', function(done) { var file = makeFile(); function assert(results) { var data = results[0]; expect(data.sourceMap.sources).toEqual(['../src/helloworld.js']); } pipe([ from.obj([file]), sourcemaps.mapSources(function(sourcePath, f) { expect(file).toEqual(f); return '../src/' + sourcePath; }), sourcemaps.write(), concat(assert), ], done); }); if (!ignoreLogTests) { // Should always be last as disabling a debug namespace does not work it('should output an error message if debug option is set and sourceContent is missing', function(done) { var file = makeFile(); file.sourceMap.sources[0] += '.invalid'; delete file.sourceMap.sourcesContent; var history = []; var unhook = hookStd.stderr(function(s) { history.push(s); }); function assert() { unhook(); var hasRegex = function(regex) { return function(s) { return regex.test(s); }; }; expect(history.some(hasRegex(/No source content for "helloworld.js.invalid". Loading from file./g))).toEqual(true); expect(history.some(hasRegex(/source file not found: /g))).toEqual(true); } pipe([ from.obj([file]), sourcemaps.write(), concat(assert), ], done); }); } });