Grunt-replace : parametric json file - javascript

Goodmornig,
I'm using grunt-replace (https://github.com/outaTiME/grunt-replace) inside my gruntfile to replace some string in a html file by loading a json object from a json file.
I want to add some flexibility to this approach and i customized another task called 'setopts' that simply add some properties to the grunt.option that i use i the 'replace' task in the following way:
replace: {
common: {
options: {
patterns: [
{
json: '<%=grunt.option("locales")%>'
}
]
},
files: [
{expand: true, flatten: true, src: ['public/sites/<%=grunt.option("domain")%>/index.html'], dest: 'public/sites/<%=grunt.option("domain")%>/'},
]
}
}
Here my 'setopts' task :
grunt.registerTask('setopts', function (domain) {
locales = grunt.file.readJSON('src/locales/domain/myfile.json');
grunt.option('locales', locales);
grunt.option('domain', domain);
}
I run the following task :
grunt.registerTask('maintask', [ 'setopts:mydomain', 'replace:common']);
After some attempts i found that the 'files' property in the 'replace' task works fine but i get an error in the 'patterns' property :
Processing source...ERROR
Warning: Error while processing "public/sites/xxxxx/index.html" file. Use --force to continue.
What's going wrong with this?
Thanks for any comment!

I know I'm 1.5 years late, but maybe some other people might need the answer to this.
The way I made it work was by not using grunt.option. Instead, I used grunt.config.set.
replace: {
common: {
options: {
patterns: [
{
json: '<%= locales %>'
}
]
},
files: [
{expand: true, flatten: true, src: ['public/sites/<%= domain %>/index.html'], dest: 'public/sites/<%= domain %>/'},
]
}
}
Notice the way the locales variable is used as a value to the json property.
This is the setopts task:
grunt.registerTask('setopts', function (domain) {
locales = grunt.file.readJSON('src/locales/domain/myfile.json');
grunt.config.set('locales', locales);
grunt.config.set('domain', domain);
}
Hopefully it helps somebody :)
This question helped me find the answer Programmatically pass arguments to grunt task?

Related

passing value fron conf.js to a grunt task or between grunt tasks

How do I pass information between grunt tasks? I would like to pass a value from a grunt task to another grunt task.
My situation is that after completing a protractor test, I would like to pass a value to a new grunt task. To achieve this, I went ahead and set the value in process.env and tried to use process.env in the new grunt task. But that doesn't seem to work
This is conf.js:
afterLaunch: function(exitCode) {
return new Promise(function(fulfill, reject) {
if (typeof jasmine.getEnv().testReportFilePath !== 'undefined' && jasmine.getEnv().testReportFilePath !== null) {
process.env.testReportFilePath = jasmine.getEnv().testReportFilePath;
console.log('Trying: ' + process.env.testReportFilePath);
fulfill('Success: Environment variable testReportFilePath is set in conf.js');
} else {
reject(new Error('Failed: Environment variable testReportFilePath not set in conf.js'));
}
});
And this is my Gruntfile:
grunt.loadNpmTasks('grunt-protractor-runner');
grunt.loadNpmTasks('grunt-protractor-webdriver');
grunt.loadNpmTasks('grunt-execute');
grunt.config('protractor', {
require: [ setTesting ],
options: {
configFile: 'conf.js', // common config file
keepAlive: true, // If false, the grunt process stops when the test fails.
noColor: false // If true, protractor will not use colors in its output.
},
run_specific_suite: {
options: {
args: {
baseUrl: '<%= grunt.option("testUrl") %>',
browser: '<%= grunt.option("testBrowser") %>',
params: {
environment: '<%= grunt.option("testEnv") %>'
},
suite: '<%= grunt.option("testSuite") %>'
}
}
},
});
grunt.config('execute', {
email_stakeholders: {
options: {
args: [
process.env.testReportFilePath,
'myemail#email.com'
]
},
src: ['toDelete.js']
}
});
But process.env.testReportFilePath appears to be undefined in the gruntjs file.
This answer is long overdue. I did follow #mparnisari suggestion to write the variable out to the file. So I did the following in my conf.js to write the value into a yaml file :
fs.writeFileSync(path.join(process.cwd(),'_testReportFilePath.yml'),
'testReportFilePath: ' + jasmine.getEnv().testReportFilePath);
and in the gruntfile, the yaml file read using the grunt api :
// --- grunt execute task --- //
grunt.config('execute', {
email_stakeholders: {
options: {
args:[
grunt.file.readYAML(path.join(process.cwd(),'_testReportFilePath.yml')).testReportFilePath, // html report
'myemail#email.com'//enter the recipient emails here
]
},
src: ['test/scripts/nightlyPostTasks.js']
}
});
and appears to do what I need. Only quirk is that a dummy yaml file with the name _testReportFilePath.yml must always be present in CWD to prevent any grunt error.

How to pass file name/options to Grunt minifyify

I'm using the minifyify plugin as recommended by this answer but I can't seem to find any way to pass flags/options to it when used with Grunt.
Here is the relevant part of my Gruntfile:
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
browserify: {
options: {
browserifyOptions: {
debug: true
},
exclude: [/*...all vendor packages...*/],
transform: [
'brfs',
'debowerify',
'deamdify'
]
},
app: {
files: [{
expand: true,
cwd: 'web/resources/js',
src: '**/*.js',
dest: 'web/assets/js',
ext: '.min.js',
extDot: 'last'
}],
options: {
plugin: ['minifyify']
}
}
}
});
The compiled files are appended to with //# sourceMappingURL=bundle.map, which is incorrect. Also, the map files aren't being written to disk or generated at all.
How can I pass options in so that the sourceMappingURL is the same as the file name? So for example:
/web/assets/js/foo.min.js -> /web/assets/js/foo.js.map
/web/assets/js/bar.min.js -> /web/assets/js/bar.js.map
and so on...
you can pass options into grunt-browserify plugins/transforms if you pass in the transform as an array with the name as first item, and the options-object as the second:
plugin: [['minifyify', {your: 'options'}]]
for the transform option it is documented here: https://github.com/jmreidy/grunt-browserify#transform
for the plugin-option there is no documentation, but they generally work the same (see lib/runner.js, ans search for options.plugin)

