Tell Grunt to put source into same target dir - gruntjs

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'
}

Related

Assemble handlebar template relative to its path

So I'm trying to look through a directory and compile all hbs files. But the thing is that the hbs file should compile in the folder it lies in.
pseudo code:
assemble: {
options: {
flatten: false,
assets: 'assets',
dev: true,
livereloadPort: '<%- livereloadPort %>',
partials: ['dev/assemble/partials/*.hbs'],
layout: 'dev/assemble/banner.hbs',
data: ['dev/assemble/data/*.{json,yml}']
},
// ----------------------------------------------------------------
// assembles
dev: {
options: {
data: ['dev/assemble/data/*.{json,yml}']
},
src: ['dev/banners/**/*.hbs'],
expand: true,
dest: '<% SAME AS SRC FILE %>',
ext: '.html'
}
},
So basically this folder structure;
/banners/
/bannerfolder_1/
handlebarfile.hbs
/bannerfolder_2/
another_handlebarfile.hbs
Would result in this;
/banners/
/bannerfolder_1/
handlebarfile.hbs
handlebarfile.html
/bannerfolder_2/
another_handlebarfile.hbs
another_handlebarfile.html
Can this be done?
Try the following globbing pattern / dynamic mapping
files: {
expand: true, // Enable dynamic expansion.
cwd: 'dev/', // Src matches are relative to this path.
src: ['banners/**/*.hbs'], // Actual pattern(s) to match.
dest: 'dev/', // Destination path prefix.
ext: '.html', // Dest filepaths will have this extension.
extDot: 'last' // Extensions in filenames begin after the last dot
}

Grunt dynamic mapping configuration to output one file

Is it possible using the dynamic mapping configuration to output one minimized file instead of one per src file?
cssmin: {
target: {
files: [{
expand: true,
cwd: 'release/css',
src: ['*.css', '!*.min.css'],
dest: 'css/finalfile.css',
ext: '.min.css'
}]
}
}
This configuration creates folder named css/finalfile.css and generates one output file per one src file.
Any help appreciated.
You can use standard file config to do that.
cssmin: {
target: {
files: {
'output.css': ['app/**/*.css']
}
}
}
Above will minify and concatenate all the CSS files from app directory into output.css

Copy files with grunt skip source folder

There is source folder and publish folder in the project. I want to copy all files and folders from source to publish.
Related code from Gruntfiles.js:
grunt.initConfig({
copy: {
main: {
files: [
{ src: ['source/**/*'], dest: 'publish/'},
]
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.registerTask('default', ['copy']);
However it copies source folder itself and puts in publish folder.
Tried a lot of variations from grunt-copy documentation and cannot find solution.
Try this configuration:
grunt.initConfig({
copy: {
main: {
cwd: 'source',
src: ['**/*'],
dest: 'publish/',
expand: true
}
}
});
If you want to only copy some parts of SRC and build the others on the normal flow (SASS, CONCAT, MINIFY plugins), you may choose to:
copy: {
main: {
files: [
{expand: true, cwd: '../src/', src: ['images/*'], dest: '../public/images'},
...
]
}
}
The key point above is the CWD which allows you to copy folders as is instead of copying the "src" inside "public".

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.

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