Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump to 0.5.0, removed 'sort', use sandermatch, better sourcemaps. #7

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# changelog

## 0.5.0

* Removed `sort` option in favour of ordered minimatch pattern handling via sandermatch
* Handle symlinks in sourcemaps
* Correctly handle newlines in identity sourcemaps
* Ability to handle inline sourcemaps (e.g. from gobble-postcss)
* Use `/*# */` sourcemap comments in CSS files (instead of `//#`)

## 0.4.0

* Handle sourcemaps
Expand Down
8 changes: 2 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var gobble = require( 'gobble' );
module.exports = gobble( 'js' ).transform( 'concat', { dest: 'bundle.js' });
```

The `dest` property is required. Other values - `files`, `sort`, `separator` and `writeSourcemap`, explained below - are optional.
The `dest` option is required. Other options - `files`, `separator` and `writeSourcemap`, explained below - are optional.

### `files`

Expand All @@ -45,11 +45,7 @@ module.exports = gobble( 'js' )
});
```

### `sort`

Within each pattern, if multiple files are found, they will be sorted alphabetically by default. You can override this by passing a `sort` option, which is a standard [compare function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)].

If files match multiple patterns, they will only be included once (upon the first match).
If a file matches more than one minimatch pattern, only its first appearance is taken into account. The order of the patterns will decide the order of the files (in the previous example, all the `vendor/` files will appear before any `src` files).

### `separator`

Expand Down
73 changes: 73 additions & 0 deletions get-source-node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@

// Given a file name, reads it, checks it if has a sourcemap attached, then either:
// - Creates an identity sourcemap if it doesn't exist,
// - Reads the file with the sourcemap, or
// - Decodes an embedded base64 sourcemap


var SourceNode = require('source-map').SourceNode;
var SourceMapConsumer = require('source-map').SourceMapConsumer;
var sander = require('sander'),
readFile = sander.readFile,
readFileSync = sander.readFileSync,
realpathSync = sander.realpathSync;