Grunt how to set up a task to invoke a plugin more than once

I use requirejs to distribute the code into a single file.
In grunt.initConfig, I have:
grunt.initConfig({
requirejs: {
compile: {
options: {
paths: requirejs_path,
shim:require_shim,
baseUrl : "./mobile",
name: "mobilemain",
out: "./mobile/dist/main.js",
removeCombined: true,
findNestedDependencies: true,
optimize: "uglify2",
wrap: true,
uglify2: requirejs_uglify2
}
}
}
}
this this part of code to set up requirejs. and I use
grunt.registerTask("distribute", ["typescript", "requirejs"]);
to register it to a task distribute, all works fine.
Now I want to call requirejs twice in the distribute task, once for mobile and once for desktop. Basically I will need to change the baseUrl, name, and out config in the above code.
How can I do that?
grunt-contrib-requirejs is a multitask where you can simply configure as much sub-tasks as you want (using the options property)
grunt.initConfig({
requirejs: {
// define your base options which are the same for both tasks
options: {
paths: requirejs_path,
shim:require_shim,
removeCombined: true,
findNestedDependencies: true,
optimize: "uglify2",
wrap: true,
uglify2: requirejs_uglify2
},
// your first task which contains the 3 options which should be used
compile: {
options: {
baseUrl : "./mobile",
name: "mobilemain",
out: "./mobile/dist/main.js"
}
},
// your second task which contains the 3 options which should be used
compile2: {
options: {
baseUrl : "...",
name: "...",
out: "..."
}
}
}
}
then you can leave your alias-task distribute as it is, because grunt will run all sub-tasks if none is specified
grunt.registerTask("distribute", ["typescript", "requirejs"]);
or you can simply just run a single sub-task using the colon-notation:
grunt.registerTask("distribute", ["typescript", "requirejs:compile", "requirejs:compile2"]);
the second one would be useful if you absolutly must guarantee, that compile needs to be run before compile2 (remember: javascript does not guarantee property order in objects)

Include in nunjucks (grunt-nunjucks-2-html) are based on an incorrect path

I'm using Nunjucks with grunt/node via the grunt plugin grunt-nunjucks-2-html
My root path is where the gruntfile is, so it's look like this:
./src
index.html
expo.html
./inc
head.html
header.html
My gruntfile config looks like this :
nunjucks: {
render: {
files: [
{
expand: true,
cwd: 'src/',
src: "*.html",
dest: pathbuild,
ext: ".html"
}
]
}
},
in my index.html I have this:
{% include "inc/head.html" %}
When I try grunt nunjucks, this is what I get
Warning: (unknown path) Error: template not found: inc/head.html
Use --force to continue.
That can be solved if I change path to "src/inc/head/html" but I don't get why I need to specified this, seems not logical to me.
Do you have something to teach to me that I've missed so hard?
Thanks.
I had the same issue and after looking at the plugin code, I noticed that the template path had to be supplied as an array:
nunjucks: {
options: {
paths: ['templates'], // 'templates' as a string can now be passed (30Oct2014)
data: grunt.file.readJSON('results.json')
},
render: {
files: [
{
expand: true,
cwd: "templates/",
src: "*.html",
dest: "build/",
ext: ".html"
}
]
}
}
I've sent a pull request (https://github.com/vitkarpov/grunt-nunjucks-2-html/pull/4) so if it gets accepted, we'll be able to supply the template path as a string.
Update 30-Oct-14: The pull request has been merged, so a string or array can be passed to options.paths.

How to enable Stylus url() rewrites

I'm trying to get stylus urls to work. I would like to convert the url('/path/to/img.png') to convert to the base64 encoded form.
I'm trying to follow the documentation here, but it's not helping me much.
I tried adding the require bit and the example functions, importing url, but not sure how to enable this thing.
How do I get this to work?
UPDATE:
Trying to use grunt-image-embed plugin.
Here is my grunt config:
imageEmbed: {
dist: {
src: [ "./public/local/css/images.css" ],
dest: "./public/prod/css/images.css",
options: {
deleteAfterEncoding : false
}
}
},
And the css contains:
#footer-social .youtube {
width: 18px;
background-image: url('/img/youtube-icon.png');
}
Which produces the error:
Warning: File C:\path\...\grunt-image-embed\tasks\lib\img\youtube-icon.png
does not exist Use --force to continue.
If I remove the background-image line it all works and goes through fine. I can't modify the paths in the css because on local we use the relative path to the actual image.
try this:
function compile(str, path) {
return stylus(str)
.define('url', stylus.url({
paths : [__dirname + '/public'],
limit : 10000
}));
}
From here:
http://bengourley.co.uk/using-stylus
It worked for me here:
https://github.com/MichaelJCole/wintersmith-stylus/blob/master/plugin.coffee
It's coffeescript, and the interesting part is this:
stylus(#_text, options)
.use(nib())
.define('url', stylus.url(
paths : [__dirname + '/public']
limit : locals.inlineSpriteMaxBytes || 0 ) )
.render (err, css) ->
if err
callback err
else
callback null, new Buffer css
I do not know how it makes no a stylus, but you can use this [1]: http://docs.emmet.io/actions/base64/
I think you'll find this grunt plugin to be exactly what you need; grunt image embed. Works for both images and fonts. From the docs:
grunt.initConfig({
imageEmbed: {
dist: {
src: [ "css/styles.css" ],
dest: "css/output.css",
options: {
deleteAfterEncoding : false
}
}
}
});

Categories