var path = require('path'); module.exports = function (grunt) { // -- Config ------------------------------------------------------------------- grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), // -- Constants ------------------------------------------------------------ BUILD_COMMENT: 'THIS FILE IS GENERATED BY A BUILD SCRIPT - DO NOT EDIT!', NORMALIZE_LICENSE: [ '/*! normalize.css v1.1.1 | MIT License | git.io/normalize */', '/*! Copyright (c) Nicolas Gallagher and Jonathan Neal */', '\n' ].join('\n'), // -- Clean Config --------------------------------------------------------- clean: { build : ['build/'], build_res: ['build/*-r.css'], release : ['release/<%= pkg.version %>/'], base : ['src/base/css/', 'src/base/tests/', 'src/base/LICENSE.md'] }, // -- Copy Config ---------------------------------------------------------- copy: { build: { expand : true, flatten: true, src : 'src/**/css/*.css', dest : 'build/', rename: function (dest, src) { // normalize -> base src = src.replace(/^normalize(-.+\.css|\.css)$/, 'base$1'); return path.join(dest, src); } }, normalize: { expand : true, flatten: true, cwd : '../normalize.css/', src : '{LICENSE.md,normalize.css,test.html}', dest : 'src/base/', rename: function (dest, file) { if (grunt.file.isMatch('*.css', file)) { return path.join(dest, 'css', file); } if (grunt.file.isMatch('*.html', file)) { return path.join(dest, 'tests', 'manual', file); } return path.join(dest, file); }, options: { processContent: function (content, file) { var comment = grunt.config('BUILD_COMMENT'); if (grunt.file.isMatch({matchBase: true}, '*.css', file)) { content = '/* ' + comment + ' */\n' + content; } else if (grunt.file.isMatch({matchBase: true}, '*.html', file)) { content = '\n' + content; } return content; } } } }, // -- Concat Config -------------------------------------------------------- concat: { build: { files: [ {'build/buttons.css': [ 'build/buttons-core.css', 'build/buttons.css' ]}, {'build/forms-nr.css': [ 'build/forms-core.css', 'build/forms.css' ]}, {'build/forms.css': [ 'build/forms-nr.css', 'build/forms-r.css' ]}, {'build/grids-nr.css': [ 'build/grids-core.css', 'build/grids-units.css' ]}, {'build/grids.css': [ 'build/grids-nr.css', 'build/grids-r.css' ]}, {'build/menus-nr.css': [ 'build/menus-core.css', 'build/menus.css', 'build/menus-paginator.css' ]}, {'build/menus.css': [ 'build/menus-nr.css', 'build/menus-r.css' ]} ] }, kimono: { files: { 'build/kimono-min.css': [ 'build/base-min.css', 'build/buttons-min.css', 'build/forms-min.css', 'build/grids-min.css', 'build/menus-min.css', 'build/tables-min.css' ], 'build/kimono-nr-min.css': [ 'build/base-min.css', 'build/buttons-min.css', 'build/forms-nr-min.css', 'build/grids-nr-min.css', 'build/menus-nr-min.css', 'build/tables-min.css' ] } } }, // -- CSSMin Config -------------------------------------------------------- cssmin: { options: { // report: 'gzip' }, files: { expand: true, src : 'build/*.css', ext : '-min.css' } }, // -- Compress Config ------------------------------------------------------ compress: { release: { options: { archive: 'release/<%= pkg.version %>/<%= pkg.name %>-<%= pkg.version %>.zip' }, expand : true, flatten: true, src : 'build/*.css', dest : '<%= pkg.name %>/<%= pkg.version %>/' } }, // -- Contextualize Config ------------------------------------------------- contextualize: { normalize: { src : 'src/base/css/normalize.css', dest: 'src/base/css/normalize-context.css', options: { prefix: '.k', banner: '/* <%= BUILD_COMMENT %> */\n<%= NORMALIZE_LICENSE %>' } } } }); // -- Main Tasks --------------------------------------------------------------- grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-compress'); grunt.registerTask('default', [ 'clean:build', 'copy:build', 'concat:build', 'clean:build_res', 'cssmin', 'concat:kimono' ]); grunt.registerTask('import', [ 'import-normalize' ]); grunt.registerTask('release', [ 'default', 'clean:release', 'compress:release' ]); // -- Import Tasks ------------------------------------------------------------- grunt.registerTask('import-normalize', [ 'clean:base', 'copy:normalize', 'contextualize:normalize' ]); // -- Contextualize Task ------------------------------------------------------- grunt.registerMultiTask('contextualize', 'Makes Contextualized CSS files.', function () { var Parser = require('parserlib').css.Parser, done = this.async(), options = this.options({banner: ''}), banner = grunt.template.process(options.banner), processing = 0; function oneDone() { if (!(processing -= 1)) { done(); } } this.files.forEach(function (filePair) { filePair.src.forEach(function (file) { var src = grunt.file.read(file), contextual = banner, parser = new Parser(); parser.addListener('endstylesheet', function () { grunt.file.write(filePair.dest, contextual); grunt.log.writeln('File "' + filePair.dest + '" created.'); oneDone(); }); // Fired right before CSS properties are parsed for a certain rule. // Go through and add all the selectors to the `css` string. parser.addListener('startrule', function (event) { var prefix = options.prefix; event.selectors.forEach(function (selector, i) { var nextSelector = event.selectors[i + 1]; // If the selector does not contain the html selector, we // can go ahead and prepend .k in front of it. if (selector.text.indexOf('html') === -1) { contextual += prefix + ' ' + selector.text; } else if (selector.text.indexOf('html') !== -1) { // If it contains `html`, replace the `html` with `.k`. // Replace multiple spaces with a single space. This is // for the case where `html input[type='button']` comes // through as `html input[type='button']`. contextual += selector.text.replace('html', prefix).replace(/ +/g, ' '); } // If theres another selector, add a comma. if (nextSelector) { contextual += ',\n'; } else { // Otherwise, add an opening bracket for properties contextual += ' {\n'; } }); }); // Fired right after CSS properties are parsed for a certain rule. // Add the closing bracket to end the CSS Rule. parser.addListener('endrule', function (event) { contextual += '}\n'; }); // Fired for each property that the parser encounters. Add these // properties to the `css` string with 4 spaces. parser.addListener('property', function (event) { // Add 4 spaces tab. contextual += ' ' + event.property + ': ' + event.value + ';\n'; }); // Do the parsing. processing += 1; parser.parse(src); }); }); }); };