spacewindow
spacewindow

Reputation: 407

Grunt - pass filename variable from command line

I am struggling to understand how I can pass a partial filename from the grunt command line, in order to run a task (from an installed grunt module) on a particular file.

What I want to be able to do is configure a series of tasks to take filename parameter from the command line.

I've tried reworking the final example on this page http://chrisawren.com/posts/Advanced-Grunt-tooling but I'm kind of stabbing in the dark a bit. Thought someone would have a quick answer.

Here is my Gruntfile:

module.exports = function (grunt) {
    grunt.initConfig({
      globalConfig: globalConfig,

        uglify: {
          js: {
            options: {
              mangle: true
            },
            files: {
              'js/<%= globalConfig.file %>.min.js': ['js/<%= globalConfig.file %>.js']
            }
          }
        },



    });

    // Load tasks so we can use them



    grunt.loadNpmTasks('grunt-contrib-uglify');

    grunt.registerTask('go', 'Runs a task on a specified file', function (fileName){
      globalConfig.file = fileName;
      grunt.task.run('uglify:js');
    });
};

I attempt to run it from the command line like this:

grunt go:app

to target js/app.js

I get this error:

Aborted due to warnings.
roberts-mbp:150212 - Grunt Tasks robthwaites$ grunt go:app
Loading "Gruntfile.js" tasks...ERROR
>> ReferenceError: globalConfig is not defined
Warning: Task "go:app" not found. Use --force to continue.

Thanks

Upvotes: 4

Views: 1583

Answers (2)

spacewindow
spacewindow

Reputation: 407

I the end I was able to accomplish what I wanted like this, but not sure if this is a standard way.

What I was failing to do was declare the globalConfig variable globally first, so that I could redefine it from the Terminal as I ran my grunt task.

Here is an example. When working with HTML emails I need to:

  1. Process my sass files to css (grunt-contrib-sass)
  2. Run an autoprefixer on the resulting css (grunt-autoprefixer)
  3. Minify my CSS and remove CSS comments (grunt-contrib-cssmin)
  4. Include my full CSS in a tag the of my html file (using grunt-include-replace)
  5. Finally, run premailer on the file to inline all styles (grunt-premailer)

The point is, if I am working on several different HTMl emails in the same project, I need to be able to run all these tasks on html files one-by-one, as needed. The Gruntfile below allows me to do this.

What this does:

If you enter into terminal grunt It will simply run the sass task, which processes all sass files - no file parameter needed from Terminal.

However, if I wish to run a series of processes on a single html file, I enter grunt process:fileName with fileName being the name of the html file without the .html extension.

You will notice that the only tasks that require the fileName are actually include-replace and premailer. However, I still want to run al the other CSS cleanup tasks prior to targetting my chosen file.

The key is:

  1. Declaring the global variable
  2. Load the globalConfig variables into the grunt.initConfig
  3. Use the grunt variable declaration where needed in your tasks
  4. register your custom task, with the fileName variable being used as a paramater.

Hope that helps someone.

module.exports = function (grunt) {

    var globalConfig = {
        file: 'index' // this is the default value, for a single project.
    }

    grunt.initConfig({

        pkg: grunt.file.readJSON('package.json'),

        // load the globalConfig variables

        globalConfig: globalConfig,

    sass: {
        dev: {
            files: [{
                expand: true,
                cwd: 'scss',
                src: ['*.scss'],
                dest: 'css',
                ext: '.css'
    }]
        }
    },

    cssmin: {
        options: {
            keepSpecialComments: 0,
            keepBreaks: true,
            advanced: false
        },
        target: {
            files: [{
                expand: true,
                cwd: 'css',
                src: '*.css',
                dest: 'css',
                ext: '.css'
    }]
        }
    },

    autoprefixer: {
        css: {
            src: "css/*.css"
        }
    },

    includereplace: {
        your_target: {
            options: {
                prefix: '\\/\\* ',
                suffix: ' \\*\\/',
            },
            files: {
                'inline/<%= globalConfig.file %>-inline.html': ['<%= globalConfig.file %>.html']
            }
        }
    },

    premailer: {
        main: {
            options: {
                verbose: true,
                preserveStyles: true,
            },
            src: 'inline/<%= globalConfig.file %>-inline.html',
            dest: 'inline/<%= globalConfig.file %>-inline.html'
        }
    },


});


grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-autoprefixer');
grunt.loadNpmTasks('grunt-include-replace');
grunt.loadNpmTasks('grunt-premailer');

grunt.registerTask('default', 'sass');

grunt.registerTask('process', 'Runs all processing tasks on a specific file to produce inlined file', function (fileName) {
    globalConfig.file = fileName;
    grunt.task.run('sass', 'autoprefixer', 'cssmin', 'includereplace', 'premailer');
});

}

EDIT: Obviously at the moment this accepts only one parameter I beleive. In other use cases the grunt.option version above could give more functionality, being able to submit several parameters in one command. I will continue to experiment with grunt.option if I find the need to do this.

Upvotes: 1

Trupti M Panchal
Trupti M Panchal

Reputation: 260

you can use grunt.option.

your grunt register task will look like this.

> grunt.option('fileName'); grunt.registerTask('go', 'Runs a task on a
> specified file', function (){     
>       grunt.task.run('uglify:js');
>     });

your grunt configuration will be

module.exports = function (grunt) {
 var fileName=grunt.option('fileName');
    grunt.initConfig({
        uglify: {
          js: {
            options: {
              mangle: true
            },
            files: {
              'js/fileName.min.js': ['js/fileName.js']
            }
          }
        },   
    });

command to run the task from terminal:

$ grunt go --fileName='xyzfile'

Upvotes: 8

Related Questions