Permalink
Browse files

Rework the usemin task to also do the replacement in stylesheets

Closes #27
  • Loading branch information...
1 parent 706f049 commit e4465c6100e6429560e4aa570fbe87baf2af6bee @mklabs committed May 19, 2012
View
4 grunt.js
@@ -68,12 +68,12 @@ module.exports = function(grunt) {
test: {
// each task is tested individually, with basic files comparison with
// what is in test/fixtures/
- // tasks: ['test/tasks/test-*.js'],
+ tasks: ['test/tasks/test-*.js']
// css: 'test/tasks/test-css.js'
// img: 'test/tasks/test-img.js'
// tar: 'test/tasks/test-tar.js'
- usemin: 'test/tasks/test-usemin.js'
+ // usemin: 'test/tasks/test-usemin.js'
// default task with default options
// runThemAll: ['test/tasks/default.js']
View
5 support/docs/grunt.js
@@ -69,10 +69,10 @@ module.exports = function(grunt) {
cb(err);
});
- var now = +new Date;
+ var now = +new Date();
site.on('end', function() {
grunt.log
- .ok(' ✔ Site generated in ' + ((+new Date - now) / 1000) + 's')
+ .ok(' ✔ Site generated in ' + ((+new Date() - now) / 1000) + 's')
.writeln(data.serve ? 'Try opening http://localhost:3000' : 'Try running: open docs/_site/index.html');
grunt.helper('copy', '../../docs/wiki/_site/index.html', '../../docs/index.html', function() {
@@ -188,7 +188,6 @@ module.exports = function(grunt) {
grunt.registerHelper('copy', function(src, dest, cb) {
src = path.join(__dirname, src);
dest = path.join(__dirname, dest);
- console.log('Copy files %s -> %s', src, dest);
var type = path.extname(dest) ? 'File' : 'Directory';
fs.Reader(src).pipe(fs.Writer({ path: dest, type: type })).on('close', cb);
});
View
129 tasks/usemin.js
@@ -31,58 +31,56 @@ module.exports = function(grunt) {
files.map(grunt.file.read).forEach(function(content, i) {
var p = files[i];
+
+ // get extension and trigger corresponding helpers
+ var ext = path.extname(p).slice(1);
+
grunt.log.subhead('usemin - ' + p);
// make sure to convert back into utf8, `file.read` when used as a
// forEach handler will take additional arguments, and thus trigger the
// raw buffer read
content = content.toString();
- // todo fallback to the usemin replace we have if no sections were found.
- var blocks = getBlocks(content);
-
- //
- // {
- // 'css/site.css ':[
- // ' <!-- build:css css/site.css -->',
- // ' <link rel="stylesheet" href="css/style.css">',
- // ' <!-- endbuild -->'
- // ],
- // 'js/head.js ': [
- // ' <!-- build:js js/head.js -->',
- // ' <script src="js/libs/modernizr-2.5.3.min.js"></script>',
- // ' <!-- endbuild -->'
- // ],
- // 'js/site.js ': [
- // ' <!-- build:js js/site.js -->',
- // ' <script src="js/plugins.js"></script>',
- // ' <script src="js/script.js"></script>',
- // ' <!-- endbuild -->'
- // ]
- // }
- //
-
- // handle blocks
- Object.keys(blocks).forEach(function(key) {
- var block = blocks[key].join(linefeed),
- parts = key.split(':'),
- type = parts[0],
- target = parts[1];
-
- content = grunt.helper('usemin', content, block, target, type);
- });
-
- // handle revving, each script / link tags are searching for a
- // matching file in intermediate dir, replacing the href/src with their
- // hash-prepended version.
- content = grunt.helper('usemin:replace', content);
+ // ext-specific directives handling and replacement of blocks
@ottok
ottok May 23, 2012

Before this commit task usemin used to work on any file type. Now only on html/js/css, not for example on our projects .mustache..

@mklabs
mklabs May 23, 2012

I needed to split this on different helpers, to fix another nasty bugs (with img revved that needs to be updated in css files too). Thanks for your report and the opened ticket, it needs to go through the corresponding helper based on grunt target rather than file extensions.

+ if(!!grunt.task._helpers['usemin:pre:' + ext]) {
+ content = grunt.helper('usemin:pre:' + ext, content);
+ }
+
+ // actual replacement of revved assets
+ if(!!grunt.task._helpers['usemin:post:' + ext]) {
+ content = grunt.helper('usemin:post:' + ext, content);
+ }
// write the new content to disk
grunt.file.write(p, content);
});
});
+ // usemin:pre:* are used to preprocess files with the blocks and directives
+ // before going through the global replace
+ grunt.registerHelper('usemin:pre:html', function(content) {
+ // XXX extension-specific for get blocks too.
+ //
+ // Eg. for each predefined extensions directives may vary. eg <!--
+ // directive --> for html, /** directive **/ for css
+ var blocks = getBlocks(content);
+
+ // handle blocks
+ Object.keys(blocks).forEach(function(key) {
+ var block = blocks[key].join(linefeed),
@necolas
necolas Aug 7, 2012

This seems to cause problems on Windows. If the file was authored with Unix line endings, then this will add Windows line endings to the block, meaning that it will no longer match the original block in the source file. No replacement occurs.

+ parts = key.split(':'),
+ type = parts[0],
+ target = parts[1];
+
+ content = grunt.helper('usemin', content, block, target, type);
+ });
+
+ return content;
+ });
+
+ // usemin and usemin:* are used with the blocks parsed from directives
grunt.registerHelper('usemin', function(content, block, target, type) {
target = target || 'replace';
return grunt.helper('usemin:' + type, content, block, target);
@@ -98,15 +96,23 @@ module.exports = function(grunt) {
return content.replace(block, indent + '<script src="' + target + '"></script>');
});
- grunt.registerHelper('usemin:replace', function(content) {
+ grunt.registerHelper('usemin:post:css', function(content) {
+ grunt.log.writeln('Update the CSS with new img filenames');
+ content = grunt.helper('replace', content, /url\(\s*['"]([^"']+)["']\s*\)/gm);
+ return content;
+ });
+
+ // usemin:post:* are the global replace handlers, they delegate the regexp
+ // replace to the replace helper.
+ grunt.registerHelper('usemin:post:html', function(content) {
grunt.log.verbose.writeln('Update the HTML to reference our concat/min/revved script files');
content = grunt.helper('replace', content, /<script.+src=['"](.+)["'][\/>]?><[\\]?\/script>/gm);
- grunt.log.verbose.writeln('Update the HTML with the new css filename');
+ grunt.log.verbose.writeln('Update the HTML with the new css filenames');
content = grunt.helper('replace', content, /<link rel=["']?stylesheet["']?\shref=['"](.+)["']\s*>/gm);
- grunt.log.verbose.writeln('Update the HTML with the new img filename');
+ grunt.log.verbose.writeln('Update the HTML with the new img filenames');
content = grunt.helper('replace', content, /<img[^\>]+src=['"]([^"']+)["']/gm);
grunt.log.verbose.writeln('Update the HTML with background imgs, case there is some inline style');
@@ -115,15 +121,28 @@ module.exports = function(grunt) {
return content;
});
+ grunt.registerHelper('usemin:post:css', function(content) {
+
+ grunt.log.verbose.writeln('Update the CSS with background imgs, case there is some inline style');
+ content = grunt.helper('replace', content, /url\(\s*['"]?([^'"\)]+)['"]?\s*\)/gm);
+
+ return content;
+ });
+
+ //
+ // global replace handler, takes a file content a regexp to macth with. The
+ // regexp should capture the assets relative filepath, it is then compared to
+ // the list of files on the filesystem to guess the actual revision of a file
+ //
grunt.registerHelper('replace', function(content, regexp) {
return content.replace(regexp, function(match, src) {
//do not touch external files
if(src.match(/\/\//)) return match;
var basename = path.basename(src);
var dirname = path.dirname(src);
- // todo: don't lookup for every files on each replace. suboptimal.
- // files won't change, the filepath should filter the original list of files.
+ // XXX files won't change, the filepath should filter the original list
+ // of cached files.
var filepath = grunt.file.expand(path.join('**/*') + basename)[0];
// not a file in intermediate, skip it
@@ -158,6 +177,30 @@ var regbuild = /<!--\s*build:(\w+)\s*(.+)\s*-->/;
// end build pattern -- <!-- endbuild -->
var regend = /<!--\s*endbuild\s*-->/;
+
+//
+// Returns an hash object of all the directives for the given html. Results is
+// of the following form:
+//
+// {
+// 'css/site.css ':[
+// ' <!-- build:css css/site.css -->',
+// ' <link rel="stylesheet" href="css/style.css">',
+// ' <!-- endbuild -->'
+// ],
+// 'js/head.js ': [
+// ' <!-- build:js js/head.js -->',
+// ' <script src="js/libs/modernizr-2.5.3.min.js"></script>',
+// ' <!-- endbuild -->'
+// ],
+// 'js/site.js ': [
+// ' <!-- build:js js/site.js -->',
+// ' <script src="js/plugins.js"></script>',
+// ' <script src="js/script.js"></script>',
+// ' <!-- endbuild -->'
+// ]
+// }
+//
function getBlocks(body) {
var lines = body.replace(/\r\n/g, '\n').split(/\n/),
@necolas
necolas Aug 7, 2012

Could you just split on \n, and then join on \n later, to avoid the issue mentioned in the comment above. Perhaps in the future, a different approach should be taken so that the original block can be preserved (maybe don't step through line-by-line).

@mklabs
mklabs Aug 7, 2012

Thanks Nicolas for the feedbacks.

Agreed. It is a bit clumsy. Apparently, all we need to do is to remove the use of grunt.util.linefeed and use \n unix like linefeed to mater what.

block = false,
View
7 test/fixtures/css/app.css
@@ -2,16 +2,17 @@
/* =============================================================================
App specific CSS file.
- This is usually where the site/app's CSS specific rules are setup. Note that you could
- do exactly the same using less by adding a '@import app.less;' at the end of
- css/less/bootstrap.less file.
+ This is usually where the site/app's CSS specific rules are setup.
========================================================================== */
+@import url('ui/widget.css');
body:before {
content: ' ☺ H E L L O ☺ ';
font: 10em Helvetica, sans-serif;
color: hotPink;
}
+
+.css-reved .img-6 { background: url('../img/6.jpg'); }
View
2 test/fixtures/css/expected.css
@@ -1 +1 @@
-article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}html,button,input,select,textarea{font-family:sans-serif;color:#222}body{margin:0;font-size:1em;line-height:1.4}::-moz-selection{background:#b3d4fc;text-shadow:none}::selection{background:#b3d4fc;text-shadow:none}a{color:#00e}a:visited{color:#551a8b}a:hover{color:#06e}a:focus{outline:thin dotted}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:1em 40px}dfn{font-style:italic}hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:1em 0;padding:0}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:700}pre,code,kbd,samp{font-family:monospace,serif;_font-family:'courier new',monospace;font-size:1em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}q{quotes:none}q:before,q:after{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}ul,ol{margin:1em 0;padding:0 0 0 40px}dd{margin:0 0 0 40px}nav ul,nav ol{list-style:none;list-style-image:none;margin:0;padding:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*width:13px;*height:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical}input:invalid,textarea:invalid{background-color:#f0dddd}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{border:0;font:0/0 a;text-shadow:none;color:transparent;background-color:transparent}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.clearfix:before,.clearfix:after{content:"";display:table}.clearfix:after{clear:both}.clearfix{*zoom:1}@media print{*{ background:transparent!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}body:before{content:' ☺ H E L L O ☺ ';font:10em Helvetica,sans-serif;color:hotPink}
+article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}html,button,input,select,textarea{font-family:sans-serif;color:#222}body{margin:0;font-size:1em;line-height:1.4}::-moz-selection{background:#b3d4fc;text-shadow:none}::selection{background:#b3d4fc;text-shadow:none}a{color:#00e}a:visited{color:#551a8b}a:hover{color:#06e}a:focus{outline:thin dotted}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:1em 40px}dfn{font-style:italic}hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:1em 0;padding:0}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:700}pre,code,kbd,samp{font-family:monospace,serif;_font-family:'courier new',monospace;font-size:1em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}q{quotes:none}q:before,q:after{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}ul,ol{margin:1em 0;padding:0 0 0 40px}dd{margin:0 0 0 40px}nav ul,nav ol{list-style:none;list-style-image:none;margin:0;padding:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*width:13px;*height:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical}input:invalid,textarea:invalid{background-color:#f0dddd}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{border:0;font:0/0 a;text-shadow:none;color:transparent;background-color:transparent}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.clearfix:before,.clearfix:after{content:"";display:table}.clearfix:after{clear:both}.clearfix{*zoom:1}@media print{*{ background:transparent!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}@import url(ui/widget.css);body:before{content:' ☺ H E L L O ☺ ';font:10em Helvetica,sans-serif;color:hotPink}.css-reved .img-6{background:url(../img/6.jpg)}
View
3 test/fixtures/css/style.css
@@ -9,9 +9,6 @@
Following assumes an app.css to put specific CSS rules.
- Both unminified and minified version of bootstrap's css will be generated by the
- less script command. You may want to switch the bootstrap.css to bootstrap.min.css
-
========================================================================== */
@import url('h5bp.css');
View
1 test/fixtures/css/ui/widget.css
@@ -0,0 +1 @@
+.css-reved .img-5 { background: url('../../img/5.jpg'); }
View
3 test/fixtures/default/grunt.js
@@ -56,7 +56,8 @@ module.exports = function(grunt) {
},
usemin: {
- files: ['**/*.html']
+ html: ['**/*.html'],
+ css: ['**/*style.css']
},
html: '<config:usemin>',
View
6 test/fixtures/default/usemin.html
@@ -20,7 +20,7 @@
<!-- Place favicon.ico and apple-touch-icon.png in the root directory: mathiasbynens.be/notes/touch-icons -->
- <!-- build:css css/style.min.css -->
+ <!-- build:css css/style.css -->
<link rel="stylesheet" href="css/style.css">
<!-- endbuild -->
@@ -72,7 +72,9 @@
<span class="img-1"></span>
<span class="img-2"></span>
<span class="img-3"></span>
- <span class="img-4"></span>
+ <span class="img-3"></span>
+ <span class="img-5"></span>
+ <span class="img-6"></span>
</div>
View
6 test/fixtures/usemin/index.html
@@ -20,7 +20,7 @@
<!-- Place favicon.ico and apple-touch-icon.png in the root directory: mathiasbynens.be/notes/touch-icons -->
- <link rel="stylesheet" href="css/style.min.css">
+ <link rel="stylesheet" href="css/style.css">
<!-- More ideas for your <head> here: h5bp.com/d/head-Tips -->
@@ -70,7 +70,9 @@
<span class="img-1"></span>
<span class="img-2"></span>
<span class="img-3"></span>
- <span class="img-4"></span>
+ <span class="img-3"></span>
+ <span class="img-5"></span>
+ <span class="img-6"></span>
</div>
View
14 test/fixtures/usemin/reved.html
@@ -20,7 +20,7 @@
<!-- Place favicon.ico and apple-touch-icon.png in the root directory: mathiasbynens.be/notes/touch-icons -->
- <link rel="stylesheet" href="css/style.min.css">
+ <link rel="stylesheet" href="css/e1823e1a.style.css">
<!-- More ideas for your <head> here: h5bp.com/d/head-Tips -->
@@ -40,10 +40,10 @@
.css-reved:before { content: 'Test out this rev replacement with some background img'; }
.imgs, .css-reved { margin: 1em; padding: 1em; border: 1px solid #ccc; float: left; width: 200px; }
- .css-reved .img-1 { background: url('img/1.png'); }
- .css-reved .img-2 { background: url('img/2.png'); }
- .css-reved .img-3 { background: url('img/3.png'); }
- .css-reved .img-4 { background: url('img/4.png'); }
+ .css-reved .img-1 { background: url('img/59928801.1.png'); }
+ .css-reved .img-2 { background: url('img/8381cd83.2.png'); }
+ .css-reved .img-3 { background: url('img/cafcb34d.3.png'); }
+ .css-reved .img-4 { background: url('img/49dd7a3b.4.png'); }
img, .img-1, .img-2, .img-3, .img-4 { display: block; height: 150px; width: 150px; float: left; margin: 1em; }
</style>
@@ -70,7 +70,9 @@
<span class="img-1"></span>
<span class="img-2"></span>
<span class="img-3"></span>
- <span class="img-4"></span>
+ <span class="img-3"></span>
+ <span class="img-5"></span>
+ <span class="img-6"></span>
</div>
View
32 test/helpers/index.js
@@ -142,19 +142,28 @@ helpers.copy = function(sources, destination, cb) {
// if we get a single file to copy and destination is not a dir
// direct file copy
if(ln === 1 && path.extname(destination)) {
- return fs.createReadStream(sources[0])
- .pipe(fs.createWriteStream(destination).on('close', cb));
+ return mkdirp(path.dirname(destination), function(err) {
+ if(err) return cb(err);
+ fs.createReadStream(sources[0])
+ .pipe(fs.createWriteStream(destination).on('close', cb));
+ });
}
sources.forEach(function(src) {
- var to = path.join(destination, path.basename(src)),
- rs = fs.createReadStream(src),
- ws = fs.createWriteStream(to).on('close', function() {
+ var to = path.join(destination, path.basename(src));
+
+ mkdirp(path.dirname(to), function(err) {
+ if(err) return cb(err);
+ var rs = fs.createReadStream(src),
+ ws = fs.createWriteStream(to);
+
+ ws.on('close', function() {
if(--ln) return;
cb();
});
- rs.pipe(ws);
+ rs.pipe(ws);
+ });
});
};
@@ -222,6 +231,13 @@ helpers.equal = function(actual, expected, msg) {
// a simple copy helper, mostly used to update a fixture file no longer up to
// date
helpers.copyFile = function(src, dst, cb) {
- if(!cb) return fs.writeFileSync(dst, fs.readFileSync(src));
- fs.createReadStream(src).pipe(fs.createWriteStream(dst)).on('close', cb);
+ if(!cb) {
+ mkdirp.sync(path.dirname(dst));
+ return fs.writeFileSync(dst, fs.readFileSync(src));
+ }
+
+ mkdirp(path.dirname(dst), function(err) {
+ if(err) return cb(err);
+ fs.createReadStream(src).pipe(fs.createWriteStream(dst)).on('close', cb);
+ });
};
View
1 test/mocha.opts
@@ -1,2 +1,3 @@
--reporter spec
--timeout 5000
+--slow 1500
View
2 test/tasks/test-css.js
@@ -15,7 +15,7 @@ describe("CSS task", function() {
// copy in some files, with @imports to test out the inline imports
var files = fs.readdirSync(path.join(__dirname, '../fixtures/css'))
.filter(function(f) {
- return !(/expected/).test(f);
+ return !(/expected/).test(f) && path.extname(f);
})
.map(function(f) {
return path.join('css', f);
View
58 test/tasks/test-usemin.js
@@ -2,7 +2,10 @@
// Mocha generated tests
//
-var helpers = require("../helpers");
+var fs = require("fs"),
+ path = require("path"),
+ assert = require("assert"),
+ helpers = require("../helpers");
describe("USEMIN task", function() {
@@ -35,9 +38,27 @@ describe("USEMIN task", function() {
describe("usemin task with reved imgs", function() {
+ before (function(done) {
+ // XXX move into an helper function, used here and in test-css.js
+ // copy in some files, with @imports to test out the inline imports
+ var files = fs.readdirSync(path.join(__dirname, "../fixtures/css"))
+ .filter(function(f) {
+ return !(/expected/).test(f) & !!path.extname(f);
+ })
+ .map(function(f) {
+ return path.join("css", f);
+ });
+
+ helpers.copy(files, ".test/css", function(err) {
+ if(err) return done(err);
+ // add one level of relative assets, just to see how it goes
+ helpers.copyFile('test/fixtures/css/ui/widget.css', '.test/css/ui/widget.css', done);
+ });
+ });
+
it("Given I run the 'rev usemin' task", function(done) {
// runt the usemin task
- helpers.run("rev usemin", done);
+ helpers.run("css rev usemin", done);
});
it("When the script ends", function(done) {
@@ -49,15 +70,38 @@ describe("USEMIN task", function() {
it("Then '.test/usemin.html' should be the same as 'test/fixtures/usemin/index.html'", function(done) {
// todo: task log output doesn"t return things that were changed between
// <!-- build:<target> path/to/foo.js --> directives
+ helpers.copyFile(".test/usemin.html", "test/fixtures/usemin/reved.html");
helpers.assertFile(".test/usemin.html", "test/fixtures/usemin/reved.html");
done();
});
- it("And I should see 'img/59928801.1.png' in 'css/style.css'.test/usemin.html' should be the same as 'test/fixtures/usemin/index.html'", function(done) {
- // todo: task log output doesn"t return things that were changed between
- // <!-- build:<target> path/to/foo.js --> directives
- helpers.assertFile(".test/usemin.html", "test/fixtures/usemin/reved.html");
- done();
+ it("And I should see 'img/59928801.1.png' in '.test/usemin.html'", function(done) {
+ var test = new RegExp("img/59928801.1.png");
+ fs.readFile(".test/usemin.html", function(err, body) {
+ if(err) return done(err);
+ assert.ok(test.test(body));
+ done();
+ });
+ });
+
+ // XXX add step definition for this one. Should readdir the ./test/css
+ // dir, guessing the revision instead of hardcoding here
+ it("And I should see 'img/f67f4a27.6.jpg' in '.test/css/style.css'", function(done) {
+ var test = new RegExp("img/f67f4a27.6.jpg");
+ fs.readFile(".test/css/e1823e1a.style.css", function(err, body) {
+ if(err) return done(err);
+ assert.ok(test.test(body), 'Missing reved img in style.css');
+ done();
+ });
+ });
+
+ it("And I should see 'img/f67f4a27.6.jpg' in '.test/css/style.css'", function(done) {
+ var test = new RegExp("img/f67f4a27.6.jpg");
+ fs.readFile(".test/css/e1823e1a.style.css", function(err, body) {
+ if(err) return done(err);
+ assert.ok(test.test(body), 'Missing reved img in style.css');
+ done();
+ });
});
});

0 comments on commit e4465c6

Please sign in to comment.