grunt-sass, no errors log when 'watching' - sass

I'm using the following grunt tasks
grunt-sass
grunt-contrib-watch
grunt-autoprefix
node-bourbon
(there are a few other tasks, such as uglify, spritesmith, and haml, which i have left out of this example)
My grunt file looks like this:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
options: {
sourceMap: true,
outputStyle: 'compressed',
imagePath: 'assets/css/img',
includePaths: require('node-bourbon').includePaths
},
dist: {
files: {
'assets/css/app.css': 'assets/sass/app.scss'
}
}
},
autoprefixer: {
options: {
browsers: ['last 2 version', 'ie 8', 'ie 9'],
silent : false
},
dev: {
src: 'assets/css/app.css',
dest: 'assets/css/post.css'
},
},
watch: {
options: {
livereload: true
},
sass: {
files: ['assets/sass/**/*.scss', 'assets/sass/*.scss'],
tasks: ['sass:dist', 'autoprefixer:dev']
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-autoprefixer');
grunt.registerTask('default', ['watch', 'sass']);
};
This is working. However, if there is an error in my sass file nothing is reported. For instance if I try and use an $variable that doesn't exist, no errors are reported in my terminal
Here are two subsequent logs, the first compiles successfully with no errors. The second doesn't compile (as there is an undefined variable in the scss file)
Completed in 1.712s at Sun Sep 28 2014 15:23:17 GMT+0100 (GMT Daylight Time) - Waiting...
>> File "assets\sass\app.scss" changed.
Running "sass:dist" (sass) task
File assets/css/app.css created.
File assets/css/app.css.map created.
Running "autoprefixer:dev" (autoprefixer) task
File assets/css/post.css created.
Done, without errors.
C:\wamp\www\_bp2>grunt
Running "watch" task
Waiting...
>> File "assets\sass\app.scss" changed.
Running "sass:dist" (sass) task
Completed in 1.656s at Sun Sep 28 2014 15:29:25 GMT+0100 (GMT Daylight Time) - Waiting...
Does anyone know why no errors are being logged?
I'm in the process of rebuilding my sass boilerplate to use libsass and bourbon instead of compass. So I'm expecting to come across loads of errors during the process, so I really need to know what these errors are.
Thanks

Related

How can I force Grunt to compile Sass even when no changes have been made?

I want grunt to compile sass every time grunt is executed if my Sass files haven't changed. Sometimes the watcher fails to detect if the compiled result is different from the existing CSS file, and the only way to force it to compile is by editing one of the Sass files.
Grunt file:
/**
* #file
*/
module.exports = function(grunt) {
// This is where we configure each task that we'd like to run.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
// This is where we set up all the tasks we'd like grunt to watch for changes.
scripts: {
files: ['js/source/{,*/}*.js'],
tasks: ['uglify'],
options: {
spawn: false,
},
},
images: {
files: ['images/source/{,*/}*.{png,jpg,gif}'],
tasks: ['imagemin'],
options: {
spawn: false,
}
},
vector: {
files: ['images/source/{,*/}*.svg'],
tasks: ['svgmin'],
options: {
spawn: false,
}
},
css: {
files: ['sass/{,*/}*.{scss,sass}'],
tasks: ['sass']
}
},
uglify: {
// This is for minifying all of our scripts.
options: {
sourceMap: true,
mangle: false
},
my_target: {
files: [{
expand: true,
cwd: 'js/source',
src: '{,*/}*.js',
dest: 'js/build'
}]
}
},
imagemin: {
// This will optimize all of our images for the web.
dynamic: {
files: [{
expand: true,
cwd: 'images/source/',
src: ['{,*/}*.{png,jpg,gif}' ],
dest: 'images/optimized/'
}]
}
},
svgmin: {
options: {
plugins: [{
removeViewBox: false
}, {
removeUselessStrokeAndFill: false
}]
},
dist: {
files: [{
expand: true,
cwd: 'images/source/',
src: ['{,*/}*.svg' ],
dest: 'images/optimized/'
}]
}
},
sass: {
// This will compile all of our sass files
// Additional configuration options can be found at https://github.com/sindresorhus/grunt-sass
options: {
sourceMap: true,
// This controls the compiled css and can be changed to nested, compact or compressed.
outputStyle: 'expanded',
precision: 5
},
dist: {
files: {
'css/base/base.css': 'sass/base/base.sass',
'css/components/components.css': 'sass/components/components.sass',
'css/components/tabs.css': 'sass/components/tabs.sass',
'css/components/messages.css': 'sass/components/messages.sass',
'css/layout/layout.css': 'sass/layout/layout.sass',
'css/theme/theme.css': 'sass/theme/theme.sass',
'css/theme/print.css': 'sass/theme/print.sass'
}
}
},
browserSync: {
dev: {
bsFiles: {
src : [
'css/**/*.css',
'templates/{,*/}*.twig',
'images/optimized/{,*/}*.{png,jpg,gif,svg}',
'js/build/{,*/}*.js',
'*.theme'
]
},
options: {
watchTask: true,
// Change this to "true" if you'd like the css to be injected rather than a browser refresh. In order for this to work with Drupal you will need to install https://drupal.org/project/link_css keep in mind though that this should not be run on a production site.
injectChanges: false
}
}
},
});
// This is where we tell Grunt we plan to use this plug-in.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.loadNpmTasks('grunt-svgmin');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-browser-sync');
// Now that we've loaded the package.json and the node_modules we set the base path
// for the actual execution of the tasks
// grunt.file.setBase('/')
// This is where we tell Grunt what to do when we type "grunt" into the terminal.
// Note: if you'd like to run and of the tasks individually you can do so by typing 'grunt mytaskname' alternatively
// you can type 'grunt watch' to automatically track your files for changes.
grunt.registerTask('default', ['browserSync','watch']);
};
grunt.registerTask('default', [
'browserSync',
'sass',
'watch',
]);
Simply register sass as a task to run when you type grunt.
If you do this and the sass files are still not giving you the results you want, then you need to revisit your sass task and make sure you're piping the files where you want them to go.
More cool options:
newer: When you run grunt you want sass to compile to CSS only if there is a difference between the new CSS and the old. In that case, try grunt-newer. Appending newer:taskyouwanttorun:option will work.
watch:sass: You want sass to compile during a watch based on something besides changing one of the sass files. Easy, just set up a watch task that looks for whatever file you want to modify, image/javascript/html/whatever and set the task as sass

