Skip to content

Instantly share code, notes, and snippets.

@jonschlinkert
Forked from brianfeister/attach_heads.js
Created December 19, 2012 03:49
Show Gist options
  • Save jonschlinkert/4334244 to your computer and use it in GitHub Desktop.
Save jonschlinkert/4334244 to your computer and use it in GitHub Desktop.
/**
* Task: attach_heads
* Description: Set the heads for all themes declared in themes.json
*/
module.exports = function(grunt) {
'use strict';
var fs = require('fs');
var path = require('path');
grunt.registerTask('attach_heads', 'Set the heads recursively for all JS/CSS in themes.json', function() {
var themeMetaObj = grunt.file.readJSON('themes.json');
var pkgObject = grunt.file.readJSON('package.json');
var banner =
' (v.'+pkgObject.version+')\n' +
' * by '+pkgObject.name+' \n' +
' * '+pkgObject.homepage+'\n' +
' * Copyright (c) '+grunt.template.today("yyyy")+' '+pkgObject.name+'\n' +
' * \n' +
' * ============================================= */ \n';
// iterate over the themeMetaObj for number of themes (default is declared here as well)
for ( var key in themeMetaObj ) {
var thisTheme = themeMetaObj[key];
var headObj = {
'devCss' : '../'+thisTheme._name+'/assets/css/main.css',
'prodCss' : '../'+thisTheme._name+'/assets/css/main.min.css',
'devJs' : '../'+thisTheme._name+'/assets/js/scripts.js',
'prodJs' : '../'+thisTheme._name+'/assets/js/scripts.min.js'
};
var thisBanner = '';
thisBanner = '/*! ================================================ \n' +
' * \n' +
' * '+thisTheme._long_name+' Theme ' +
banner;
for ( var fileKey in headObj ) {
var thisFile = headObj[fileKey];
var content = grunt.file.read( thisFile );
content = thisBanner + content;
grunt.file.write( thisFile, content );
grunt.log.writeln('"' + thisFile + '" updated with latest head.');
}
}
});
};
/*jshint laxcomma:true */
module.exports = function(grunt) {
grunt.initConfig({
pkg: '<json:package.json>',
themeMeta: '<json:themes.json>',
lint: {
files: ['assets/js/_*.js', 'grunt.js']
},
recess: {
// set dynamically in generateThemeConfig()
},
concat: {
// set dynamically in generateThemeConfig()
// full listing of original bootstrap plugins
// "_js_includes" : [
// "assets/js/plugins/bootstrap/bootstrap-transition.js",
// "assets/js/plugins/bootstrap/bootstrap-alert.js",
// "assets/js/plugins/bootstrap/bootstrap-button.js",
// "assets/js/plugins/bootstrap/bootstrap-carousel.js",
// "assets/js/plugins/bootstrap/bootstrap-collapse.js",
// "assets/js/plugins/bootstrap/bootstrap-dropdown.js",
// "assets/js/plugins/bootstrap/bootstrap-modal.js",
// "assets/js/plugins/bootstrap/bootstrap-tooltip.js",
// "assets/js/plugins/bootstrap/bootstrap-popover.js",
// "assets/js/plugins/bootstrap/bootstrap-scrollspy.js",
// "assets/js/plugins/bootstrap/bootstrap-tab.js",
// "assets/js/plugins/bootstrap/bootstrap-typeahead.js",
// "assets/js/plugins/*.js",
// "assets/js/_*.js"
// ]
},
min: {
// set dynamically in generateThemeConfig()
},
mincss: {
// set dynamically in generateThemeConfig()
},
watch: {
// set dynamically in generateThemeConfig()
}
});
grunt.loadTasks('build/tasks');
grunt.loadNpmTasks('grunt-contrib');
grunt.loadNpmTasks('grunt-recess');
function generateThemeConfig( registerThemeTask ) {
var i
, len
, o
, allTasksLen
, msg
, themeMetaObj = grunt.file.readJSON('themes.json')
, pkgObject = grunt.file.readJSON('package.json')
// tasks performed on all themes are declared in package.json
, themeSpecificTasks = pkgObject.themeSpecificTasks;
// iterate over the themeMetaObj for number of themes (default is declared here as well)
for ( var key in themeMetaObj ) {
var thisTheme = themeMetaObj[key]
, taskArray = [];
grunt.config( 'recess.'+thisTheme._name+'DevCss', {
src: 'child_themes/'+thisTheme._name+'/master.less',
dest: '../'+thisTheme._name+'/assets/css/main.css',
options: {
compile: true
}
});
grunt.config( 'recess.'+thisTheme._name+'ProdCss', {
src: 'child_themes/'+thisTheme._name+'/master.less',
dest: '../'+thisTheme._name+'/assets/css/main.min.css',
options: {
compile: true,
compress: true
}
});
grunt.config( 'concat.'+thisTheme._name, {
src: thisTheme._js_includes,
dest: '../'+thisTheme._name+'/assets/js/scripts.js'
});
grunt.config( 'min.'+thisTheme._name, {
src: thisTheme._js_includes,
dest: '../'+thisTheme._name+'/assets/js/scripts.min.js'
});
}
registerThemeTask();
}
// register themes as a callback to ensure config is generated first
generateThemeConfig( function() {
var themeMetaObj = grunt.file.readJSON('themes.json')
, pkgObject = grunt.file.readJSON('package.json')
// tasks performed on all themes are declared in package.json
// in attribute name `themeSpecificTasks`
, themeSpecificTasks = pkgObject.themeSpecificTasks
, allTaskArray = [];
// iterate over the themeMetaObj for number of themes (default is declared here as well)
for ( var key in themeMetaObj ) {
var thisTheme = themeMetaObj[key]
, taskArray = [];
// iterate over preLoopTasks (set in package.json) and push them
// into the array for this theme
for ( var preLoopTasksKey in pkgObject.preLoopTasks ) {
taskArray.push( pkgObject.preLoopTasks[preLoopTasksKey] );
}
// iterate over theme-specific tasks and push them into
// theme-specific task array
for ( var tasksKey in themeSpecificTasks ) {
var thisTaskObj = themeSpecificTasks[tasksKey];
// grunt.log.writeln( grunt.log.writeflags( thisTaskObj, 'thisTaskObj') );
// take thisTask and check to see if it has an array of length
// if > 0, then we need multiple "sub-tasks" and we assign them
if ( thisTaskObj.length > 0 ) {
for (var x = 0; x < thisTaskObj.length; x++) {
taskArray.push( tasksKey+':'+thisTheme._name+thisTaskObj[x] );
}
} else {
taskArray.push( tasksKey+':'+thisTheme._name );
}
}
allTaskArray = allTaskArray.concat( taskArray );
// iterate over postLoopTasks (set in package.json) and push them
// into the array for this theme
for ( var postLoopTasksKey in pkgObject.postLoopTasks ) {
taskArray.push( pkgObject.postLoopTasks[postLoopTasksKey] );
}
grunt.registerTask( 'theme:'+thisTheme._name, taskArray);
}
// function to find and remove elements from an array
function removeArr(arr) {
var what, a = arguments, L = a.length, ax;
while (L > 1 && arr.length) {
what = a[--L];
while ((ax= arr.indexOf(what)) !== -1) {
arr.splice(ax, 1);
}
}
return arr;
}
for ( var loopTask in pkgObject.preLoopTasks ) {
removeArr( allTaskArray, pkgObject.preLoopTasks[loopTask]);
allTaskArray.unshift( pkgObject.preLoopTasks[loopTask] );
}
allTaskArray = allTaskArray.concat( pkgObject.postLoopTasks );
grunt.registerTask( 'default', allTaskArray );
});
};
{
"name": "example.com",
"description": "Tagline here",
"version": "1.0",
"homepage": "http://example.com",
"author": "[email protected]",
"dependencies": {
"grunt": "~0.3.15",
"grunt-contrib": "~0.2.0",
"grunt-recess": "~0.1.1",
"uglify-js": "~1.3.3",
"jshint": "~0.5.9"
},
"devDependencies": {},
"preLoopTasks" : [
"lint"
],
"postLoopTasks" : [
"enqueue_ver",
"attach_heads"
],
"themeSpecificTasks" : {
"recess" : [
"DevCss",
"ProdCss"
],
"concat" : [],
"min" : []
},
"attach_heads_to" : {
"devCss" : "/assets/css/main.css",
"prodCss" : "/assets/css/main.min.css",
"devJs" : "/assets/js/scripts.js",
"prodJs" : "/assets/js/scripts.min.js"
}
}
{
"default" : {
"_name" : "default",
"_long_name" : "Default",
"_js_includes" : [
"assets/js/plugins/bootstrap/bootstrap-transition.js",
"assets/js/plugins/bootstrap/bootstrap-alert.js",
"assets/js/plugins/bootstrap/bootstrap-button.js",
"assets/js/plugins/bootstrap/bootstrap-carousel.js",
"assets/js/plugins/bootstrap/bootstrap-collapse.js",
"assets/js/plugins/bootstrap/bootstrap-dropdown.js",
"assets/js/plugins/bootstrap/bootstrap-modal.js",
"assets/js/plugins/bootstrap/bootstrap-tooltip.js",
"assets/js/plugins/bootstrap/bootstrap-popover.js",
"assets/js/plugins/bootstrap/bootstrap-scrollspy.js",
"assets/js/plugins/bootstrap/bootstrap-tab.js",
"assets/js/plugins/bootstrap/bootstrap-typeahead.js",
"assets/js/plugins/*.js",
"assets/js/_*.js"
]
},
"foo" : {
"_name" : "foo",
"_long_name" : "Foo",
"_js_includes" : [
"assets/js/plugins/bootstrap/bootstrap-transition.js",
"assets/js/plugins/bootstrap/bootstrap-alert.js",
"assets/js/plugins/bootstrap/bootstrap-button.js",
"assets/js/plugins/bootstrap/bootstrap-collapse.js",
"assets/js/plugins/bootstrap/bootstrap-dropdown.js",
"assets/js/plugins/bootstrap/bootstrap-tooltip.js",
"assets/js/plugins/bootstrap/bootstrap-popover.js",
"assets/js/plugins/*.js",
"assets/js/_*.js"
]
},
"bar" : {
"_name" : "bar",
"_long_name" : "Bar",
"_js_includes" : [
"assets/js/plugins/bootstrap/bootstrap-transition.js",
"assets/js/plugins/bootstrap/bootstrap-alert.js",
"assets/js/plugins/bootstrap/bootstrap-button.js",
"assets/js/plugins/bootstrap/bootstrap-collapse.js",
"assets/js/plugins/bootstrap/bootstrap-dropdown.js",
"assets/js/plugins/bootstrap/bootstrap-tooltip.js",
"assets/js/plugins/bootstrap/bootstrap-popover.js",
"assets/js/plugins/*.js",
"assets/js/_*.js"
]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment