n4m31ess_c0d3r
n4m31ess_c0d3r

Reputation: 3148

How to read a variable in grunt config defined within the target?

I'm trying to configure grunt for a multi task registerMultiTask having a targets depending upon the different domains.

Below is the configuration example.

grunt.initConfig({
    log: {
        'domain_01': {
            hostName: 'www.domain1.com',
            options: {
                urls: [ 
                    '<%= hostName %>' + '/file1.js', 
                    '<%= hostName %>' + '/file2.js'
                ]
            }
        }
    }
});

grunt.registerMultiTask('log', function() {
    grunt.log.writeln('hostName = ' + this.data.hostName);
    grunt.log.writeln('urls = ' + this.data.options.urls);
});

So, expected result should be:

> grunt validation:domain_01
hostName = domain_01
urls = ['www.domain1.com/file1.js', 'www.domain1.com/file2.js']

I'm having toruble reading the variable hostName defined inside the target domain_01, getting the error:

Warning: An error occurred while processing a template (hostName is not defined). Use --force to continue.

Aborted due to warnings.

I also tried with ['<%= grunt.config("log.domain_02.hostName") %>' + '/file1.js', ...].

It worked but it defeats the aim of making this code a generic one as I will have to change the template string on every line if I want to add another target. How can I achieve this?

Note: Task log is just a sample task, I will be using different plugins and for that purpose I want minimum changes to it and achieve in configuration only if possible.

Upvotes: 1

Views: 434

Answers (1)

RobC
RobC

Reputation: 24962

Update...

I misread a couple of key requirements in your post when providing my previous answer. I.e. This part in the title:

...read a variable in grunt config defined within the target?

and this too..

...as I will have to change the template string on every line if I want to add another target

Solution three

This can be achieved by:

  1. Not attempting to use template strings to prefix the hostName in options.urls of each target.
  2. Prefix each url with its relevant hostName inside the grunt.registerMultiTask function instead.

The following gist demonstrates this:

module.exports = function(grunt) {

    'use strict';

    grunt.initConfig({

        log: {
            'domain_01': {
                hostName: 'www.domain1.com',
                options: {
                    urls: [
                        '/file1.js' //<-- Note: No reference to hostName
                    ]
                }
            },
            'domain_02': {
                hostName: 'www.domain2.com',
                options: {
                    urls: [
                        '/file1.js',
                        '/file2.js'
                    ]
                }
            },
            'domain_03': {
                hostName: 'www.domain3.com',
                options: {
                    urls: [
                        '/file1.js',
                        '/file2.js',
                        '/file3.js'
                    ]
                }
            }
        }
    });

    grunt.registerMultiTask('log', function() {
        var hostName = this.data.hostName,
            urls = this.data.options.urls.map(function (url) {
                return hostName + url;
            });

        grunt.log.writeln('hostName = ' + hostName);
        grunt.log.writeln('urls = ' + urls);
    });
};

Results

  1. Running $ grunt log:domain_01 via the CLI returns:
hostName = www.domain1.com
urls = www.domain1.com/file1.js
  1. $ grunt log:domain_02 returns:
hostName = www.domain2.com
urls = www.domain2.com/file1.js,www.domain2.com/file2.js
  1. And $ grunt log:domain_03 returns:
hostName = www.domain3.com
urls = www.domain3.com/file1.js,www.domain3.com/file2.js,www.domain3.com/file3.js

Previous Answer...

You could setup as follows:

Solution one

module.exports = function(grunt) {

    grunt.initConfig({

        hostName: 'www.domain1.com', //<-- Define the default hostname

        log: {
            'domain_01': {
                hostName: '<%= hostName %>',
                options: {
                    urls: [
                        '<%= hostName %>' + '/file1.js',
                        '<%= hostName %>' + '/file2.js'
                    ]
                }
            }
        }
    });

    grunt.registerMultiTask('log', function() {
        grunt.log.writeln('hostName = ' + this.data.hostName);
        grunt.log.writeln('urls = ' + this.data.options.urls);
    });
};

Note the addition of the hostName key plus default value.


Solution two

You may wish to consider also utilizing the grunt.option API if the hostName value is likely to change in the future, therefore providing even more generic code. For example:

module.exports = function(grunt) {

    grunt.initConfig({

        // Notice this time we also accept an optional value and a default.
        hostName: grunt.option('hostName') || 'www.domain1.com',

        log: {
            'domain_01': {
                hostName: '<%= hostName %>',
                options: {
                    urls: [
                        '<%= hostName %>' + '/file1.js',
                        '<%= hostName %>' + '/file2.js'
                    ]
                }
            }
        }
    });

    grunt.registerMultiTask('log', function() {
        grunt.log.writeln('hostName = ' + this.data.hostName);
        grunt.log.writeln('urls = ' + this.data.options.urls);
    });
};

1 Running solution two via the CLI as follows:

$ grunt log

reports:

hostName = www.domain1.com
urls = www.domain1.com/file1.js,www.domain1.com/file2.js

Note the default value is used as no option flag is provided.

2 Whilst running solution two via the CLI with an options flag as follows:

$ grunt log --hostName=www.domain2.com

... reports:

hostName = www.domain2.com
urls = www.domain2.com/file1.js,www.domain2.com/file2.js

Note the options flag value is reported.

Upvotes: 2

Related Questions