Specifying Grunt output to a dynamic parallel folder - gruntjs

The Context
I'm new to Grunt and am trying to learn a bit by modifying the meanjs boilerplate to support stylus, I would like to keep my precompiled css assets organized in modular buckets, as recommended by the current meanjs defaults.
The Question
I have the following file structure:
- app
- config
- public
- modules
- foo
- assets
- stylesheets
...
- css
...
...
How can I use Grunt to take Stylus .styl files in the public/modules/*/assets/stylesheets directory, and have them compile to the public/modules/*/css directory?
Naive Attempt:
Below is an example attempt, which didn't get very far.
stylus: {
compile: {
files: [{
dest: '../../css',
src: 'public/modules/*/assets/stylesheets/*.styl',
ext: '.css',
expand: true
}]
}
}
This results in: File ../../css/public/modules/foo/assets/stylesheets/baz.css created.
If I leave "dest" empty, it does properly compile but the output is in the assets/stylesheets folder (as expected). I'm sure there is a clean way to do this, but I don't know yet.

setting the src, dest, cwd, as well as using the hidden rename options of grunt should get stylus files in your desired format.
example:
stylus: {
compile: {
options: {
compress: true
},
files: [{
cwd: 'public/modules',
dest: 'public/modules',
src: ['*/assets/stylesheets/*.styl'],
expand: true,
rename: function(dest, src) {
var path = require('path');
var module = src.split(path.sep).slice(0,1)[0];
return path.join(dest, module + '/css/' + module + '.css');
}
}]
}
},
grunt tricks - customize file output rename

Related

grunt less multiple css files keeping folder structure

I have a branding application where I would like to have this output:
/branding/
/default/
default.css
/brand1/
brand1.css
/brand2/
brand2.css
This one should be output from a branding folder with same structure but with .less files
So I would like to do something like this:
less: {
production: {
options: {
},
files: {
'dist/branding/**/*.css': 'branding/**/*.less'
}
}
}
I just seen examples on this where they all go to same folder, but I want to keep this dynamic because in my case there is like a ton of brandings, and the branding folders have more than just a css file, they also have other artifacts like images and so on.
Any suggestions?
If I understand you correctly you want LESS files under branding compiled to a dist/branding folder and to keep the folder structure.
To do that you would do something like this:
files: [
{
expand: true, // Recursive
cwd: "branding", // The startup directory
src: ["**/*.less"], // Source files
dest: "dist/branding", // Destination
ext: ".css" // File extension
}
]
You can visit http://rajdeepdeb.me/less-to-css-grunt-for-multiple-files/
Add the following configuration in your grunt file
...rest of the grunt configuration,
files: [{
expand: true,
cwd: '/',
src: ['**/*.less'],
dest: '/',
ext: '.css',
extDot: 'last'
}],
... rest of the grunt configuration

How to set CSS Source Map output destination when grunt-contrib-less is used

I am using grunt-contrib-less for compiling less files.
I have grunt locally installed at root of project folder.
The css files are located at qa1/avinash/html5/phase1/css/ path from root of project folder.
So this is the path i am specifying for cwd (current working directory), src and dest parameters of the grunt-less task. there are no issues in compilation of css and source map.
The only issue i face is that the source map is generated in the same folder of gruntfile. but my generated css is at the dest path i specified. since the css and source map are at different locations i have to manually edit the less path references in source map and bring it to the generated css directory. or use sourceMapURL to specify the source map location ../../../../../style.css.map(backwards). Both ways are not convenient.
So can anyone help me how to specify the source map output destination path like we specify for destination path for generated css something like
sourceMapDest: 'qa1/avinash/html5/phase1/css/'
--
currently used Gruntfile.js:
module.exports = function(grunt) {
grunt.initConfig({
less: {
options: {
sourceMap:true,
sourceMapFilename: "style.css.map",
sourceMapURL: '../../../../../style.css.map'
},
src: {
// no need for files, the config below should work
expand: true,
cwd: "qa1/avinash/html5/phase1/css/",
src: "style.less",
dest: "qa1/avinash/html5/phase1/css/",
ext: ".css"
}
},
watch: {
js: {
files: ['qa1/avinash/html5/phase1/css/'],
tasks: ['default'],
}
}
});
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['less']);
};
The sourceMapFilename option may include a path part as well.
I.e. just change it to:
sourceMapFilename: "qa1/avinash/html5/phase1/css/style.css.map"

Can't get a modular Sass structure working within mean.js grunt

I setup a grunt tast to compile all sass and scss files into css using grunt-contrib-sass.
The issue I am facing is because it's a modular architecture, I don't have a single sass and css folder.
Instead I have a sass and css folder for each module.
When I specify the module name it works and compiles the sass file into css, but only for that module, like so:
sass: {
dev: {
expand: true,
cwd: 'public/modules/someModuleName/sass',
src: ['*.{scss,sass}'],
dest: 'public/modules/someModuleName/css',
ext: ['.css']
}
}
Instead I need it to compile the sass files into css for each module dynamically, like so:
sass: {
dev: {
expand: true,
cwd: 'public/modules/**/sass',
src: ['*.{scss,sass}'],
dest: 'public/modules/**/css',
ext: ['.css']
}
}
Here is the folder structure:
|-public
|--modules
|---SomeModuleName1
|----Sass
|-----*.scss
|----CSS
|-----*.css
|---SomeModuleName2
|----Sass
|-----*.scss
|----CSS
|-----*.css
From the looks of the directory structure and based on the mean.io tag, I'm assuming you are using meanjs.org or mean.io.
What I did and recommend is that if you are going with sass, you go all in sass.
Rename your each css folder under public/modules/*/ to scss
Convert the existing *.css files to *.scss files
Create a new [style/scss/stylesheets] folder in the public directory
Create a new file(style.scss or main.scss) as the main style file. Recommend main.scss as a convention.
In your main.scss you import the module scss files:
#import "../modules/core/style/core";
#import "../modules/users/style/users";
This step is kind of annoying and I'm sure it can be automated somehow. (2 options below)
https://www.npmjs.com/package/grunt-sass-directory-import
https://github.com/chriseppstein/sass-globbing
For your sass task:
sass: {
options: {
sourcemap: 'none',
update: true
},
dev: {
options: {
lineNumbers: true
},
files: {
'public/dist/application.css': 'public/style/main.scss'
}
},
dist: {
options: {
style: 'compressed'
},
files: {
'public/dist/application.min.css': 'public/style/main.scss'
}
} },
Cleanup work to your gruntfile:
You would need to add clientSCSS to your watchFiles if you want and
run the sass:dev task.
csslint task is not needed and should be
replaced with scsslint.
cssmin task is not needed as the sass:dist
has the compressed option.
Cleanup work in all.js and production.js:
Remove references to *.css files in the assets:lib:css and assets:css with the exception of public/dist/application.css and public/dist/application.min.css
Use the corresponding sass version of bootstrap if you want instead and follow the #include approach in main.scss

Expand not working in grunt-contrib-less task for dynamic selection

I've been playing with Grunt and one of the things I wanted to use it for was to compile my LESS files, but for some reason the expand: true (I commented everything out from the bottom up and it stopped throwing the err after commenting out expand) in the less:mini task is causing this error: Warning: Object true has no method 'indexOf' Use --force to continue. Does anyone know why this is happening? I can dynamically build the file object in grunt-contrib-copy no problem, and expand is required for the other options to work.
less: { // Set up to detect files dynamically versus statically
mini: {
options: {
cleancss: true, // minify
report: 'min' // minification results
},
files: {
expand: true, // set to true to enable options following options:
cwd: "dev/less/", // all sources relative to this path
src: "*.less", // source folder patterns to match, relative to cwd
dest: "dev/css/", // destination folder path prefix
ext: ".css", // replace any existing extension with this value in dest folder
flatten: true // flatten folder structure to single level
}
}
}
Thanks
files is intended to be used as an array or src-dest mappings. Grunt is interpreting the above properties within less.mini.files as src-dest mappings. See: http://gruntjs.com/configuring-tasks#files-object-format
You don't need to nest properties within files if you're not using that format. Modify your config to:
less: { // Set up to detect files dynamically versus statically
mini: {
options: {
cleancss: true, // minify
report: 'min' // minification results
},
expand: true, // set to true to enable options following options:
cwd: "dev/less/", // all sources relative to this path
src: "*.less", // source folder patterns to match, relative to cwd
dest: "dev/css/", // destination folder path prefix
ext: ".css", // replace any existing extension with this value in dest folder
flatten: true // flatten folder structure to single level
}
}

Grunt recursive copy

I'm setting up a Grunt script that needs to copy and reorganise directories of images from A to B. Simple enough.
Directory structure:
components
componentA
js
img
imgfolderA
imgfolderB
css
componentB
js
img
imgfolderA
Each img directory could contain other directories and directories within those directories to help organise the images.
I want to use Grunt to take all those images and put them under one directory (assets/img):
assets
img
dirA
imgfolderA
imgfolderB
dirB
imgfolderA
Any ideas on how could I do this in grunt without specifying each component directory (it needs to be fully automated)?
know it's a bit late but this should do the job, use 'grunt-contrib-copy' like so
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
copy: {
production: {
files: [{
expand: true,
cwd: "componentA/img/imgfolderA/",
src: ["*.*", "**/*.*"],
dest: "./assets/img/dirA/",
},
{
expand: true,
cwd: "componentB/img/imgfolderB/",
src: ["*.*", "**/*.*"],
dest: "./assets/img/dirB/",
},
]
}
}
});
// Production Build Tools
grunt.loadNpmTasks('grunt-contrib-copy');
// Default Production Build task(s).
grunt.registerTask('default', ['copy']);
};
ps magic is in the files objects, there not very well documented, but the documentation is here, after one or two reads it makes sense honest!
grunt-contrib-copy setup: https://github.com/gruntjs/grunt-contrib-copy (the readme at the bottom)
files object setup: http://gruntjs.com/configuring-tasks#globbing-patterns
task setup: http://gruntjs.com/configuring-tasks
This is rather simple using grunt.file.expand.
Just pass matching glob patterns (e.g. **/img/**), and then recurse on the returned matching file values to copy.

Resources