Grunt change target based on input - gruntjs

My Gruntfile is as follows:
module.exports = function(grunt) {
'use strict';
var dictionary = {
'all' : '**',
'html5' : 'some/path'
};
require('time-grunt')(grunt);
require('load-grunt-tasks')(grunt);
grunt.initConfig({
eslint : {
options : {
config : '.eslintrc'
},
target : ['hello/world/js/<HERE>/**.js']
}
});
grunt.registerTask('test', 'Lint a set of files', function(set) {
set = set || 'all';
var path = dictionary[set];
grunt.task.run('eslint');
});
};
Notice the <HERE> in the code. That is where I want the path variable to be inserted. I just have no idea how to do this.
If I type grunt test:html5, the path variable is set to the correct path, so I got that working, now I just need to tell ESLint where to lint. But how?
Edit:
According to the accepted answer, I now have this, which works! I want to share it in case someone else might want to take a look.
module.exports = function(grunt) {
'use strict';
var dictionary = {
'webroot' : 'app/webroot/**',
'html5' : 'app/webroot/js/some/path'
};
require('time-grunt')(grunt);
require('load-grunt-tasks')(grunt);
grunt.initConfig({
eslint : {
options : {
config : '.eslintrc'
},
target : ['<%= path %>']
}
});
grunt.registerTask('test', 'Lint a set of files', function(pathKey) {
pathKey = pathKey || 'webroot';
var path = (dictionary[pathKey] || pathKey) + '/*.js';
console.log('Parsed path as', path);
grunt.config.set('path', path);
grunt.task.run('eslint');
});
};

Save the value of your given path in the grunt config and refer to it:
module.exports = function(grunt) {
'use strict';
var dictionary = {
'all' : '**',
'html5' : 'some/path'
};
require('time-grunt')(grunt);
require('load-grunt-tasks')(grunt);
grunt.initConfig({
eslint : {
options : {
config : '.eslintrc'
},
target : ['hello/world/js/<%= dir %>/**.js']
}
});
grunt.registerTask('test', 'Lint a set of files', function(pathKey) {
var dir = dictionary[pathKey]
grunt.config.set('dir', dir );
grunt.task.run('eslint');
});
};

You can use grunt.option to pass arguments to the Gruntfile.
in the Gruntfile:
grunt.initConfig({
eslint : {
options : {
config : '.eslintrc'
},
target : ['hello/world/js/<%= grunt.option('path') %>/**.js']
}
});
from the CLI: grunt test --path=foo to get 'hello/world/js/foo/**.js'.

Related

[gulp 4]: Trying to run Gulp4 to convert SCSS to CSS

I tried to run the gulp to covert SCSS to CSS,the gulp is working wihout any error but there aren't have any css files output to the target folder, I also tried to change the output path but it still didn't work,and my code is below :
// gulpfile.js
var gulp = require('gulp');
var sass = require('gulp-sass')(require('node-sass'));
var autoprefixer = require('gulp-autoprefixer');
var sourcemaps = require('gulp-sourcemaps');
var plumber = require('gulp-plumber');
var browserSync = require('browser-sync').create();
var notify = require('gulp-notify');
var sassLint = require('gulp-sass-lint');
var styleLink = {
sassLink: 'src/**/*.(scss|sass)',
OutputLink: '../css'
}
var browserSyncLink = {
root: '../',
watchHtml: '../*.html',
watchJS: '../*.js'
}
// notify
function showErrorNotify(error) {
var args = Array.prototype.slice.call(arguments);
// Show notification
notify.logLevel(0);
notify
.onError({
title: '[' + error.relativePath + '] Error',
message: '<%= error.messageOriginal %>',
sound: 'Pop'
})
.apply(this, args);
// Keep gulp from hanging on this task
this.emit('end');
}
// sass task
function sassTask() {
return gulp.src(styleLink.sassLink, { sourcemaps: true })
.pipe(sass()) // compile SCSS to CSS
.pipe(autoprefixer())
.pipe(gulp.dest('./', { sourcemaps: '.' }));
}
function browserSyncServer(cb) {
browserSync.init({
server: {
baseDir: browserSyncLink.root
}
})
cb();
}
function browserSyncLoad(cb) {
browserSync.reload();
cb();
}
function sassLinkTask() {
return gulp
.src(styleLink.sassLink)
.pipe(
plumber({
errorHandler: showErrorNotify
})
)
.pipe(sassLint())
.pipe(sassLint.format())
.pipe(sassLint.failOnError());
}
function watchTask() {
gulp.watch('../*.html', browserSyncLoad);
gulp.watch(['src/**/*.+(scss|sass)', '../js/*.js'], gulp.series(gulp.parallel(sassTask, sassLinkTask), browserSyncLoad));
}
exports.default = gulp.series(gulp.parallel(sassTask, sassLinkTask), browserSyncServer, watchTask);
when I ran this code i alos didn't get any error.
It seems no error..
Could anyone please help me ? Thanks.
and please excuse my poor English...
In your watchTask you have this:
src/**/*.+(scss|sass) note the + sign before the alternation.
But in your styleLink variable you have:
var styleLink = {
sassLink: 'src/**/*.(scss|sass)',
OutputLink: '../css'
}
Change to sassLink: 'src/**/*.+(scss|sass)',

