Skip to content
This repository has been archived by the owner on Apr 20, 2018. It is now read-only.

Commit

Permalink
Merge pull request #113 from orand/rev-suffix
Browse files Browse the repository at this point in the history
support for revved files with suffix/postfix naming
  • Loading branch information
sleeper committed May 22, 2013
2 parents bf2d9f1 + f8b2e76 commit f3172b0
Show file tree
Hide file tree
Showing 12 changed files with 241 additions and 206 deletions.
20 changes: 5 additions & 15 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,16 @@ module.exports = function (grunt) {
'!test/temp/**/*.js',
'!test/fixtures/*.js'
]
},
mochacli: {
all: ['test/test-*.js']
}
});

grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-mocha-cli');

grunt.loadTasks('tasks');

grunt.registerTask('test', 'Run tests', function () {
var done = this.async();
var spawnOpts = {
cmd: 'node_modules/mocha/bin/mocha',
args: grunt.file.expand('test/test-*.js')
};
grunt.util.spawn(spawnOpts, function (err, res, code) {
grunt.log.write(res.stdout);
if (code) {
throw res.stderr;
}
done();
});
});
grunt.registerTask('default', ['jshint', 'test']);
grunt.registerTask('default', ['jshint', 'mochacli']);
};
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ This asset search directories collection is by default set to the location of th
```
By default `usemin` will look under `dist/html` for revved versions of:

- `styles/main.css`: a revved version of `main.css` will be looked at under the `dist/html/styles` directory. For example a file `dist/html/styles/1234.main.css` will match (although `dist/html/1234.main.css` won't: the path of the referenced file is important)
- `styles/main.css`: a revved version of `main.css` will be looked at under the `dist/html/styles` directory. For example a file `dist/html/styles/main.1234.css` will match (although `dist/html/main.1234.css` won't: the path of the referenced file is important)
- `../images/test.png`: it basically means that a revved version of `test.png` will be looked for under the `dist/images` directory

#### Example 2: file `dist/html/index.html` has the following content:
Expand All @@ -54,7 +54,7 @@ By default `usemin` will look under `dist/html` for revved versions of:
<link rel="stylesheet" href="/styles/main.css">
<img src="/images/test.png">
```
By default `usemin` will look under `dist/html` for revved versions of `styles/main.css` and `images/test.png`. Now let's suppose our assets are scattered in `dist/assets`. By changing the asset search path list to `['dist/assets']`, the revved versions of the files will be looked under `dist/assets` (and thus, for example, `dist/assets/images/875487.tes.png` and `dist/assets/styles/98090.main.css`) will be found.
By default `usemin` will look under `dist/html` for revved versions of `styles/main.css` and `images/test.png`. Now let's suppose our assets are scattered in `dist/assets`. By changing the asset search path list to `['dist/assets']`, the revved versions of the files will be looked under `dist/assets` (and thus, for example, `dist/assets/images/test.875487.png` and `dist/assets/styles/main.98090.css`) will be found.

### Options

Expand Down Expand Up @@ -353,8 +353,8 @@ Relative files references are also looked at from location of the examined file,

### usemin
`usemin` target is replacing references to images, scrips, css, ... in the furnished files (html, css, ...). These references may be either absolute (i.e. `/images/foo.png`) or relative (i.e. `image/foo.png` or `../images/foo.png`).
When the reference is absolute a set of asset search paths should be looked at under the destination directory (for example, using the previous example, and `searchpath` equal to `['assets']`, `usemin` would try to find either a revved version of the image of the image bellow the `assets` directory: for example `dest/assets/images/1223443.foo.png`).
When the reference is relative, by default the referenced item is looked in the path relative *to the current file location* in the destination directory (e.g. with the preceding example, if the file is `build/bar/index.html`, then transformed `index.html` will be in `dist/bar`, and `usemin` will look for `dist/bar/../images/32323.foo.png`).
When the reference is absolute a set of asset search paths should be looked at under the destination directory (for example, using the previous example, and `searchpath` equal to `['assets']`, `usemin` would try to find either a revved version of the image of the image bellow the `assets` directory: for example `dest/assets/images/foo.1223443.png`).
When the reference is relative, by default the referenced item is looked in the path relative *to the current file location* in the destination directory (e.g. with the preceding example, if the file is `build/bar/index.html`, then transformed `index.html` will be in `dist/bar`, and `usemin` will look for `dist/bar/../images/foo.32323.png`).

