The solution in this particular case is following:
create watch task, which does not runs any tasks for all target files and spawn set to
false
:grunt.initConfig({ // ... watch: { stylus: { files: ['whatever/*.styl'], options: { spawn: false, }, }, }, // .. })
listen for watch event:
grunt.event.on('watch', function (action, filepath) { /* ... */ });
check action type: if file wasn't deleted recompile it, otherway delete appropriate CSS file
Full code example:
grunt.initConfig({
// ...
stylus: {
compile: {
files: [
{
expand: true,
cwd: 'whatever/',
src: ['/stylus/*.styl'],
dest: 'css/',
ext: '.css',
// Compile all files from 'whatever/stylus' and put results
// in 'whatever/css/<proper name>.css'
},
],
},
},
watch: {
stylus: {
files: ['whatever/*.styl'],
options: {
spawn: false,
},
},
},
// ..
});
grunt.event.on('watch', function (action, filepath) {
var
dst, ext, files;
dst = filepath.split('.');
ext = dst.slice(-1);
if (ext == 'styl') {
// prepare destination file name,
// e.g. <dir>/stylus/<name>.styl -> <dir>/css/<name>.css
dst.splice(-1,1,'css');
dst = dst.join('.').split('/');
dst.splice(-2,1,'css');
dst = dst.join('/');
if (action != 'deleted') {
// replace stylus task dynamic patter
files = {};
files[dst] = filepath;
grunt.config('stylus.compile.files', files);
grunt.task.run('stylus:compile');
} else {
// delete obsolete css file
grunt.file.delete(dst);
grunt.log.writeln('File "' + dst + '" deleted.');
}
}
});
Helpful links:
- grunt-contrib-watch README
- Grunt FAQ: How can I share parameters across multiple tasks?
- Grunt FAQ: Globals and configs
Hope, this will help somebody.