I'm using Grunt with node.js, and trying to get Grunt to tell me where it finds errors in Gruntfile.js. It seems weird that it wouldn't do that by default.
For grunt watch, I'm getting this error:
Loading "Gruntfile.js" tasks...ERROR
>> SyntaxError: Unexpected string
Warning: Task "watch" not found. Use --force to continue.
I'd really like to know what line that unexpected string is on, but I can't get Grunt to tell me.
When I try grunt watch --stack, it shows me the entire node.js stack trace of the node files, but not the source of the error in Gruntfile.js.
Adding grunt.option('stack', true); to the top of Gruntfile.js, as suggested in this answer, has no effect whatsoever.
My Gruntfile.js:
var path_dev = 'app/assets/_dev';
var path_live = 'app/assets';
var url_dev = '//assets.domain.dev/_dev';
module.exports = function (grunt) {
grunt.option('stack', true);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
banner: '/*!\n' +
'* <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %> - Copyright <%= grunt.template.today("yyyy") %> \n' +
'* @author <%= pkg.author %>\n' +
'*/',
path_dev: path_dev,
path_live: path_live,
url_dev: url_dev,
clean: {
build: {
src: [
'<%= path_live %>/css/',
'<%= path_live %>/js/'
]
}
},
concat: {
options: {
separator: ';'
},
build: {
src: [
'<%= path_dev %>/js/core/jquery.min.js',
'<%= path_dev %>/js/core/bootstrap.min.js',
'<%= path_dev %>/js/core/jquery.slimscroll.min.js',
'<%= path_dev %>/js/core/jquery.scrollLock.min.js',
'<%= path_dev %>/js/core/jquery.appear.min.js',
'<%= path_dev %>/js/core/jquery.countTo.min.js',
'<%= path_dev %>/js/core/jquery.placeholder.min.js',
'<%= path_dev %>/js/core/js.cookie.min.js',
'<%= path_dev %>/js/main.js'
],
dest: '<%= path_live %>/js/global.js'
}
},
uglify: {
options: {
banner: '<%= banner %>'
},
build: {
files: {
'<%= path_live %>/js/global.js': ['<%= path_live %>/js/global.js']
}
}
},
copy: {
build: {
files: [
{
expand: true,
cwd: '<%= path_dev %>/css/',
src: 'bootstrap.min.css',
dest: '<%= path_live %>/css/'
},
{
expand: true,
cwd: '<%= path_dev %>/fonts/',
src: '**',
dest: '<%= path_live %>/fonts/'
},
{
expand: true,
cwd: '<%= path_dev %>/img/',
src: '**',
dest: '<%= path_live %>/img/'
},
{
expand: true,
cwd: '<%= path_dev %>/js/plugins/',
src: '**',
dest: '<%= path_live %>/js/plugins/'
}
]
}
}
});
var tasks_to_watch = [];
var less = {};
var watch = {};
//less:build
less['build'] = {
options: {
compress: true,
yuicompress: true,
optimization: 2,
},
files: {}
};
less['build']['files'][path_live+'/css/global.css'] = path_dev'/less/main.less';
less['build']['files'][path_live+'/css/apps/**/*.css'] = path_dev'/less/apps/**/*.less';
//less:dev_main
less['dev_main'] = {
options: {
sourceMap: true,
sourceMapURL: url_dev+'/css/global.css.map',
},
files: {}
};
less['dev_main']['files'][path_dev+'/css/global.css'] = path_dev'/less/main.less';
tasks_to_watch.push('less:dev_main');
//less:(dynamically find .less files)
grunt.file.recurse(path_dev+'/less/apps/', function(abspath, rootdir, subdir, filename) {
if(filename.match(/\.less$/g)){
var name = filename.substring(0, filename.lastIndexOf('.'));
var thisurl = url_dev+'/css/apps/app/'+name+'.css';
var thispath = path_dev+'/css/apps/app/'+name+'.css';
less[name] = {
options: {
sourceMap: true,
sourceMapURL: thisurl+'.map',
},
files: {}
};
less[name]['files'][thispath] = abspath;
tasks_to_watch.push('less:'+name);
}
}); //grunt.file.recurse()
watch = {
styles: {
files: [path_dev+'/less/**/*.less'],
tasks: tasks_to_watch,
options: {
nospawn: true
}
}
};
//now repurpose the array to contain all tasks, so we can register them all below
tasks_to_watch.push('less:build');
tasks_to_watch.push('watch');
//load tasks
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.config('less', less);
grunt.config('watch', watch);
//register tasks
grunt.registerTask('default', tasks_to_watch);
grunt.registerTask('build', ['clean:build', 'less:build', 'concat:build', 'uglify:build', 'copy:build']);
};
The problems are on lines: 104, 105 and 116, you missed the plus + sign after path_dev:
less['build']['files'][path_live+'/css/global.css'] = path_dev+'/less/main.less';
Please fix you the other ones.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With