Grunt - Output file in same folder - gruntjs

I have the following gruntfile.js:
module.exports = function(grunt) {
require('jit-grunt')(grunt);
grunt.initConfig({
uglify: {
options: {
manage: false
},
my_target: {
files: [{
expand: true,
cwd: 'assets/js',
src: '*.js',
dest: 'assets/js/min'
}]
},
},
less: {
development: {
options: {
compress: true,
yuicompress: true,
optimization: 2
},
files: [
{
expand: true, // Recursive
cwd: "assets", // The startup directory
src: ["**/*.less"], // Source files
dest: "assets/", // Destination
ext: ".css" // File extension
}
]
}
},
watch: {
styles: {
files: ['assets/**/*.less', 'assets/js/*.js'], // which files to watch
tasks: ['less', 'newer:uglify'],
options: {
nospawn: true
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-newer');
grunt.registerTask('default', ['less', 'watch', 'newer:uglify']);
};
And the following path distribution:
| assets
|-- folder-1
|-- less
|-- folder-2
|-- less
With the current gruntfile.js, my output is a sub-level of the less folder:
| assets
|-- folder-1
|-- less
|-- css
|-- folder-2
|-- less
|-- css
But it should be on the same level of the LESS file. For example:
| assets
|-- folder-1
|-- less
|-- css
|-- folder-2
|-- less
|-- css
Any idea on how to modify my gruntfile.js? Is that possible?

If I understand your correctly, you want a css/ folder as a sibling of a less/ folder in each of your folder-{x}/ folders.
This can be done by adding the rename property to your less task config:
files: [
{
expand: true, // Recursive
cwd: "assets", // The startup directory
src: ["**/*.less"], // Source files
dest: "assets/", // Destination
ext: ".css", // File extension
rename: function (dest, src) {
return (dest + src.replace('less/', 'css/'));
}
}
]

Related

How to set Gruntfile to ignore files with underscore?

I have several files in my LESS folder with a underscore before the file name. Example:
_variables.less
_colors.less
These files only store data used on other .less files, so they should not have the .css file generated.
Is there any way to set a "ignore" on my gruntfile.js for this kind of file?
Here is my current setup:
module.exports = function(grunt) {
require('jit-grunt')(grunt);
grunt.initConfig({
uglify: {
options: {
manage: false
},
my_target: {
files: [{
expand: true,
cwd: 'assets/js',
src: '*.js',
dest: 'assets/js/min'
}]
},
},
less: {
components: {
options: {
imports: {
reference: [
"assets/less/**/*.less",
]
}
},
files: [{
expand: true,
cwd: 'assets/less',
src: [
'input.less'
],
dest: 'assets/css/',
ext: '.css'
}]
}
},
watch: {
styles: {
files: ['assets/less/**/*.less', 'assets/js/*.js'],
tasks: ['less', 'newer:uglify'],
options: {
nospawn: truetasks
}
}
}
});
grunt.loadNpmTasks('assemble-less');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-newer');
grunt.registerTask('default', ['less', 'watch', 'newer:uglify']);
};

Tell Grunt to put source into same target dir

Code that I have:
coffee: {
compile: {
files: {
'server/api/**/*.js': ['server/api/**/*.coffee'] // compile and concat into single file
}
}
},
Meaning, the target Dir should be the same where the .coffee file was found. Above code in Grunt does however create the directory "**" and puts the file "*.js" into it.
This is what I want:
server/api/sample/sample.coffee -> server/api/sample/sample.js
server/api/sample2/sample2.coffee -> server/api/sample2/sample2.js
To compile your files dinamically you have to do it:
glob_to_multiple: {
expand: true,
flatten: true,
cwd: 'server/api',
src: ['**/*.coffee'],
dest: 'server/api',
ext: '.js',
extDot: 'last'
}

Grunt cssmin for .min.css files

Am using grunt and cssmin to minify my css.
However, in my css assets folder, I have some css that has a .min.css extension. So when I run grunt, only files with .css in my source folder will be minified to be in the build folder. Those files that have .min.css in the source folder will be found in the build folder, but the .min extension will be lost. ie bootstrap.min.css will become bootstrap.css
My Gruntfile.js is as below
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build: {
files: [{
expand: true,
src: '**/*.js',
dest: 'resources/front/js',
cwd: 'assets/front/js'
}]
}
},
cssmin: {
minify: {
expand: true,
cwd: 'assets/front/css/',
src: ['*.css', '*.min.css'],
dest: 'resources/front/css/',
ext: '.css'
}
}
});
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
// Default task(s).
grunt.registerTask('default', ['uglify','cssmin']);
};
Is there any way that the .min.css files can still be minified and be in the build folder and retain the correct '.min.css' extension?
EDIT
See this answer for the most control over file name renaming.
Try this:
cssmin: {
minify: {
files: [{
expand: true,
cwd: 'assets/front/css/',
src: ['*.css', '!*.min.css'],
dest: 'resources/front/css/',
ext: '.css'
}, {
expand: true,
cwd: 'assets/front/css/',
src: ['*.min.css'],
dest: 'resources/front/css/',
ext: '.min.css'
}]
}
}
The first files block will minify only the *.css files and retain the .css extension of those files. The second files block will minify only the *.min.css files and retain the .min.css extension of those files.
I use grunt-contrib-copy: just copy *.min.css to dest.
First of all,exclude all *.min.css files
cssmin:{
min:{
files:[{
expand:true,
cwd:'css',
src:['*.css','!*.min.css'],
dest:'release/css',
ext:'.min.css'
}]
}
}
Second,Copy all *.min.css from css folder as src to release/css folder as dest
copy:{
main:{
files:[{
// Copy *.min.css
expand:true,
src:['css/**/*.min.css'],
dest:'release/'
}]
}
}

Can I configure a grint-contrib-less task to compile into a parallel structure?

Currently we are using grunt-contrib-less to handle our LESS file compiling as a Grunt task. The less files are stored in a structure similar to this:
assets/
styles/
base.less
client/
client.less
device/
tablet.less
phone.less
We have the following for our Grunt config:
less: {
options: {
paths: 'assets/',
yuicompress: false,
ieCompat: true,
require: [
'assets/styles/base.less'
]
},
src: {
expand: true,
cwd: 'assets/',
src: [
'styles/**/*.less'
],
ext: '.css',
dest: 'assets/'
}
},
Currently this is installing all of the generated css files into the same directory as the original less file it came from. What we'd like to do is have them spit out into an /assets/css/ directory, but with the same relative structure. eg:
assets/
css/
base.css
client/
client.css
device/
tablet.css
phone.css
Is there a grunt-contrib-less configuration that can accomplish this?
An easier way to do this seems to be:
less: {
options: {
paths: 'assets/',
ieCompat: true,
require: [
'assets/styles/base.less'
]
},
src: {
expand: true,
cwd: 'assets/styles/',
src: [
'**/*.less'
],
ext: '.css',
dest: 'assets/css'
}
},
I was able to achieve the desired effect wit the following Gruntfile.js
var path = require('path');
module.exports = function(grunt) {
grunt.initConfig({
less: {
options: {
paths: 'assets/',
yuicompress: false,
ieCompat: true,
require: [
'assets/styles/base.less'
]
},
src: {
expand: true,
cwd: 'assets/',
src: [
'styles/**/*.less'
],
ext: '.css',
dest: 'assets',
rename: function(dest, src) {
return path.join(dest, src.replace(/^styles/, 'css'));
}
}
},
});
grunt.loadNpmTasks('grunt-contrib-less');
}
Explanation
Although it is not in the grunt-contrib-less docs there are a bunch more features available for files objects. I didn't realize there were this many until I was working on answering this question. The link for the docs on them is under resources.
Resources
Configuring tasks - Building the files object dynamically

How can I rename files with Grunt, based on the respective file's parent folder name?

I have a the following structure:
src/
modules/
module1/
js/
main.js
scss/
main.scss
index.html
module2/
js/
main.js
scss/
main.scss
index.html
I'd like to run a grunt task to copy these out to the following structure:
dev/
js/
module1.js
module2.js
css/
module1.css
module2.css
module1.html
module2.html
Is there a way to do this with an existing grunt plugin? If not, how could I achieve this?
This can be done using the grunt-contrib-copy plugin.
The main thing to note is that you can change the destination programmatically by using a rename function (which takes in the destination and source of each file).
Here is a (somewhat brittle) sample Gruntfile.js that should copy to your desired structure:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
copy: {
main: {
files: [
{
expand: true,
cwd: 'src/modules/',
src: ['**/*.js'],
dest: 'dev/js/',
rename: function(dest, src) {
// use the source directory to create the file
// example with your directory structure
// dest = 'dev/js/'
// src = 'module1/js/main.js'
return dest + src.substring(0, src.indexOf('/')) + '.js';
}
},
{
expand: true,
cwd: 'src/modules/',
src: ['**/*.scss'],
dest: 'dev/css/',
rename: function(dest, src) {
return dest + src.substring(0, src.indexOf('/')) + '.css';
}
},
{
expand: true,
cwd: 'src/modules/',
src: ['**/*.html'],
dest: 'dev/',
rename: function(dest, src) {
return dest + src.substring(0, src.indexOf('/')) + '.html';
}
}
]
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
// Default task(s).
grunt.registerTask('default', ['copy']);
};
There's no need to use grunt-contrib-copy just for this any more, you can now take advantage of grunt.file.expandMapping which has options to just change the file extension, or to define a function that returns the output filename.
Here's an example of a files object in a jade task for compiling .jade templates into .html files:
files: [{
expand: true,
src: "**/*.jade",
dest: "<%= distDir %>",
cwd: "<%= assetsDir %>/jade",
rename: function(dest, matchedSrcPath, options) {
// return the destination path and filename:
return (dest + matchedSrcPath).replace('.jade', '.html');
}
}]
It would have been easier to use the ext: '.html' option instead of the rename option in this case, but I'm using rename here so you can see how it works.
More info about the ext and rename (and other) options in the grunt.file docs. Some more examples here and here.
You could simply use the options:
expand : true,
flatten: true
No need for custom rename callbacks.
if u want to rename .coffee files to .js or similar then just adapt it ;)
sudo npm install grunt-contrib-copy
copy: {
rename: {
files: [{
expand: true,
dot: true,
cwd: './app/scripts',
dest: './app/scripts/',
src: [
'**/*.coffee'
],
rename: function(dest, src) {
console.log(dest + src);
return dest + src.replace('.coffee','.js');
}
}]
}
},
Not exactly an answer to your question but i made it here looking for relative dest folders with grunt so... Here is how i solved it
...
base: {
files:
[
{
expand: true,
cwd: 'app/design/frontend/',
src: ['**/Magento_Sales/email-src/*.html'],
dest: '../../Magento_Sales/email/',
rename: function(dest, src, expand) {
src = path.parse(src)
return path.join(expand.cwd, src.dir, dest, src.base);
}
},
],
}
...
This little bit path.join(expand.cwd, src.dir, dest, src.base); just creating the path i need.
expand.cwd = app/design/frontend/
src.dir = <DYNAMIC_FOLDERS>/Magento_Sales/email-src/
dest = ../../Magento_Sales/email/
src.base = <FILE>.html
and all together it = app/design/frontend/<COMPANY>/<MAIN-THEME>/Magento_Sales/email/<FILE>.html
and in my situation it will now compile my html emails in relative destination folders
I wanted to save the file in a min folder created at the root where we found the file so it's more easy to moove the plugin folder into another project :
-- Plugins/
-- bootstrap/
-- bootstrap.js
-- bootstrap.css
-- min/
-- bootstrap.min.js
-- bootstrap.min.css
I post the solution I found thanks to this page maybe it can help others :
uglify: {
options: {
mangle: true
},
dynamic_mappings: {
// Grunt will search for "**/*.js" under "Plugins/" when the "uglify" task
// runs and build the appropriate src-dest file mappings then, so you
// don't need to update the Gruntfile when files are added or removed.
files: [
{
expand: true, // Enable dynamic expansion.
cwd: 'Plugins/', // Src matches are relative to this path.
src: ['**/*.js', '!**/*.min.js'], // Pattern to match (ignore .min files)
dest: '/min/', // Destination path prefix.
ext: '.min.js', // Dest filepaths will have this extension.
extDot: 'last', // Extensions in filenames begin after the first dot
rename: function( dest, matchedPath, options ) {
Pathname = matchedPath.substring( 0, matchedPath.indexOf('/') );
Filename = matchedPath.replace( Pathname, '' );
//Return "Plugins / plugin_folder / min / file_name.min.js"
return options.cwd + Pathname + dest + Filename;
}
},
],
},
}

Resources