Visual Studio 2015 autoprefixer

I find Web Essentials autoprefixer not auto enough - I need to manually say it to add prefixes. Also it doesn't offer me prefixes when I'm writing .less or .scss.
Is there any extension or option to make it automatically add prefixes on css compilation from .less or .scss stage?
I've tried Web Compiler extension, but it doesn't support prefixing for sass, and says that it supports prefixing for less, but I've tried enabling autoprefix in compilerconfig.json while writing .less and it didn't add anything.
Is there something for visual studio? Or maybe I should dump it and use some editor + gulp?
I'm sure there will be an extension out there but it isn't too much work to create a Grunt/Gulp file to do your compiling for you. Task Runner Explorer will then manage the running of the file. Writing your own will give you the control and the flexibility that an extension will not.
Here is a sample using Grunt, taken from my post on the subject Getting started with Grunt, SASS and Task Runner Explorer
module.exports = function (grunt) {
'use strict';
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-autoprefixer');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// Sass
sass: {
options: {
sourceMap: true, // Create source map
outputStyle: 'compressed' // Minify output
},
dist: {
files: [
{
expand: true, // Recursive
cwd: "sass", // The startup directory
src: ["**/*.scss"], // Source files
dest: "stylesheets", // Destination
ext: ".css" // File extension
}
]
}
},
// Autoprefixer
autoprefixer: {
options: {
browsers: ['last 2 versions'],
map: true // Update source map (creates one if it can't find an existing map)
},
// Prefix all files
multiple_files: {
src: 'stylesheets/**/*.css'
},
},
// Watch
watch: {
css: {
files: ['sass/**/*.scss'],
tasks: ['sass', 'autoprefixer'],
options: {
spawn: false
}
}
}
});
grunt.registerTask('dev', ['watch']);
grunt.registerTask('prod', ['sass', 'autoprefixer']);
};

Grunt - pass filename variable from command line

