Browse files

New helper to compile single CSS file

  • Loading branch information...
1 parent e9ab556 commit ff22e0dab9669429df832a17de8b5d5553876686 @sergeche committed Jan 4, 2013
Showing with 100 additions and 36 deletions.
  1. +5 −0 .npmignore
  2. +2 −1 lib/css.js
  3. +2 −5 package.json
  4. +79 −30 tasks/frontend.js
  5. +12 −0 test/frontend.js
View
5 .npmignore
@@ -0,0 +1,5 @@
+/node_modules/
+tmp
+
+/test/
+/.build-catalog.json
View
3 lib/css.js
@@ -122,4 +122,5 @@ function compileCSSFile(file, pathResolver, alreadyImported) {
return csso.justDoIt(header + inlinedContent, true);
}
-exports.compileCSSFile = compileCSSFile;
+exports.compileCSSFile = compileCSSFile;
+exports.inlineCSSFile = inlineCSSFile;
View
7 package.json
@@ -1,7 +1,7 @@
{
"name": "grunt-frontend",
"description": "CSS and JS minifier that respects source modification",
- "version": "1.0.0",
+ "version": "1.0.1",
"homepage": "https://github.com/sergeche/grunt-frontend",
"author": {
"name": "Sergey Chikuyonok",
@@ -28,14 +28,11 @@
"test": "grunt test"
},
"dependencies": {
- "grunt": "~0.3.8",
"underscore": ">=1.3.x",
"csso": "*"
},
"devDependencies": {
- "grunt": "~0.3.8",
- "underscore": ">=1.3.x",
- "csso": "*"
+ "grunt": "~0.3.8"
},
"keywords": [
"gruntplugin",
View
109 tasks/frontend.js
@@ -1,5 +1,9 @@
"use strict";
+var fs = require('fs');
+var path = require('path');
+var csso = require('csso');
+
module.exports = function(grunt) {
var cssModule = require('../lib/css');
var crypto = require('crypto');
@@ -128,11 +132,24 @@ module.exports = function(grunt) {
return shouldCompile;
}
+ /**
+ * Check if passed path is a file
+ * @param {String} path
+ * @return {Boolean}
+ */
+ function isFile(path) {
+ if (fs.existsSync(path)) {
+ return fs.statSync(path).isFile();
+ } else {
+ return (/\.\w+$/).test(path);
+ }
+ }
+
/**
* Register reusable CSS compiler helper
* @param {Object} data Task payload
* @param {Object} config Task config (can be obtained from getConfig() method)
- * @param {Object} catalog Pointer resources to catalog (can be obtained fron loadCatalog())
+ * @param {Object} catalog Pointer resources to catalog (can be obtained from loadCatalog())
*/
grunt.registerHelper('frontend-css', function(data, config, catalog) {
if (!('src' in data)) {
@@ -144,46 +161,78 @@ module.exports = function(grunt) {
}
catalog = catalog || {};
- var force = config.force;
var srcDir = makeAbsPath(data.src);
var destDir = makeAbsPath(data.dest);
- var webroot = config.webroot;
-
- grunt.file.mkdir(destDir);
// read all css files
var reCSSFile = /\.css$/i;
var reSkip = config.skipNames || reSkipCSSFileName;
var resolver = createPathResolver(config.srcWebroot);
grunt.file.recurse(srcDir, function(abspath, rootdir, subdir, filename) {
if (reCSSFile.test(abspath) && !reSkip.test(filename)) {
- var destFile = path.join(destDir, subdir, filename);
- var catalogName = filePathForCatalog(destFile, webroot);
- var srcCatalogName = filePathForCatalog(abspath, config.srcWebroot);
-
- grunt.log.writeln('\nReading ' + filePathForCatalog(abspath, config.srcWebroot));
- var imports = {};
- var min = cssModule.compileCSSFile(abspath, resolver, imports);
-
- // check if we should re-save compiled file
- // thus change its content and modification date
- var hash = md5(min);
-
- if (!force && catalogName in catalog && catalog[catalogName].md5 === hash && fs.existsSync(destFile)) {
- grunt.log.writeln('File is not modified, skipping');
- return;
- }
-
- grunt.log.writeln('Saving minified version to ' + filePathForCatalog(destFile, webroot));
- grunt.file.write(path.join(destDir, subdir, filename), min);
-
- catalog[catalogName] = {
- md5: hash,
- date: timestamp(),
- files: [srcCatalogName]
- };
+ var payload = {};
+ payload[path.join(destDir, subdir, filename)] = abspath;
+ grunt.helper('frontend-css-file', payload, config, catalog);
+ }
+ });
+
+ return catalog;
+ });
+
+ /**
+ * Compiles single CSS file
+ * @param {Object} data Task payload
+ * @param {Object} config Task config (can be obtained from getConfig() method)
+ * @param {Object} catalog Pointer resources to catalog (can be obtained from loadCatalog())
+ */
+ grunt.registerHelper('frontend-css-file', function(data, config, catalog) {
+ catalog = catalog || {};
+
+ var resolver = createPathResolver(config.srcWebroot);
+
+ _.each(data, function(src, dest) {
+ var destFile = makeAbsPath(dest);
+ grunt.file.mkdir(path.dirname(destFile));
+
+ var imports = {};
+ var keepImports = [];
+ var srcCatalogFiles = [];
+
+ // sequentially inline all source CSS files into a singe one
+ var max = _.map(grunt.file.expandFiles(src), function(f) {
+ var srcFile = makeAbsPath(f);
+ srcCatalogFiles.push(filePathForCatalog(srcFile, config.srcWebroot));
+ grunt.log.writeln('\nReading ' + _.last(srcCatalogFiles));
+
+ return cssModule.inlineCSSFile(srcFile, resolver, keepImports, imports);
+ }).join('');
+
+ // create file header with @imports that should be kept
+ var header = _.map(keepImports, function(imp) {
+ return imp.value;
+ }).join(';\n') + '\n';
+
+ // minify CSS
+ var min = csso.justDoIt(header + max, true);
+
+ // check if we should re-save compiled file
+ // thus change its content and modification date
+ var hash = md5(min);
+ var catalogName = filePathForCatalog(destFile, config.webroot);
+ if (!config.force && catalogName in catalog && catalog[catalogName].md5 === hash && fs.existsSync(destFile)) {
+ grunt.log.writeln('File is not modified, skipping');
+ return;
}
+
+ grunt.log.writeln('Saving minified version to ' + catalogName);
+ grunt.file.write(destFile, min);
+
+ catalog[catalogName] = {
+ md5: hash,
+ date: timestamp(),
+ files: srcCatalogFiles
+ };
});
return catalog;
View
12 test/frontend.js
@@ -43,6 +43,18 @@ exports.testGrunt = {
test.done();
},
+ cssSingle: function(test) {
+ var payload = {};
+ payload[pathResolver('out/css/single.css')] = pathResolver('css/test-utf.css');
+
+ var catalog = grunt.helper('frontend-css-file', payload, config);
+
+ test.ok(catalog, 'Single CSS compiled successfully');
+ test.ok('/css/single.css' in catalog, 'Has single.css');
+
+ test.done();
+ },
+
js: function(test) {
var payload = {
'test/out/js/f.js': [

0 comments on commit ff22e0d

Please sign in to comment.