Settings files via grunt.config - gruntjs

I'm trying to set the files option in grunt config dynamically.
This works:
grunt.initConfig({
mocha_casperjs: {
options: options,
files: {
src: ['test.js']
}
}
});
And I'm trying to reproduce it like so:
grunt.registerTask('run_tests', function() {
grunt.config('options', options);
grunt.config('files', { src: ['test.js'] });
grunt.task.run('mocha_casperjs');
});
But the files attribute is not set. Am I doing something wrong here?

Please, read carefully about grunt.config API.
grunt.config.get(taskName) returns config object for specified task. It performs just key's lookup in the root config object.
grunt.config.set(taskName, newValue) works the same way.
So, to set new files for mocha_casperjs you need to do it like this:
var mochaCasperjsConfig = grunt.config.get('mocha_casperjs');
mochaCasperjsConfig.files = { src: ['test.js'] };
grunt.config.set('mocha_casperjs', mochaCasperjsConfig);

Related

grunt rename function not working

I am using save2png to provide fallback pngs to svg4everybody. The svgs are created and I can change input and output directory. But svg4everybody requires that the pngs are saved with a filename like: "spritesheetname.svg.id.jpg"
At first, I tried some simple things, but I can't even figure out how to change the filename in the first place.
Here is my code:
module.exports = function(grunt){
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
svg2png: {
all: {
files: [
// rasterize all SVG files in "img" and its subdirectories to "img/png"
{ cwd: '../img/icons/',
src: ['**/*.svg'],
dest: '../symbol/svg/',
rename: function(dest, src) {
var filename = src.substring(src.lastIndexOf('/'), src.length);
return dest + 'prefix' + filename + '.png';
}
}
]
}
}
});
grunt.registerTask('default', []);
grunt.loadNpmTasks('grunt-svg2png');
};
The pngs are created, but the filename is always the same as the original svg.
I stumbled upon this question, Grunt rename not working, but it was no real help. Flatten and expand just changed the directory structure, but had no influence on the filename.

Location of Intern reporters output files like corbertura or html report

