Вопрос

Consider following Gruntfile.js

module.exports = function(grunt) {
    var 
        stylusFiles = [
            {
                expand: true,
                cwd: 'radio/static/css/',
                src: ['*.styl'],
                ext: ['.css']
            },
            {
                expand: true,
                cwd: 'radio/static/polymer/radio-light/',
                src: ['**/*.styl'],
                ext: ['.css']
            },
            {
                expand: true,
                cwd: 'radio/static/themes/',
                src: ['**/*.styl'],
                ext: ['.css']
            }
        ];

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        stylus: {
            all: {
                files: stylusFiles,
            },
        },

        watch: {
            files: [
                'radio/static/css/*.styl',
                'radio/static/themes/**/*.styl',
                'radio/static/polymer/radio-light/**/*.styl',
            ],
            tasks: ['stylus:all'],
        }
      });


    // Other stuff
};

Stylus task compiles every .styl file found in specified folders. Watch task now leading to recompilation of all .styl files, and I want to recompile only watched ones.
I've read a little bit about watch.event, but I can't understand how to run default task (e.g. stylus:single) with watched pathname.
In other words is there a way to implement stylus subtask, which could be run by grunt.task.run() with custom files option?

UPDATED: The solution is below in my own answer.

Это было полезно?

Решение 2

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:

Hope, this will help somebody.

Другие советы

The way I understood was, you could create multiple json objects and assign to variables. So then in your styluscreate multiple sub tasks as follows. So you can use the same sub tasks for the watch as well.

ex.

    var stylusStaticFiles = [ {
        expand : true,
        cwd : 'radio/static/css/',
        src : [ '*.styl' ],
        ext : [ '.css' ]
    } ];

    var stylusRadioLightFiles = [ {
        expand : true,
        cwd : 'radio/static/polymer/radio-light/',
        src : [ '**/*.styl' ],
        ext : [ '.css' ]
    } ];

    var stylusthemesFiles = [ {
        expand : true,
        cwd : 'radio/static/themes/',
        src : [ '**/*.styl' ],
        ext : [ '.css' ]
    } ];

In your stylus

         stylus: {
         stylusStaticFiles: {
                    files: stylusStaticFiles,
                },
                stylusRadioLightFiles: {
                    files: stylusRadioLightFiles,
                },
                stylusthemesFiles: {
                    files: stylusthemesFiles,
                }
     }

In the watch

    watch: {
            stylusStaticFiles: {
                files: ['radio/static/css/*.styl'],
                tasks: ['stylus:stylusStaticFiles']
            },

             stylusRadioLightFiles: {
                files: ['radio/static/themes/**/*.styl'],
                tasks: ['stylus:stylusRadioLightFiles']
            },
            stylusthemesFiles: {
                files: ['radio/static/polymer/radio-light/**/*.styl'],
                tasks: ['stylus:stylusthemesFiles']
            }
  }

Let me know if this works for you.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top