I am struggling to understand how I can pass a partial filename from the grunt command line, in order to run a task (from an installed grunt module) on a particular file.
What I want to be able to do is configure a series of tasks to take filename parameter from the command line.
I've tried reworking the final example on this page http://chrisawren.com/posts/Advanced-Grunt-tooling but I'm kind of stabbing in the dark a bit. Thought someone would have a quick answer.
Here is my Gruntfile:
module.exports = function (grunt) {
grunt.initConfig({
globalConfig: globalConfig,
uglify: {
js: {
options: {
mangle: true
},
files: {
'js/<%= globalConfig.file %>.min.js': ['js/<%= globalConfig.file %>.js']
}
}
},
});
// Load tasks so we can use them
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('go', 'Runs a task on a specified file', function (fileName){
globalConfig.file = fileName;
grunt.task.run('uglify:js');
});
};
I attempt to run it from the command line like this:
grunt go:app
to target js/app.js
I get this error:
Aborted due to warnings.
roberts-mbp:150212 - Grunt Tasks robthwaites$ grunt go:app
Loading "Gruntfile.js" tasks...ERROR
>> ReferenceError: globalConfig is not defined
Warning: Task "go:app" not found. Use --force to continue.
Thanks
you can use grunt.option.
your grunt register task will look like this.
> grunt.option('fileName'); grunt.registerTask('go', 'Runs a task on a
> specified file', function (){
> grunt.task.run('uglify:js');
> });
your grunt configuration will be
module.exports = function (grunt) {
var fileName=grunt.option('fileName');
grunt.initConfig({
uglify: {
js: {
options: {
mangle: true
},
files: {
'js/fileName.min.js': ['js/fileName.js']
}
}
},
});
command to run the task from terminal:
$ grunt go --fileName='xyzfile'
I the end I was able to accomplish what I wanted like this, but not sure if this is a standard way.
What I was failing to do was declare the globalConfig variable globally first, so that I could redefine it from the Terminal as I ran my grunt task.
Here is an example. When working with HTML emails I need to:
Process my sass files to css (grunt-contrib-sass)
Run an autoprefixer on the resulting css (grunt-autoprefixer)
Minify my CSS and remove CSS comments (grunt-contrib-cssmin)
Include my full CSS in a tag the of my html file (using grunt-include-replace)
Finally, run premailer on the file to inline all styles (grunt-premailer)
The point is, if I am working on several different HTMl emails in the same project, I need to be able to run all these tasks on html files one-by-one, as needed. The Gruntfile below allows me to do this.
What this does:
If you enter into terminal grunt It will simply run the sass task, which processes all sass files - no file parameter needed from Terminal.
However, if I wish to run a series of processes on a single html file, I enter grunt process:fileName with fileName being the name of the html file without the .html extension.
You will notice that the only tasks that require the fileName are actually include-replace and premailer. However, I still want to run al the other CSS cleanup tasks prior to targetting my chosen file.
The key is:
Declaring the global variable
Load the globalConfig variables into the grunt.initConfig
Use the grunt variable declaration where needed in your tasks
register your custom task, with the fileName variable being used as a paramater.
Hope that helps someone.
module.exports = function (grunt) {
var globalConfig = {
file: 'index' // this is the default value, for a single project.
}
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// load the globalConfig variables
globalConfig: globalConfig,
sass: {
dev: {
files: [{
expand: true,
cwd: 'scss',
src: ['*.scss'],
dest: 'css',
ext: '.css'
}]
}
},
cssmin: {
options: {
keepSpecialComments: 0,
keepBreaks: true,
advanced: false
},
target: {
files: [{
expand: true,
cwd: 'css',
src: '*.css',
dest: 'css',
ext: '.css'
}]
}
},
autoprefixer: {
css: {
src: "css/*.css"
}
},
includereplace: {
your_target: {
options: {
prefix: '\\/\\* ',
suffix: ' \\*\\/',
},
files: {
'inline/<%= globalConfig.file %>-inline.html': ['<%= globalConfig.file %>.html']
}
}
},
premailer: {
main: {
options: {
verbose: true,
preserveStyles: true,
},
src: 'inline/<%= globalConfig.file %>-inline.html',
dest: 'inline/<%= globalConfig.file %>-inline.html'
}
},
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-autoprefixer');
grunt.loadNpmTasks('grunt-include-replace');
grunt.loadNpmTasks('grunt-premailer');
grunt.registerTask('default', 'sass');
grunt.registerTask('process', 'Runs all processing tasks on a specific file to produce inlined file', function (fileName) {
globalConfig.file = fileName;
grunt.task.run('sass', 'autoprefixer', 'cssmin', 'includereplace', 'premailer');
});
}
EDIT: Obviously at the moment this accepts only one parameter I beleive. In other use cases the grunt.option version above could give more functionality, being able to submit several parameters in one command. I will continue to experiment with grunt.option if I find the need to do this.

Unable to load grunt, not sure what i am doing wrong or what i need to do

I am trying to run my first project using grunt. i am stuck at the point when i try running grunt in the command line i get an error/warning like this:
Traviss-MacBook-Pro-2:GRUNT Travis$ grunt compass
>> Local Npm module "grunt-contrib-jshint" not found. Is it installed?
>> Local Npm module "grunt-contrib-qunit" not found. Is it installed?
Warning: Task "compass" not found. Use --force to continue.
Aborted due to warnings.
I installed both jshint and qunit so i am lost on what to do next for fixing this problem.
Any help would be greatly appreciated, thank you.
Here is my grunt.js file
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
separator: ';'
},
dist: {
src: ['src/**/*.js'],
dest: 'dist/<%= pkg.name %>.js'
}
},
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
},
dist: {
files: {
'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
}
}
},
qunit: {
files: ['test/**/*.html']
},
jshint: {
files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
options: {
// options here to override JSHint defaults
globals: {
jQuery: true,
console: true,
module: true,
document: true
}
}
},
watch: {
files: ['<%= jshint.files %>'],
tasks: ['jshint', 'qunit']
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('test', ['jshint', 'qunit']);
grunt.registerTask('default', ['jshint', 'qunit', 'concat', 'uglify']);
};
You probably don't have the 'grunt-contrib' modules that use qunit and jshint in a grunt task form. You should be able to check with something like npm ls | grep contrib.
I'd suggest, within your project, running:
npm install grunt-contrib-jshint --save-dev
and
npm install grunt-contrib-qunit --save-dev
I would've expected some of the other grunt.loadNpmTasks()-specified modules to choke too, so I'm a little surprised more errors are not happening.
As for "Warning: Task "compass" not found", there is no 'compass' target in your gruntfile (as there is for qunit, watch, etc.), so that makes sense. You'll either want to add in a 'compass' task to do stuff under that name or specify another target to grunt on the command-line (or omit any specific target to execute your default ['jshint', 'qunit', 'concat', 'uglify'] tasks).