## License

Expand Down
24 changes: 16 additions & 8 deletions lib/revvedfinder.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ RevvedFinder.prototype.getCandidatesFromMapping = function(file, searchPaths) {
// We need to transform the actual file to a form that matches the one we received
// For example if we received file 'foo/images/test.png' with searchPaths == ['dist'],
// and found in mapping that 'dist/foo/images/test.png' has been renamed
// 'dist/foo/images/1234.test.png' by grunt-rev, then we need to return
// 'foo/images/1234.test.png'
// 'dist/foo/images/test.1234.png' by grunt-rev, then we need to return
// 'foo/images/test.1234.png'
var cfile = path.basename(self.mapping[key]);
candidates.push(dirname + '/' + cfile);
debug('Found a candidate: %s/%s',dirname, cfile);
Expand All @@ -45,14 +45,22 @@ RevvedFinder.prototype.getCandidatesFromMapping = function(file, searchPaths) {
}
;
RevvedFinder.prototype.getCandidatesFromFS = function(file, searchPaths) {
var basename = path.basename(file);
var extname = path.extname(file);
var basename = path.basename(file, extname);
var dirname = path.dirname(file);
var revvedRx = new RegExp('[0-9a-fA-F]+\\.' + regexpQuote(basename) + '$');
var revvedRx = new RegExp(regexpQuote(basename) + '\\.[0-9a-fA-F]+' + regexpQuote(extname) + '$');
var candidates = [];
var self = this;

searchPaths.forEach(function(sp) {
var searchString = path.join(sp, dirname, '*.' + basename);
var searchString = path.join(sp, dirname, basename + '.*' + extname);

if (searchString.indexOf('#') === 0) {
// patterns starting with # are treated as comments by the glob implementation which returns undefined,
// which would cause an unhandled exception in self.expandfn below so the file is never written
return;
}

debug('Looking for %s on disk', searchString);

var files = self.expandfn(searchString);
Expand Down Expand Up @@ -86,7 +94,7 @@ RevvedFinder.prototype.getCandidatesFromFS = function(file, searchPaths) {
// It should return an array of candidates that are in the same format as the
// furnished file.
// For example, when given file 'images/test.png', and searchPaths of ['dist']
// the returned array should be something like ['images/1234.test.png']
// the returned array should be something like ['images/test.1234.png']
//
RevvedFinder.prototype.getRevvedCandidates = function(file, searchPaths) {
var candidates;
Expand Down Expand Up @@ -118,13 +126,13 @@ RevvedFinder.prototype.getRevvedCandidates = function(file, searchPaths) {
// | + style.css
// + images
// |
// + 2123.pic.png
// + pic.2123.png
//
// and that somehow style.css is referencing '../../images/pic.png'
// When called like that:
// revvedFinder.find('../../images/pic.png', 'build/css');
// the function must return
// '../../images/2123.pic.png'
// '../../images/pic.2123.png'
//
// Note that +ofile+ should be a relative path to the looked for file
// (i.e. if it's an absolue path -- starting with / -- or an external one -- containing :// -- then
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@
"dependencies": {
"lodash": "~1.0.1",
"debug": "~0.7.2"
},
},
"devDependencies": {
"grunt": "~0.4.1",
"mocha": "~1.9.0",
"mkdirp": "~0.3.5",
"rimraf": "~2.1.4",
"grunt-contrib-jshint": "~0.4.1"
"grunt-contrib-jshint": "~0.4.1",
"grunt-mocha-cli": "~1.0.5"
},
"peerDependencies": {
"grunt": "~0.4.0"
Expand Down
37 changes: 35 additions & 2 deletions test/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ helpers.makeFinder = function(mapping) {
if (typeof b === 'string' || b instanceof String) {
b = [b];
}
var dir = _.find(b, function(d) {return mapping[path.join(d,s)]; });
var file = typeof dir !== 'undefined' ? mapping[path.join(dir,s)] : s;
var dir = _.find(b, function(d) {return mapping[path.join(d,s).replace(/\\/g, '/')]; });
var file = typeof dir !== 'undefined' ? mapping[path.join(dir,s).replace(/\\/g, '/')] : s;

if (typeof file === 'array' || file instanceof Array) {
output = file[0];
Expand All @@ -127,3 +127,36 @@ helpers.makeFinder = function(mapping) {
}
};
};

helpers.normalize = function (object) {
// turns {'foo/bar': ['app/bar.js', 'app/baz.js']}
// into {'foo\\bar': ['app\\bar.js', 'app\\baz.js']} on Windows

if (process.platform !== 'win32') {
return object;
}

if (object) {
if (typeof object === 'string') {
object = path.normalize(object);
} else if (object instanceof Array) {
for (var i = 0; i < object.length; i++) {
object[i] = helpers.normalize(object[i]);
}
} else {
for (var prop in object) {
if (object.hasOwnProperty(prop)) {
if (prop.indexOf('/') !== -1) {
object[path.normalize(prop)] = helpers.normalize(object[prop]);
delete object[prop];
}
else {
object[prop] = helpers.normalize(object[prop]);
}
}
}
}
}

return object;
};
5 changes: 3 additions & 2 deletions test/test-config-concat.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';
var assert = require('assert');
var concatConfig = require('../lib/config/concat.js');
var path = require('path');

var block = {
type: 'js',
Expand All @@ -27,8 +28,8 @@ describe('Concat config write', function () {
it('should use the input files correctly', function () {
var ctx = { inDir: '.', inFiles: ['foo.js', 'bar.js', 'baz.js'], outDir: 'tmp/concat', outFiles: []};
var cfg = concatConfig.createConfig( ctx, block );
assert.ok(cfg['tmp/concat/scripts/site.js']);
assert.deepEqual(cfg['tmp/concat/scripts/site.js'], ['foo.js', 'bar.js', 'baz.js']);
assert.ok(cfg[path.normalize('tmp/concat/scripts/site.js')]);
assert.deepEqual(cfg[path.normalize('tmp/concat/scripts/site.js')], ['foo.js', 'bar.js', 'baz.js']);
assert.deepEqual(ctx.outFiles, ['scripts/site.js']);
});
});
7 changes: 4 additions & 3 deletions test/test-config-requirejs.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';
var assert = require('assert');
var requirejsConfig = require('../lib/config/requirejs.js');
var helpers = require('./helpers');

var block = {
type: 'js',
Expand Down Expand Up @@ -41,11 +42,11 @@ describe('Requirejs config write', function() {
it('should use the input files correctly', function () {
var ctx = { inDir: 'zzz', inFiles: ['foo.js'], outDir: 'tmp/requirejs', outFiles: []};
var cfg = requirejsConfig.createConfig( ctx, block );
assert.deepEqual(cfg,{
assert.deepEqual(cfg,helpers.normalize({
'default': {
'options': { 'name': 'main', 'out': 'tmp/requirejs/scripts/amd-app.js', 'baseUrl': 'zzz/scripts', 'mainConfigFile': 'zzz/scripts/main.js'}
}
});
}));
});

it('should do nothing if the block is not requirejs enabled', function() {
Expand All @@ -57,7 +58,7 @@ describe('Requirejs config write', function() {
it('should add a .js when needed to mainConfigFile', function() {
var ctx = { inDir: 'zzz', inFiles: ['foo.js'], outDir: 'tmp/requirejs', outFiles: []};
var cfg = requirejsConfig.createConfig( ctx, block );
assert.equal(cfg['default'].options.mainConfigFile, 'zzz/scripts/main.js');
assert.equal(cfg['default'].options.mainConfigFile, helpers.normalize('zzz/scripts/main.js'));
});

it('should treat multi-config requirejs');
Expand Down
17 changes: 9 additions & 8 deletions test/test-config-uglifyjs.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';
var assert = require('assert');
var uglifyjsConfig = require('../lib/config/uglifyjs.js');
var path = require('path');

var block = {
type: 'js',
Expand All @@ -27,20 +28,20 @@ describe('Uglifyjs config write', function () {
it('should use the input files correctly', function () {
var ctx = { inDir: 'zzz', inFiles: ['foo.js', 'bar.js', 'baz.js'], outDir: 'tmp/uglifyjs', outFiles: []};
var cfg = uglifyjsConfig.createConfig( ctx, block );
assert.ok(cfg['tmp/uglifyjs/foo.js']);
assert.deepEqual(cfg['tmp/uglifyjs/foo.js'], ['zzz/foo.js']);
assert.ok(cfg['tmp/uglifyjs/bar.js']);
assert.deepEqual(cfg['tmp/uglifyjs/bar.js'], ['zzz/bar.js']);
assert.ok(cfg['tmp/uglifyjs/baz.js']);
assert.deepEqual(cfg['tmp/uglifyjs/baz.js'], ['zzz/baz.js']);
assert.ok(cfg[path.normalize('tmp/uglifyjs/foo.js')]);
assert.deepEqual(cfg[path.normalize('tmp/uglifyjs/foo.js')], [path.normalize('zzz/foo.js')]);
assert.ok(cfg[path.normalize('tmp/uglifyjs/bar.js')]);
assert.deepEqual(cfg[path.normalize('tmp/uglifyjs/bar.js')], [path.normalize('zzz/bar.js')]);
assert.ok(cfg[path.normalize('tmp/uglifyjs/baz.js')]);
assert.deepEqual(cfg[path.normalize('tmp/uglifyjs/baz.js')], [path.normalize('zzz/baz.js')]);
assert.deepEqual(ctx.outFiles, ['foo.js', 'bar.js', 'baz.js']);
});

it('should use the destination file if it is the laast step of the pipe.', function () {
var ctx = { inDir: 'zzz', inFiles: ['foo.js', 'bar.js', 'baz.js'], outDir: 'dist', outFiles: [], last: true};
var cfg = uglifyjsConfig.createConfig( ctx, block );
assert.ok(cfg['dist/scripts/site.js']);
assert.deepEqual(cfg['dist/scripts/site.js'], ['zzz/foo.js', 'zzz/bar.js', 'zzz/baz.js']);
assert.ok(cfg[path.normalize('dist/scripts/site.js')]);
assert.deepEqual(cfg[path.normalize('dist/scripts/site.js')], [path.normalize('zzz/foo.js'), path.normalize('zzz/bar.js'), path.normalize('zzz/baz.js')]);
assert.deepEqual(ctx.outFiles, ['scripts/site.js']);
});

Expand Down
26 changes: 13 additions & 13 deletions test/test-config-writer.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ describe('ConfigWriter', function () {
var file = helpers.createFile('foo', 'app', blocks);
var c = new ConfigWriter( flow, [], {input: 'app', dest: 'dist', staging: '.tmp'} );
var config = c.process(file);
assert.deepEqual(config, {
assert.deepEqual(config, helpers.normalize({
'concat':{'.tmp/concat/scripts/site.js': ['app/foo.js', 'app/bar.js', 'app/baz.js']},
'uglify': {'dist/scripts/site.js': ['.tmp/concat/scripts/site.js']}
});
}));
});

it('should have a configurable destination directory', function() {
Expand All @@ -45,10 +45,10 @@ describe('ConfigWriter', function () {
var file = helpers.createFile('foo', 'app', blocks);
var c = new ConfigWriter( flow, [], {input: 'app', dest: 'destination', staging: '.tmp'} );
var config = c.process(file);
assert.deepEqual(config, {
assert.deepEqual(config, helpers.normalize({
'concat':{'.tmp/concat/scripts/site.js': ['app/foo.js', 'app/bar.js', 'app/baz.js']},
'uglify': {'destination/scripts/site.js': ['.tmp/concat/scripts/site.js']}
});
}));
});

it('should have a configurable staging directory', function() {
Expand All @@ -57,10 +57,10 @@ describe('ConfigWriter', function () {
var file = helpers.createFile('foo', 'app', blocks);
var c = new ConfigWriter( flow, [], {input: 'app', dest: 'dist', staging: 'staging'} );
var config = c.process(file);
assert.deepEqual(config, {
assert.deepEqual(config, helpers.normalize({
'concat': { 'staging/concat/scripts/site.js': ['app/foo.js', 'app/bar.js', 'app/baz.js'] },
'uglify': { 'dist/scripts/site.js': ['staging/concat/scripts/site.js'] }
});
}));
});

it('should allow for single step flow', function() {
Expand All @@ -69,7 +69,7 @@ describe('ConfigWriter', function () {
var file = helpers.createFile('foo', 'app', blocks);
var c = new ConfigWriter( flow, [], {input: 'app', dest: 'dist', staging: 'staging'} );
var config = c.process(file);
assert.deepEqual(config, {'uglify': {'dist/scripts/site.js': ['app/foo.js', 'app/bar.js', 'app/baz.js']}});
assert.deepEqual(config, helpers.normalize({'uglify': {'dist/scripts/site.js': ['app/foo.js', 'app/bar.js', 'app/baz.js']}}));
});

it('should rewrite the requirejs config if needed', function() {
Expand All @@ -79,15 +79,15 @@ describe('ConfigWriter', function () {
var c = new ConfigWriter( flow, ['requirejs'], {input: 'app', dest: 'dist', staging: 'staging'} );
var config = c.process(file);

assert.deepEqual(config, {
assert.deepEqual(config, helpers.normalize({
'concat':{'staging/concat/scripts/amd-app.js': ['app/scripts/main.js']},
'uglify': {'dist/scripts/amd-app.js': ['staging/concat/scripts/amd-app.js']},
'requirejs': { 'default':
{
options: {name: 'main', out: 'dist/scripts/amd-app.js', baseUrl: 'app/scripts', mainConfigFile: 'app/scripts/main.js'}
}
}
});
}));
});

it('should allow for a configuration of the flow\'s step order', function() {
Expand All @@ -97,10 +97,10 @@ describe('ConfigWriter', function () {
var c = new ConfigWriter( flow, [], {input: 'app', dest: 'dist', staging: 'staging'} );
var config = c.process(file);

assert.deepEqual(config, {
assert.deepEqual(config, helpers.normalize({
'uglify': {'staging/uglify/foo.js': ['app/foo.js'], 'staging/uglify/bar.js': ['app/bar.js'], 'staging/uglify/baz.js': ['app/baz.js']},
'concat': {'dist/scripts/site.js': ['staging/uglify/foo.js', 'staging/uglify/bar.js', 'staging/uglify/baz.js']}
});
}));
});

it('should augment the furnished config', function() {
Expand All @@ -109,10 +109,10 @@ describe('ConfigWriter', function () {
var file = helpers.createFile('foo', 'app', blocks);
var c = new ConfigWriter( flow, [], {input: 'app', dest: 'destination', staging: '.tmp'} );
config = c.process(file, config);
assert.deepEqual(config, {
assert.deepEqual(config, helpers.normalize({
'concat':{'.tmp/concat/scripts/site.js': ['app/foo.js', 'app/bar.js', 'app/baz.js'], 'foo.js': 'bar.js'},
'uglify': {'destination/scripts/site.js': ['.tmp/concat/scripts/site.js']}
});
}));
});

it('should allow for an empty flow');
Expand Down
Loading

0 comments on commit f3172b0

Please sign in to comment.