0

I'm attempting to create a Jade task that will have a build and dev task that have very similar options, except a dev boolean, and a different destination. The simplest way I've been able to achieve this is:

jade: {
    dev: {
        options: {
            data: {
                dev: true, // dev true
                config: ...,
                pkg: ...,
                helpers: ...
            }
        },
        files: [{
            dest: '<%= config.workingDir %>',
            ...
        }]
    },
    build: {
        options: {
            data: {  // no dev
                config: ...,
                pkg: ...,
                helpers: ...
            }
        },
        files: [{
            dest: '<%= config.buildDir %>',
            ...
        }]
    }
}

There's considerable repetition in this though, particularly if I want to add more options down the track. So I'm trying to create one build task that will work both from command line and from a watch task.

The closest I've gotten is this setup, where I can run grunt jade --dev from the command line but can't set the dev boolean in the watch task.

build: {
    options: {
        data: {
            dev: '<%= grunt.option("dev") %>',
            config: ...,
            pkg: ...,
            helpers: ...
        }
    },
    files: [{
        dest: '<%= grunt.option("dev") ? config.workingDir : config.buildDir %>',
        ...
    }]
}

The watch task:

watch: {
    jade: {
        ...
        tasks: ['jade'] // the option is false
    }
}

I've also attempted to create a custom task that sets the option and then runs watch, which when listening to the watch event I can see the option is correctly set

grunt.registerTask('dev', 'Grunt dev mode', function(){
    grunt.option('dev', true);
    grunt.task.run('watch');
});

grunt.event.on('watch', function(action, filepath, target) {
    console.log(grunt.option('dev')); // true
});

Even though the log shows the dev boolean as true the wrong task options are being passed. So, with all that said, am I going about setting options the right way or am I just stuck with having a build and dev task that repeat the same information?

I've also tried using the grunt.util._.expand method with little success. data: "<%= grunt.util._.extend(jade.options.data, {dev: true}) %>",

Anton
  • 113
  • 1
  • 7

1 Answers1

2

You can specify options at the task level that will serve as the default and then further specify target (dev vs build) specific options at the target level. That way you avoid repeating the same configuration between multiple targets:

jade: {
    options : {
        config: ...,
        pkg: ...,
        helpers: ...
    },
    dev: {
        options: {
            dev : true
        },
        files: [{
            dest: '<%= config.workingDir %>',
            ...
        }]
    },
    build: {
        files: [{
            dest: '<%= config.buildDir %>',
            ...
        }]
    }
}

UPDATE

Based on the comment that in the jade case the options all need to be in data, and if the method above was used, the local data would completely override the global data, you could do this since the Gruntfile.js is just JavaScript:

var dataConfigBuild = {
    config: ...,
    pkg: ...,
    helpers: ...
};

//use your favorite way of "cloning" an object
var dataConfigDev = {};
for(var propName in dataConfigBuild) {
  dataConfigDev[propName] = dataConfigBuild[propName];
}

//and add the dev specific stuff
dataConfigDev.dev = true;

And then use like this in your task configuration:

jade: {
    dev: {
        options: {
            data : dataConfigDev
        },
        files: [{
            dest: '<%= config.workingDir %>',
            ...
        }]
    },
    build: {
        options : {
            data : dataConfigBuild
        },
        files: [{
            dest: '<%= config.buildDir %>',
            ...
        }]
    }
}

Note, this code is not tested.

As a side note, the reason you are not seeing your not seeing the expected config in the watch related code is most likely because you need to set spawn : false.

go-oleg
  • 19,272
  • 3
  • 43
  • 44
  • I believe that overwrites and not expands the options (I'm not 100% on that though) but in this case it's the options.data property that I need to have the extra for so that it passes through to Jade. – Anton Aug 14 '13 at 03:09
  • The update was a good idea. I was trying to stick with, what I thought, was the Grunt way of doing it. I was hoping to avoid repeating the file option but it seems like the best option. Thanks. – Anton Aug 14 '13 at 04:16
  • I missed the part about spawn: false. That has actually sorted my issue and I can use the single task like the second option. – Anton Aug 14 '13 at 05:20