Passing arguments from command line to grunt copy task - gruntjs

var pathValue="";
module.exports = function(grunt) {
grunt.initConfig({
copy: {
main: {
files: [{
cwd: 'srcpath', // set working folder / root to copy
src: '**/*', // copy all files and subfolders
dest: 'pathValue', // destination folder
expand: true
}]
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.registerTask('copy', function(n) {
var target = grunt.option('target');
pathValue = target;
// do something useful with target here
});
};
I'm trying to pass destination path to the copy task from command line. I tired the command
grunt copy --target=destpath
It says "Done without errors" but new folder is not getting created in the destination directory. Can someone please tell me what's the error in the code?

Try changing dest to a qualified js file path. Like this:
dest: 'dest/bob.js'

Related

Gruntfile.js Warning: The "path" argument must be of type string. Received type object Use --force to continue

I'm having an issue with running a grunt copy task. I've a library specified in package.json under dependencies as below
"#tarekraafat/autocomplete.js": "^7.2.0"
and declared copy tasks in Gruntfile.js as below
var paths = {
webroot: "wwwroot/"
};
// destination css path
paths.cssOutput = paths.webroot + "css";
// where to find bower resources
paths.bower_components = paths.webroot + "lib";
// where to find reset.css
paths.resetCss = paths.bower_components + "/html5-reset/assets/css";
module.exports = function (grunt) {
"use strict";
// Project configuration
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
clean: [paths.cssOutput, paths.bower_components],
// copy other css files
copy: {
options: {
'-W069': false,
'reporterOutput': "",
'esnext': true
},
dist: {
expand: true, // required when using cwd
cwd: paths.resetCss, // set working folder / root to copy
src: ['reset.css'], // copy all files and subfolders
dest: paths.cssOutput //'./wwwroot/css/' // destination folder
},
autoCompleteJS: {
expand: true,
cwd: "wwwroot/lib/#tarekraafat/autocomplete.js/dist/js",
src: ['autoComplete.min.js'],
dest: ['wwwroot/js']
},
autoCompleteCSS: {
expand: true,
cwd: "wwwroot/lib/#tarekraafat/autocomplete.js/dist/css",
src: ['autoComplete.css'],
dest: ['wwwroot/css']
}
}
});
// Load the plugin
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.registerTask('downloadPkgs', ['pkg']);
grunt.registerTask('cleanAll', ['clean']);
grunt.registerTask('copyAll', ['copy']);
};
Upon running the task "copy:autoCompleteJS" or "copy:autoCompleteCSS" individually, I'm getting the following warning
Running tasks: copy:autoCompleteCSS
Running "copy:autoCompleteCSS" (copy) task
Verifying property copy.autoCompleteCSS exists in config...OK
Warning: The "path" argument must be of type string. Received type object Use --force to continue.
Aborted due to warnings.
Process terminated with code 3.
Note: If I run the task "copy:dist" it is working fine. I suspect that the path supplied to cwd in the other two has special character "#" in the directory name is causing the issue.
Appreciated your help.
MSRS.
The dest value for both the autoCompleteJS and autoCompleteCSS Targets in your copy Task should be a String and not an Array.
//...
autoCompleteJS: {
expand: true,
cwd: "wwwroot/lib/#tarekraafat/autocomplete.js/dist/js",
src: ['autoComplete.min.js'],
dest: 'wwwroot/js' // <----- Change to this
},
autoCompleteCSS: {
expand: true,
cwd: "wwwroot/lib/#tarekraafat/autocomplete.js/dist/css",
src: ['autoComplete.css'],
dest: 'wwwroot/css' // <----- Change to this
}
//...
Also, although not entirely necessary to avoid the error, consider changing the src value for both Targets to Strings instead of an Array too.

Setting the destination folder with uglify in Grunt

With the Grunt code and folder structure as can be seen below, when I run grunt uglify , the result is that the output creates subfolder structure \js\src within \min folder, where the deepest folder (src) will contain the minified files. But I want the minified files to be created in the \min folder root.
If I set the dest parameter value to empty:``, the files are created in the same folder as the src folder.
If I set the dest parameter value to :/ or /js/min or /js/min/, nothing is created.
How can I generate the minified files directly in the root of the min folder?
module.exports = function(grunt){ // 1
grunt.initConfig({
uglify: {
my_target: {
files: [{
expand: true,
src: 'js/src/*.js',
dest: 'js/min/',
ext : '.min.js',
}]
}
}
});
grunt.loadNpmTasks('grunt-contrib-uglify'); //https://www.npmjs.com/package/grunt-contrib-uglify
grunt.registerTask('default', function() { // 4
grunt.log.writeln('Hello, from the default grunt task!'); // 5
});
}
The Grunt documentation has a relevant section about building the files object dynamically.
Of particular interest is the "cwd" property:
All src matches are relative to (but don't include) this path.
This will allow us to remove the unwanted path from our "src" value by setting it as the value of "cwd". This will mean that the generated source file paths will not have the unwanted prefix ("/js/src/") when they are added to the /js/min folder.
Our resulting Grunt file looks as follows:
module.exports = function (grunt) {
grunt.initConfig({
uglify: {
my_target: {
files: [{
expand: true,
cwd: 'js/src/',
src: '*.js',
dest: 'js/min/',
ext : '.min.js',
}]
}
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['uglify']);
};

How to use Grunt to recursively compile a directory of haml or jade

I have a directory tree full of haml and jade files. How do I use grunt to compile the whole structure into a matching directory tree of html?
Is it possible to use grunt watch to compile changed files into the correct location in the output directory hierarchy?
First you need to install grunt-haml2html (former grunt-contrib-haml)
npm install grunt-haml2html --save-dev
Then add to Gruntfile
grunt.initConfig({
haml: {
main: {
files : [
{ expand: true, cwd:'src', src: '**/*.haml', dest: 'dest', ext : '.html' }
]
},
watch: {
files : {}
}
},
watch: {
haml: {
files: '**/*.haml',
tasks: ['haml:watch'],
options: {
spawn: false
}
}
}
});
grunt.event.on('watch', function(action, filepath) {
if(filepath.indexOf('.haml') === -1) return;
var file = {};
var destfile = filepath.replace('.haml','.html');
file[destfile] = filepath
grunt.config('haml.watch.files', file);
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-haml2html');
Now only changed file will compile
To compile a whole folder use grunt haml:main

Grunt Watch Event with Grunt Copy for Only Changed Files

Okay I've been stuck on this for 2 weeks, so hopefully someone else here has run across this problem. I'm trying to use Grunt to copy only files that have changed. I've seen numerous examples of how to do this with JSLINT and UGLIFY but no specific examples on how to do this with grunt-contrib-copy.
When you register a watch event and pass the filename to the copy subtask, the file name is accessible (i'm logging it out), but the file never copies over properly.
I'm hoping its a simple thing that i'm overlooking. Could someone please have a look at my code and see what I'm doing wrong?
//Gruntfile.js:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
options: {
base: 'app',
dist: 'dist',
},
copy: {
changedFiles: {
expand: true,
dot: true,
cwd: '<%= options.base %>',
src: ['**/*.*'],
dest: '<%= options.dist %>/'
}
},
watch: {
options: {
nospawn: true,
//debounceDelay: 1000,
},
css: {
files: ['app/css/*.css',
'app/js/*.js'
],
tasks: ['copy:changedFiles'],
}
}
});
grunt.event.on('watch', function(action, filepath, target){
grunt.log.writeln('target: ', target + '\n filepath: ' + filepath + '\n action: has ' + action);
grunt.config('copy.changedFiles.src', new Array(filepath) );
});
//load our copy task
grunt.loadNpmTasks('grunt-contrib-copy');
//load our watch task
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('copyChangedFiles', [
'watch:css'
]);
};
Basically my folder setup is as such:
-app
| - css
| - js
-dist
I'm watching the app folder and trying to copy files that change in the app directory and copy them to the dist directory. Dynamically modifying the copy src doesn't seem to be working.
The copy task when run by itself with watch and not on the watch event works just fine and copies every file over, but I'm interested in copying only files that change.
I've also tried a variation of this within my watch event, to no avail:
var copyDest = filepath.replace(grunt.config('copy.changedFiles.dest'), '');
var copyCwd = filepath.replace(grunt.config('copy.changedFiles.cwd'), '');
grunt.config('copy.changedFiles.cwd' , copyCwd);
grunt.config(['copy', 'changedFiles', 'src'] , [filepath]);
Has anyone ever successfully done this before using grunt copy? Or is there another task I should be using? I've tried the same with grunt-sync and that didn't seem to work either. I'm stuck.
Thanks for the help.
You should be able to use the grunt-newer package. The only thing I have noticed about this is that it doesn't do the delete action if the files are removed from the source and are currently in the destination of the copy.
However, for most purposes this should perform the task that you are looking for. Watch will be triggered on a file change, newer will only run if the files in destination are older than the src.
Note: nospawn is deprecated, and is now spawn. It was left for backwards compatibility.
I'm not sure it makes sense for files: [<pattern>] to not match the src pattern described in the copy task.
module.exports = function(grunt) {
grunt.initConfig({
options: {
base: 'app',
dist: 'dist',
},
copy: {
changedFiles: {
expand: true,
dot: true,
cwd: '<%= options.base %>',
src: ['**/*.*'],
dest: '<%= options.dist %>/'
}
},
watch: {
options: {
//nospawn is depricated but kept for compatibility. use spawn false instead
spawn: false,
cwd: '<%= options.base %>'
//debounceDelay: 1000,
},
css: {
//should match above
files: ['**/*.*'],
//On new file detection run copy:changedFiles
tasks: ['newer:copy:changedFiles']
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-newer');
grunt.registerTask('copyChangedFiles', ['watch:css']);
};
I was able to use this SO answer: How to modify grunt watch tasks based on the file changed? and modify it to suit my needs. I'm now able to copy only the files that changed.
My watch now looks like this:
var path = require('path');
grunt.event.on('watch', function(action, filepath, target){
grunt.log.writeln(target + ': ' + filepath + ' might have ' + action);
var siteDirectory = path.dirname(filepath);
//changes changed file source to that of the changed file
var option = 'copy.changedFiles.src';
var result = filepath;
grunt.log.writeln(option + ' changed to ' + result);
grunt.config(option, result);
//customizes output directory so that file goes to correct place
option = 'copy.changedFiles.dest';
result = path.resolve(__dirname + '/dist');
grunt.log.writeln(option + ' changed to ' + result);
grunt.config(option, result);
});
Now running grunt copyChangedFiles will watch the app directory for changes, and any time a *.css or *.js file is modified, it will copy it over to the dist directory.
I really hope this helps someone else since I spent two weeks getting this to work properly.

Using constants in gruntjs

I am trying to write my first Grunt task to copy some files from my common libs folder, which is out of my project directory.
Project Folder : /home/user/projects/bottle
Common Libs directory : /home/user/projects/common
Files' source are inside Common Libs directory at : lib/general/static/js/
Files' destination inside project folder : lib
I have a properties.json file with Common Libs directory path as shown below
{
"common_libs" : `/home/user/projects/common`
}
Now what I already tried is :
module.exports = function(grunt) {
var properties = grunt.file.readJSON('properties.json'),
paths = {
common_libs : properties.common_libs,
common_libs_js : this.common_libs + "lib/general/static/js/"
};
grunt.initConfig({
copy: {
main: {
files: [
{
expand: true,
flatten : true,
src: [
paths.common_libs_js + "/*"
],
dest: 'lib/',
filter: 'isFile'
}
]
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
};
I am running grunt as follows
grunt copy
With this no files are copied to the destination.
Help me in this.
Also I want to know
How can I use Ant's property tag type constants in GruntJS? Because I am getting the base folder from properties.json and I need to copy many files from different folders under the base folder.
Can we have these type of constants per task?
Thanks in advance.
There are a few issues with your code. First:
common_libs_js : this.common_libs + "lib/general/static/js/"
Unfortunately this.common_libs is undefined (this doesn't point to where you think it does), so common_libs_js ends up being 'undefinedlib/general/static/js/', which doesn't work.
The second problem is that on that same line you are concatenating paths, but the first path (from the properties file) doesn't seem to end with a slash, and would become '/home/user/projects/commonlib/general/static/js/' if it wasn't for the previous issue.
Third, you'd get a whole bunch of folders inside your dest path. When the expand option is used, Grunt uses the paths as given in the src property to create the folder structure. If you want /home/user/projects/common/lib/general/static/js/foo.js to be copied to lib/foo.js, you should set the cwd option to paths.common_libs_js and the src to '*.js' (or '**/*.js' for a match on any level).
People usually embed configuration properties inside Grunt's config, and then use template strings to access them. A very common way to write your task would be something like this (with a few changes, adjust as needed):
module.exports = function(grunt) {
grunt.initConfig({
properties: grunt.file.readJSON('properties.json'),
copy: {
main: {
expand: true,
cwd: '<%= properties.common_libs %>/lib/general/static/js',
src: '**/*.js',
dest: 'lib'
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
};
Alternatively, if you want your files to end up in 'lib/general/static/js/' in the destination path too:
module.exports = function(grunt) {
grunt.initConfig({
properties: grunt.file.readJSON('properties.json'),
copy: {
main: {
expand: true,
cwd: '<%= properties.common_libs %>',
src: 'lib/general/static/js/**/*.js',
dest: '.' // because src includes 'lib'
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
};
If you're not sure how Grunt sees your files, run it with grunt -v and it will tell you.
You might also want to consider git submodules for a non-Grunt solution.
For task-specific constants: you could use the task's (or target's) options hash for that, and access it with template strings:
module.exports = function(grunt) {
grunt.initConfig({
properties: grunt.file.readJSON('properties.json'),
copy: {
options: {
foo: 'lib'
},
main: {
options: {
bar: '**/*.js'
},
expand: true,
cwd: '<%= properties.common_libs %>/<%= copy.options.foo %>/general/static/js',
src: '<%= copy.options.main.bar %>',
dest: 'lib'
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
};
This is rarely done for anything other than actual options, though. Conflicts with real options can occur. You could also use the target namespace directly, setting the property directly inside main. But again, there are a few property names that may conflict.
If you want to override properties (e.g. for a release build), you can do this:
module.exports = function(grunt) {
grunt.registerTask('release', function() {
grunt.config.set('properties.common_libs', '/usr/lib/shared');
});
grunt.initConfig({
properties: grunt.file.readJSON('properties.json'),
copy: {
main: {
expand: true,
cwd: '<%= properties.common_libs %>/lib/general/static/js',
src: '**/*.js',
dest: 'lib'
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
};
Then you'd call your task with grunt release copy.
EDIT
Based on your updated question, it doesn't seem like the properties.json file is of much use to you. Why not just specify the properties in your Gruntfile?
module.exports = function(grunt) {
grunt.initConfig({
properties: {
base_dir: '../common',
base_js_dir: '<%= properties.base_dir %>/lib/general/static/js',
base_css_dir: '<%= properties.base_dir %>/lib/general/static/css'
},
copy: {
main: {
expand: true,
cwd: '<%= properties.base_js_dir %>',
src: '**/*.js',
dest: 'lib'
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
};
You can also use the file together with this, if you want. Or even put these properties (with the template strings) inside the properties.json file. In the end it's just a matter of making Grunt see an object with template strings. It's up to you to provide that somehow.

Resources