var sourceMapRegExp = new RegExp(/(?:\/\/#|\/\/@|\/\*#)\s*sourceMappingURL=(\S*)\s*(?:\*\/\s*)?$/);
var dataUriRegexp = new RegExp(/^(data:)([\w\/\+]+)(;charset[=:][\w-]+)?(;base64)?,(.*)/); // From https://github.com/ragingwind/data-uri-regex, modified


function getSourceNode(filepath, filename) {
return readFile(filepath, filename).then( srcBuffer => {

var srcStr = srcBuffer.toString();

/// Run a regexp against the code to check for source mappings.
var match = sourceMapRegExp.exec(srcStr);

if (!match) {
// Create identity sourcemap
var realPath = realpathSync(filepath);
var realFilename = realpathSync(realPath, filename);
var lines = srcStr.split('\n');
var lineCount = lines.length;

var identNode = new SourceNode(null, null, null, '');
identNode.setSourceContent(realFilename, srcStr);

for (var i=0; i<lineCount; i++) {
var lineNode = new SourceNode(i+1, 0, realFilename, lines[i] + '\n');
identNode.add(lineNode);
}
// console.log('Created inline sourcemap for ', filename);
return identNode;
} else {
// Read sourcemap
srcStr = srcStr.replace(sourceMapRegExp, '');
var sourcemapFilename = match[1];
var dataUriMatch = dataUriRegexp.exec(match[1]);
if (dataUriMatch) {
// Read inline sourcemap
var data = dataUriMatch[5];
if (dataUriMatch[4] === ';base64') {
data = Buffer(data, 'base64').toString('utf8');
}
var parsedMap = new SourceMapConsumer( data.toString() );

// console.log('Loaded inline sourcemap for ', filename + ": (" + data.length + " bytes)");
return SourceNode.fromStringWithSourceMap( srcStr, parsedMap );
} else {
// Read external sourcemap
return readFile(filepath, sourcemapFilename )
.then( mapContents => {
// console.log('Loaded external sourcemap for ', filename + ": (" + sourcemapFilename + ")");
var parsedMap = new SourceMapConsumer( mapContents.toString() );
return SourceNode.fromStringWithSourceMap( srcStr, parsedMap );
}, err => {
throw new Error('File ' + filename + ' refers to a non-existing sourcemap at ' + sourcemapFilename + ' ' + err);
});
}
}
});
}

module.exports = getSourceNode;
75 changes: 75 additions & 0 deletions gobble-concat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// 🦃namespace concat
// Concatenates some files into one file.

var sander = require( 'sander' ),
sandermatch = require( 'sandermatch' ),
path = require( 'path' ),
mapSeries = require( 'promise-map-series' ),
getSourceNode = require( './get-source-node' );
var SourceNode = require('source-map').SourceNode;

var extensionsRegExp = new RegExp(/(\.js|\.css)$/);


module.exports = function concat ( inputdir, outputdir, options ) {

// 🦃option dest: String; The destination filename where everything will be concatenated to. Required.
if ( !options.dest ) {
throw new Error( 'You must pass a \'dest\' option to gobble-concat' );
}

// 🦃option writeSourcemap: Boolean; By default, sourcemaps are handled if the destination filename ends in `*.js` or `*.css`. Set this option to override that.
if ( options.writeSourcemap === undefined ) {
options.writeSourcemap = !!options.dest.match( extensionsRegExp );
}

// 🦃option files: Minimatch; A Minimatch expression (or an array of Minimatch expressions) matching the files to be concatenated.
return sandermatch.lsrMatch( inputdir, options.files ).then( function ( filenames ) {
var nodes = [];
function getSourceNodes ( filenames ) {
var nodes = [];

var nodePromises = [];
filenames.forEach(function (filename) {
nodePromises.push(getSourceNode( inputdir, filename ));
});
return Promise.all(nodePromises);
}

function writeResult (nodes) {
if (!nodes[0]) {
// Degenerate case: no matched files
return sander.writeFile( outputdir, options.dest, '' );
}

// 🦃option separator: String='\n\n'; The string which will be added between files.
var separatorNode = new SourceNode(null, null, null, options.separator || '\n\n');

var dest = new SourceNode(null, null, null, '');
dest.add(nodes[0]);

for (var i=1; i<nodes.length; i++) {
dest.add(separatorNode);
dest.add(nodes[i]);
}
var generated = dest.toStringWithSourceMap();

if ( options.writeSourcemap ) {
var sourceMapLocation;
if (options.dest.match(/\.css$/)) {
sourceMapLocation = '\n\n/*# sourceMappingURL=' + path.join(outputdir, options.dest + '.map') + ' */\n';
} else {
sourceMapLocation = '\n\n//# sourceMappingURL=' + path.join(outputdir, options.dest + '.map') + '\n'
}
return sander.Promise.all([
sander.writeFile( outputdir, options.dest, generated.code + sourceMapLocation ),
sander.writeFile( outputdir, options.dest + '.map', generated.map.toString() )
]);
} else {
return sander.writeFile( outputdir, options.dest, generated.code);
}
}

return getSourceNodes(filenames).then(writeResult);
});
};
108 changes: 0 additions & 108 deletions index.js

This file was deleted.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
{
"name": "gobble-concat",
"description": "Concatenate files with gobble",
"version": "0.4.0",
"version": "0.5.0",
"authors": [
"Rich Harris",
"Iván Sánchez Ortega <[email protected]>"
],
"license": "MIT",
"repository": "https://github.com/gobblejs/gobble-concat",
"files": [
"index.js"
"gobble-concat.js"
],
"main": "gobble-concat.js",
"keywords": [
"gobble-plugin"
],
"dependencies": {
"minimatch": "~1.0.0",
"promise-map-series": "~0.2.0",
"sander": "^0.1.6",
"sandermatch": "^0.1.4",
"source-map": "^0.5.3"
}
}