Grunt file fails 'Aborted due to warnings'

I'm new to Grunt. I thought I'd give it a try, so I created this grunt file.
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
css: {
src: [
'./css/*'
],
dest: './css/all.css'
},
js: {
src: [
'./js/*'
],
dest: './js/all.js'
}
},
uglify: {
js: {
files: {
'./js/build/all.min.js': ['./js/all.js']
}
}
},
sass: {
build: {
files: [{
expand: true,
cwd: './css/sass',
src: ['*.scss'],
dest: './css',
ext: '.css'
}]
}
},
cssmin: {
css: {
src: './css/all.css',
dest: './css/build/all.min.css'
}
},
watch: {
files: ['./css/sass/*', './js/*'],
tasks: ['sass:build','concat:css', 'cssmin:css', 'concat:js', 'uglify:js']
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('dev', ['sass:build','concat:css', 'cssmin:css', 'concat:js', 'uglify:js']);
};
When I run 'grunt watch' and make a change to an .scss file, terminal complains and then aborts.
Running "watch" task
Waiting...
>> File "css/sass/all.scss" changed.
Running "sass:build" (sass) task
File css/all.css created.
Running "concat:css" (concat) task
Warning: Unable to read "./css/build" file (Error code: EISDIR). Use --force to continue.
Aborted due to warnings.
Completed in 1.276s at Thu May 01 2014 23:53:59 GMT+0100 (BST) - Waiting...
Please can someone point out where I'm going wrong?
It looks to be with the concat:css - but there's no reference to the build directory there.
I believe it may be because certain tasks are colliding and files aren't ready yet to be worked with perhaps? Is there an order to tasks?
Please bear with me as it's all new!
Thanks,
Michael.
I notice this is quite old, but I'll add an answer for posterity.
This was happening to me because of a missing variable in the SASS file.
Try adding "--force" onto your grunt command. The build will still fail, but you will probably get a more helpful error message.
try to add the nospawn: true option into de the sass task options.
Also if you want to have a more complete error response you could run grunt --verbose

Resources