How to execute tasks based on a subfolder with Grunt and Grunt-Watch

I want to be able to have different subprojects inside my main project. For example:
-- my-project/
- Gruntfile.js
- subproject1/
- index.html
- scss/
- main.scss
- subproject2/
- index.html
- scss/
- main.scss
I want to be able to modify a file in subproject1 without triggering subproject2 tasks.
As of right now I'm configuring my gruntfile like so:
watch: {
subproject1: {
files: ['subproject1/*.html', 'subproject1/scss/**/*.scss'],
tasks: ['sass', 'premailer:subproject1']
},
subproject2: {
files: ['subproject2/*.html', 'subproject2/scss/**/*.scss'],
tasks: ['sass', 'premailer:subproject2']
}
},
premailer: {
subproject1: {
options: {
css: 'subproject1/css/main.css',
verbose: false
},
files: [
{
'subproject1/dist/index.html' : 'subproject1/index.html'
}
]
},
subproject2: {
options: {
css: 'subproject2/css/main.css',
verbose: false
},
files: [
{
'subproject2/dist/index.html' : 'subproject2/index.html'
}
]
},
}
Is there a way to dynamically specify to grunt what task to run depending on file modified (eg, I modify folder/index.html, then run premailer:folder) or is this the only way to achieve it ?
You can check all folders in your main folder inside your Gruntfile, using the grunt.file methods (docs here), create an array of subproject names and then using forEach to create your task dynamically.
Something like this should go:
/*global module:false*/
module.exports = function(grunt) {
var mycwd = "./";
var tempFileList = grunt.file.expand(
{ filter: function (src) {
if (grunt.file.isDir(src) == true) {
return true;
}
return false;
} },
[ mycwd + "!(Gruntfile.js|node_modules|package.json)" ] // structure to analyse
);
// I create an empty array to put all elements in, once cleaned.
var fileList = [];
tempFileList.forEach(function(url){
var cwd = url;
cwd = cwd.replace(mycwd, "");
fileList.push(cwd);
})
var watchObject = {};
var premailerObject = {};
fileList.forEach(function(name) {
watchObject[name] = {
files: [name + '/*.html', name + '/scss/**/*.scss'],
tasks: ['sass', 'premailer:' + name]
};
var filesObject = {};
filesObject[name+'/css/main.css'] = name + '/index.html';
premailerObject[name] = {
options: { css: name + '/css/main.css', verbose: false },
files: [ filesObject ]
};
});
var configObject = {
watch: watchObject,
premailer: premailerObject
};
// just to check the final structure
console.log(configObject);
grunt.initConfig(configObject);
};

Grunt filerev uses wrong sources with sourcemapping