I'm using Grunt with Intern and set some reporters to lcovhtml and cobertura:
grunt.initConfig({
intern: {
runner: {
options: {
config: 'tests/intern',
runType: 'runner',
reporters: ['pretty', 'lcovhtml','junit','cobertura']
}
}
},
Is there any configuration to control output directory of these files for all or each reporter?
For example, by adding a parameters reportDir to the options object defined in your Gruntfile.js, you can update intern/lib/reporters/lcovhtml.js with:
define([
'dojo/node!istanbul/lib/collector',
'dojo/node!istanbul/lib/report/html',
'dojo/node!istanbul/index'
], function (Collector, Reporter) {
var collector = new Collector(),
reporter = new Reporter();
//...
});
with:
define([
'../args',
'dojo/node!istanbul/lib/collector',
'dojo/node!istanbul/lib/report/html',
'dojo/node!istanbul/index'
], function (args, Collector, Reporter) {
var collector = new Collector(),
reporter = new Reporter({ dir: args.reportDir });
//...
});
You can propagate a similar update in cobertura.js and junit.js reporters.
Note: I documented this approach in https://github.com/theintern/intern/issues/71. The patch for the corresponding issue has not yet been published (pushed to Intern 2.3).

Grunt uglify : Weird behavior

I cannot figure out why uglify does not want concat string as input or output ...
This works :
uglify: {
dev_uglify_js: {
files: {
'my_file.min.js': ['my_file.js']
}
}
}
For example, this does not works :
uglify: {
dev_uglify_js: {
files: {
'my'+'_file.min.js': ['my_file.js']
}
}
}
Do you have any idea why ?
The output error is "SyntaxError: Unexpected token".
The real insterest here is to concatenate a timestamp to the file name.
But just with 2 strings it does not work so ...
Thanks for your help !
In JavaScript, an object key cannot be declared dynamically. This is not a problem with grunt or uglify - it's a language constraint.
myObject = { 'a' + 'b' : 'b' } // NOPE!
However, any object property can be accessed via square brackets. For example:
myObject = { 'banana': 'boat' }
myObject.banana // boat
myObject['banana'] // boat!
Therefore, you can add properties after the object is already created, using the square brackets syntax.
myObject = {}
myObject[ 'a' + 'b' ] = 'b' // Yes
myObject.ab // b
The Gruntfile example
In your Gruntfile, you're bound to, at some point, call something like grunt.config.init or grunt.initConfig. This is usually done inline:
grunt.initConfig({
uglify: {} // properties ...
});
However, initConfig simply receives an object. You can define it and manipulate it as much as you need before calling this function. So, for example:
var config = { uglify: {} };
config.uglify['such'+'dynamic'+'very'+'smarts'] = {};
grunt.initConfig(config);
Similar questions:
How do I create a dynamic key to be added to a JavaScript object variable
How do I add a property to a JavaScript object using a variable as the name?

Encrypting files with grunt-encrypt

I'm trying to encrypt my .keychain files on my Mac and saving them on in a backup place. When i run grunt enc it just creates 2 very small files in the directory of the source files. So encrypting and moving the files doesn't go well...
package.js is just grunt with 1 devDependency grunt-encrypt.
Gruntfile.js is shown below.
'use strict';
module.exports = function(grunt) {
var npmDependencies = require('./package.json').devDependencies;
grunt.initConfig({
encrypt: {
encryptKeys: {
options: {
key: 'SuperSecretKey',
dest: '/Users/myusername/www/admin/filebackup/encrypted',
},
files: {
'keychains': [
'/Library/Keychains/system.keychain',
'/Users/myusername/Library/Keychains/login.keychain'
]
}
}
},
});
grunt.loadNpmTasks('grunt-encrypt');
grunt.registerTask('enc', [
'encrypt'
]);
};
I've been using Grunt for a week, so could very well be i'm missing something obvious. Anybody used grunt-encrypt before?
Thanks!
Looks as if your SuperSecretKey is not defined yet.
I've solved it like this:
add
module.exports = function (grunt) {
// ad here
var superSecretKey = 'secretpassword';
to your Gruntfile.js
Or put a keyfile (mine is called livereload.key) in the project's root and alter your Gruntfile like this:
//key : superSecretKey,
key: grunt.file.read('livereload.key'),

How to avoid unnecessary uglifying in GruntJS?

I have a grunt file with the following definition:
uglify: {
build: {
src: 'www/temp/application.js', // a concatenation of files via grunt-contrib-concat
dest: 'www/temp/application.min.js'
}
},
what I would really like to do is to recompute the final application.min.js only in case that application.js file was changed. More precisely, I want to add the condition:
# pseudocode
if (getFileContents(application.js) == getFileContents(previously.uglified.application.js)) {
// do nothing
} else {
// run uglifying on application.js
}
Reason:
I deploy my project by git and uglifying is relatively slow (3+ seconds) and moreover, it is unnecessary since I don't change JS files often.
There are several possible solutions:
You can create your own grunt task that will check files for last modify time using for example fs.stat then run uglify task through grunt.task.run with prepared options as argument.
Or you can build files object dynamically passing it through filter function:
var fs = require('fs');
module.exports = function (grunt) {
function filterChanged(files) {
var mtime = '',
stats;
for (var dest in files) {
stats = fs.statSync(files[dest]);
try {
mtime = fs.readFileSync(files[dest] + '.mtime', 'utf8');
}
catch (ex) {
fs.writeFileSync(files[dest] + '.mtime', stats.mtime, 'utf8');
return files;
}
if (stats.mtime == mtime || !mtime) {
delete files[dest];
}
else {
fs.writeFileSync(files[dest] + '.mtime', stats.mtime, 'utf8');
}
}
return files;
}
grunt.initConfig({
uglify: {
build: {
files: filterChanged({
'www/temp/application.min.js': 'www/temp/application.js'
})
}
}
});
};
This causes invoke of filterChanged function every time uglify task runs.

Resources