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.

Revisions

  1. Brian Feister revised this gist Dec 16, 2012. 1 changed file with 7 additions and 1 deletion.
    8 changes: 7 additions & 1 deletion package.json
    Original file line number Diff line number Diff line change
    @@ -26,5 +26,11 @@
    ],
    "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"
    }
    }
    }
  2. Brian Feister revised this gist Dec 16, 2012. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions grunt.js
    Original file line number Diff line number Diff line change
    @@ -62,7 +62,6 @@ module.exports = function(grunt) {
    , taskArray = [];

    grunt.config( 'recess.'+thisTheme._name+'DevCss', {
    // set dynamically in generateThemeBundles()
    src: 'child_themes/'+thisTheme._name+'/master.less',
    dest: '../'+thisTheme._name+'/assets/css/main.css',
    options: {
    @@ -71,7 +70,6 @@ module.exports = function(grunt) {
    });

    grunt.config( 'recess.'+thisTheme._name+'ProdCss', {
    // set dynamically in generateThemeBundles()
    src: 'child_themes/'+thisTheme._name+'/master.less',
    dest: '../'+thisTheme._name+'/assets/css/main.min.css',
    options: {
  3. Brian Feister revised this gist Dec 16, 2012. 3 changed files with 87 additions and 53 deletions.
    92 changes: 66 additions & 26 deletions grunt.js
    Original file line number Diff line number Diff line change
    @@ -3,9 +3,6 @@ module.exports = function(grunt) {
    grunt.initConfig({
    pkg: '<json:package.json>',
    themeMeta: '<json:themes.json>',
    meta: {
    // // set dynamically in generateThemeConfig()
    },
    lint: {
    files: ['assets/js/_*.js', 'grunt.js']
    },
    @@ -14,6 +11,24 @@ module.exports = function(grunt) {
    },
    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()
    @@ -46,27 +61,18 @@ module.exports = function(grunt) {
    var thisTheme = themeMetaObj[key]
    , taskArray = [];

    grunt.config( 'meta.'+thisTheme._name, {
    banner: '/*! ================================================\n' +
    ' * '+thisTheme._long_name+' Theme by example.co \n' +
    ' * v.<%= pkg.version %>\n' +
    ' * Copyright (c) <%= grunt.template.today("yyyy") %> ' +
    ' example.Co */\n' +
    ' * ================================================ */'
    });

    grunt.config( 'recess.'+thisTheme._name+'Dev', {
    grunt.config( 'recess.'+thisTheme._name+'DevCss', {
    // set dynamically in generateThemeBundles()
    src: 'assets/css/less/'+thisTheme._name+'/master.less',
    src: 'child_themes/'+thisTheme._name+'/master.less',
    dest: '../'+thisTheme._name+'/assets/css/main.css',
    options: {
    compile: true
    }
    });

    grunt.config( 'recess.'+thisTheme._name+'Prod', {
    grunt.config( 'recess.'+thisTheme._name+'ProdCss', {
    // set dynamically in generateThemeBundles()
    src: 'assets/css/less/'+thisTheme._name+'/master.less',
    src: 'child_themes/'+thisTheme._name+'/master.less',
    dest: '../'+thisTheme._name+'/assets/css/main.min.css',
    options: {
    compile: true,
    @@ -78,16 +84,16 @@ module.exports = function(grunt) {
    src: thisTheme._js_includes,
    dest: '../'+thisTheme._name+'/assets/js/scripts.js'
    });

    grunt.config( 'min.'+thisTheme._name, {
    src: ['<'+thisTheme._name+'Banner>', 'assets/js/scripts.js'],
    src: thisTheme._js_includes,
    dest: '../'+thisTheme._name+'/assets/js/scripts.min.js'
    });

    }

    registerThemeTask();
    }

    // grunt.log.writeln( grunt.log.writeflags( grunt.config.get(), prefix) );

    // register themes as a callback to ensure config is generated first
    generateThemeConfig( function() {
    @@ -104,22 +110,56 @@ module.exports = function(grunt) {
    var thisTheme = themeMetaObj[key]
    , taskArray = [];

    // now that our config is setup, let's register this as a MultiTask
    taskArray = ['lint'];
    // 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 ) {
    if ( themeSpecificTasks[tasksKey] === 'recess' ) {
    taskArray.push( themeSpecificTasks[tasksKey]+':'+thisTheme._name+'Dev' );
    taskArray.push( themeSpecificTasks[tasksKey]+':'+thisTheme._name+'Prod' );
    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( themeSpecificTasks[tasksKey]+':'+thisTheme._name );
    taskArray.push( tasksKey+':'+thisTheme._name );
    }
    }
    taskArray.push( 'enqueue_ver' );
    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 );

    });
    22 changes: 15 additions & 7 deletions package.json
    Original file line number Diff line number Diff line change
    @@ -12,11 +12,19 @@
    "jshint": "~0.5.9"
    },
    "devDependencies": {},
    "themeSpecificTasks" : [
    "recess",
    "concat",
    "min",
    "mincss",
    "enqueue_ver"
    ]
    "preLoopTasks" : [
    "lint"
    ],
    "postLoopTasks" : [
    "enqueue_ver",
    "attach_heads"
    ],
    "themeSpecificTasks" : {
    "recess" : [
    "DevCss",
    "ProdCss"
    ],
    "concat" : [],
    "min" : []
    }
    }
    26 changes: 6 additions & 20 deletions themes.json
    Original file line number Diff line number Diff line change
    @@ -19,9 +19,9 @@
    "assets/js/_*.js"
    ]
    },
    "vintage" : {
    "_name" : "vintage",
    "_long_name" : "Vintage",
    "foo" : {
    "_name" : "foo",
    "_long_name" : "Foo",
    "_js_includes" : [
    "assets/js/plugins/bootstrap/bootstrap-transition.js",
    "assets/js/plugins/bootstrap/bootstrap-alert.js",
    @@ -34,23 +34,9 @@
    "assets/js/_*.js"
    ]
    },
    "pure" : {
    "_name" : "pure",
    "_long_name" : "Pure",
    "_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"
    ]
    }, "mystique" : {
    "_name" : "mystique",
    "_long_name" : "Mystique",
    "bar" : {
    "_name" : "bar",
    "_long_name" : "Bar",
    "_js_includes" : [
    "assets/js/plugins/bootstrap/bootstrap-transition.js",
    "assets/js/plugins/bootstrap/bootstrap-alert.js",
  4. Brian Feister revised this gist Dec 16, 2012. 1 changed file with 46 additions and 0 deletions.
    46 changes: 46 additions & 0 deletions attach_heads.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,46 @@
    /**
    * 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.');
    }
    }
    });
    };
  5. Brian Feister revised this gist Dec 16, 2012. 1 changed file with 25 additions and 15 deletions.
    40 changes: 25 additions & 15 deletions grunt.js
    Original file line number Diff line number Diff line change
    @@ -29,7 +29,6 @@ module.exports = function(grunt) {
    grunt.loadTasks('build/tasks');
    grunt.loadNpmTasks('grunt-contrib');
    grunt.loadNpmTasks('grunt-recess');
    grunt.registerTask('default', 'lint recess concat min mincss enqueue_ver');

    function generateThemeConfig( registerThemeTask ) {
    var i
    @@ -56,7 +55,7 @@ module.exports = function(grunt) {
    ' * ================================================ */'
    });

    grunt.config( 'recess.'+thisTheme._name, {
    grunt.config( 'recess.'+thisTheme._name+'Dev', {
    // set dynamically in generateThemeBundles()
    src: 'assets/css/less/'+thisTheme._name+'/master.less',
    dest: '../'+thisTheme._name+'/assets/css/main.css',
    @@ -65,6 +64,16 @@ module.exports = function(grunt) {
    }
    });

    grunt.config( 'recess.'+thisTheme._name+'Prod', {
    // set dynamically in generateThemeBundles()
    src: 'assets/css/less/'+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'
    @@ -74,28 +83,21 @@ module.exports = function(grunt) {
    dest: '../'+thisTheme._name+'/assets/js/scripts.min.js'
    });

    // set strings as vars, config function doesn't accept inline concatenation
    var minFileOut = '../'+thisTheme._name+'/assets/css/main.min.css'
    , minFileIn = '../'+thisTheme._name+'/assets/css/main.css';
    grunt.config( 'mincss.'+thisTheme._name, {
    compress: {
    files: {
    minFileOut : [ '<meta:'+thisTheme._name+'.banner>', minFileIn ]
    }
    }
    });
    }
    registerThemeTask();
    }

    // grunt.log.writeln( grunt.log.writeflags( grunt.config.get(), prefix) );

    // 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;
    , themeSpecificTasks = pkgObject.themeSpecificTasks
    , allTaskArray = [];

    // iterate over the themeMetaObj for number of themes (default is declared here as well)
    for ( var key in themeMetaObj ) {
    @@ -105,13 +107,21 @@ module.exports = function(grunt) {
    // now that our config is setup, let's register this as a MultiTask
    taskArray = ['lint'];
    for ( var tasksKey in themeSpecificTasks ) {
    taskArray.push( themeSpecificTasks[tasksKey]+':'+thisTheme._name );
    if ( themeSpecificTasks[tasksKey] === 'recess' ) {
    taskArray.push( themeSpecificTasks[tasksKey]+':'+thisTheme._name+'Dev' );
    taskArray.push( themeSpecificTasks[tasksKey]+':'+thisTheme._name+'Prod' );
    } else {
    taskArray.push( themeSpecificTasks[tasksKey]+':'+thisTheme._name );
    }
    }
    taskArray.push( 'enqueue_ver' );
    // grunt.log.writeln('taskArray ="'+taskArray+'"');
    allTaskArray = allTaskArray.concat( taskArray );

    grunt.registerTask( 'theme:'+thisTheme._name, taskArray);
    }

    grunt.registerTask( 'default', allTaskArray );

    });

    };
  6. Brian Feister revised this gist Dec 15, 2012. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions grunt.js
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@ module.exports = function(grunt) {
    // // set dynamically in generateThemeConfig()
    },
    lint: {
    files: ['assets/js/_*.js']
    files: ['assets/js/_*.js', 'grunt.js']
    },
    recess: {
    // set dynamically in generateThemeConfig()
    @@ -85,11 +85,11 @@ module.exports = function(grunt) {
    }
    });
    }
    registerThemeTask( thisTheme );
    };
    registerThemeTask();
    }

    // register themes as a callback to ensure config is generated first
    generateThemeConfig( function( thisTheme ) {
    generateThemeConfig( function() {

    var themeMetaObj = grunt.file.readJSON('themes.json')
    , pkgObject = grunt.file.readJSON('package.json')
  7. Brian Feister created this gist Dec 15, 2012.
    117 changes: 117 additions & 0 deletions grunt.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,117 @@
    /*jshint laxcomma:true */
    module.exports = function(grunt) {
    grunt.initConfig({
    pkg: '<json:package.json>',
    themeMeta: '<json:themes.json>',
    meta: {
    // // set dynamically in generateThemeConfig()
    },
    lint: {
    files: ['assets/js/_*.js']
    },
    recess: {
    // set dynamically in generateThemeConfig()
    },
    concat: {
    // set dynamically in generateThemeConfig()
    },
    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');
    grunt.registerTask('default', 'lint recess concat min mincss enqueue_ver');

    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( 'meta.'+thisTheme._name, {
    banner: '/*! ================================================\n' +
    ' * '+thisTheme._long_name+' Theme by example.co \n' +
    ' * v.<%= pkg.version %>\n' +
    ' * Copyright (c) <%= grunt.template.today("yyyy") %> ' +
    ' example.Co */\n' +
    ' * ================================================ */'
    });

    grunt.config( 'recess.'+thisTheme._name, {
    // set dynamically in generateThemeBundles()
    src: 'assets/css/less/'+thisTheme._name+'/master.less',
    dest: '../'+thisTheme._name+'/assets/css/main.css',
    options: {
    compile: true
    }
    });

    grunt.config( 'concat.'+thisTheme._name, {
    src: thisTheme._js_includes,
    dest: '../'+thisTheme._name+'/assets/js/scripts.js'
    });
    grunt.config( 'min.'+thisTheme._name, {
    src: ['<'+thisTheme._name+'Banner>', 'assets/js/scripts.js'],
    dest: '../'+thisTheme._name+'/assets/js/scripts.min.js'
    });

    // set strings as vars, config function doesn't accept inline concatenation
    var minFileOut = '../'+thisTheme._name+'/assets/css/main.min.css'
    , minFileIn = '../'+thisTheme._name+'/assets/css/main.css';
    grunt.config( 'mincss.'+thisTheme._name, {
    compress: {
    files: {
    minFileOut : [ '<meta:'+thisTheme._name+'.banner>', minFileIn ]
    }
    }
    });
    }
    registerThemeTask( thisTheme );
    };

    // register themes as a callback to ensure config is generated first
    generateThemeConfig( function( thisTheme ) {

    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;

    // iterate over the themeMetaObj for number of themes (default is declared here as well)
    for ( var key in themeMetaObj ) {
    var thisTheme = themeMetaObj[key]
    , taskArray = [];

    // now that our config is setup, let's register this as a MultiTask
    taskArray = ['lint'];
    for ( var tasksKey in themeSpecificTasks ) {
    taskArray.push( themeSpecificTasks[tasksKey]+':'+thisTheme._name );
    }
    taskArray.push( 'enqueue_ver' );
    // grunt.log.writeln('taskArray ="'+taskArray+'"');

    grunt.registerTask( 'theme:'+thisTheme._name, taskArray);
    }
    });

    };
    22 changes: 22 additions & 0 deletions package.json
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,22 @@
    {
    "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": {},
    "themeSpecificTasks" : [
    "recess",
    "concat",
    "min",
    "mincss",
    "enqueue_ver"
    ]
    }
    66 changes: 66 additions & 0 deletions themes.json
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,66 @@
    {
    "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"
    ]
    },
    "vintage" : {
    "_name" : "vintage",
    "_long_name" : "Vintage",
    "_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"
    ]
    },
    "pure" : {
    "_name" : "pure",
    "_long_name" : "Pure",
    "_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"
    ]
    }, "mystique" : {
    "_name" : "mystique",
    "_long_name" : "Mystique",
    "_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"
    ]
    }
    }