I just started using Grunt. I'm trying to uglify a set of files with Grunt, and then create a revision of that file (with grunt-filerev). Everything is fine, except the sourcemaps for the file.
I uglify my files into 1 file called shared.min.js. I also create a sourcemap for this file, and filerev creates a revisioned file and a sourcemap for the revisioned file as well. This means it will generate 4 files:
shared.min.js
shared.min.js.map
shared.min.153987b3.js
shared.min.153987b3.js.map
The problem is that the shared.min.153987b3.js.map uses shared.min.js as it's source, I think it should be shared.min.153987b3.js instead. As you can see in my Gruntfile, I dirty-fixed this with a task called fixFilerevSourcemap.
Then the next problem occured: shared.min.153987b3.js uses shared.min.js.map as it's sourcemap, I think it should be shared.min.153987b3.js.map. Should I dirty-fix this as well? Or is there a better solution?
I have the following Grunt configuration:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
sourceMap: true,
sourceMapIncludeSources: true
},
dist: {
files: {
'somedir/shared.min.js': ['otherdir/file1.js', 'otherdir/file2.js'],
}
}
},
filerev: {
options: {
sourceMap: true
},
scripts: {
src: ['somedir/shared.min.js'],
dest: 'somedir/'
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-filerev');
grunt.registerTask('fixFilerevSourcemap', 'Blaat', function() {
var revisionedSource;
for (var file in grunt.filerev.summary) {
var revisionedFile = grunt.filerev.summary[file];
if (revisionedFile.substr(revisionedFile.length - 3) == 'map') {
if (null == revisionedSource) {
throw "No revisionedSource found!";
}
var mapData = grunt.file.readJSON(revisionedFile);
mapData.file = basename(revisionedSource);
grunt.file.write(revisionedFile, JSON.stringify(mapData));
} else {
revisionedSource = basename(revisionedFile);
}
}
});
grunt.registerTask('default', ['uglify', 'filerev', 'fixFilerevSourcemap']);
function basename(path, suffix) {
// discuss at: http://phpjs.org/functions/basename/
// original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
// improved by: Ash Searle (http://hexmen.com/blog/)
// improved by: Lincoln Ramsay
// improved by: djmix
// improved by: Dmitry Gorelenkov
// example 1: basename('/www/site/home.htm', '.htm');
// returns 1: 'home'
// example 2: basename('ecra.php?p=1');
// returns 2: 'ecra.php?p=1'
// example 3: basename('/some/path/');
// returns 3: 'path'
// example 4: basename('/some/path_ext.ext/','.ext');
// returns 4: 'path_ext'
var b = path;
var lastChar = b.charAt(b.length - 1);
if (lastChar === '/' || lastChar === '\\') {
b = b.slice(0, -1);
}
b = b.replace(/^.*[\/\\]/g, '');
if (typeof suffix === 'string' && b.substr(b.length - suffix.length) == suffix) {
b = b.substr(0, b.length - suffix.length);
}
return b;
}
};

Dynamic config for Grunt task

I'm trying to change a boolean value based on the task called.
For example, given this task definition inside the grunt.initConfig block:
myTask:{
options:{
someConfig:doTheAction
},
build:{...}
}
The doTheAction var is defined above the grunt.initConfig block. (e.g. var doTheAction=true;).
What I'm trying to do is this:
grunt.registerTask('prod','Production',function()
{
doTheAction=true;
grunt.task.run('default');
});
grunt.registerTask('prod','Production',function()
{
doTheAction=false;
grunt.task.run('default');
});
The issue is that while doTheAction changes value, the myTask's option someConfig is set to the init value of that var.
How can I make someConfig change based on the task called?
Here is how I do it using grunt.config :
var taskConfig = {
pkg: {
var1: null
},
myTask:{
options:{
someConfig : '<%= pkg.var1%>',
someOtherConfig: grunt.config.get('pkg.var1') //alternative
},
build:{...}
}
}
grunt.registerTask('prod','Production',function()
{
grunt.config.set('pkg.var1', true);
grunt.task.run('default');
});
grunt.registerTask('prod','Production',function()
{
grunt.config.set('pkg.var1', false);
grunt.task.run('default');
});
Hope this helps

registerMultiTask.js in grunt-horde

I'm trying to configure grunt-horde so that I can have multiple builds all using a centrally managed task configuration.
The documentation provides the following example of a registerMultiTasks.js file, but I can't get it to work
module.exports = function(grunt) {
var myMultiTask = require('./multi-tasks/secret-sauce.js');
return {
myMultiTask: ['some description', myMultiTask]
};
};
Even if I replace their example with something more simple:
module.exports = function(grunt) {
return {
demo: ['Demo', function() {
console.info('hello');
}]
};
};
When I run grunt demo:test the output is:
Running "demo:test" (demo) task
Verifying property demo.test exists in config...ERROR
>> Unable to process task.
Warning: Required config property "demo.test" missing. Use --force to continue.
Aborted due to warnings.
When I run grunt --help the demo task shows up in the list. Thinking about the warning message I've also tried the following, but again with no luck.
module.exports = function(grunt) {
return {
demo: ['Demo', function(){
return {test: function(){console.info('hello');}};
}]
};
};
...what am I doing wrong?
I figured it out - you need to define the configuration for each target of the multitasks:
initConfig/demo.js
module.exports = function() {
'use strict';
return {
test: {
foo: 'bar'
}
};
};
You can then access this configuration data and the target from within the multitask function:
registerMultiTask.js
module.exports = function(grunt) {
return {
demo: ['Demo', function() {
grunt.log.writeln('target: ' + this.target);
grunt.log.writeln('foo: ' + this.data.foo);
}]
};
};

Resources