How to copy compiled jade files to a destination folder using grunt - node.js

For a single page app that I'm working on, I have the following structure:
dist
css
js
lib
partials
index.html
src
css
js
lib
views
partials
index.jade
Directory dist will be used by the express server to serve the project. I have trivial grunt tasks (using grunt-contrib-clean, grunt-contrib-copy) for cleaning dist and copying src/css, src/js, src/lib to dist.
The problem lies with src/views. This directory contains jade files which need to be compiled to html files. After compilation I want them in dist (index.html in the dist root, partials as subdir).
At the moment I am using the grunt-contrib-jade task to compile and copy the jade files. I want to copy them to dist, since I don't want to add the compiled html files to source control. But now this is not really workable, since you have to specify every jade file (now there are only a few, but that will grow):
jade: {
compile: {
options: {
pretty: true
},
files: {
// TODO make one line
'dist/index.html': ['src/views/index.jade'],
'dist/partials/banner.html': ['src/views/partials/banner.jade'],
'dist/partials/dashboard.html': ['src/views/partials/dashboard.jade'],
'dist/partials/navbar.html': ['src/views/partials/navbar.jade'],
'dist/partials/transfer.html': ['src/views/partials/transfer.jade']
}
}
},
Is there any way to use the grunt-contrib-jade task (or another one) with a directory filter? Like this:
jade: {
compile: {
options: {
pretty: true
},
dir: {
'dist': ['src/views']
}
}
}

Little clarification from Grunt wiki - expand mapping:
grunt.file.expandMapping(patterns, dest [, options])
Note that while this method may be used to programmatically generate a files array for a multi task, the declarative syntax for doing this described in the "Building the files object dynamically" section of the Configuring tasks guide is preferred.
Assuming the above, configuration will look like this:
files: [ {
expand: true,
src: "**/*.jade",
dest: "dist/",
cwd: "src/views",
ext: '.html'
} ];
Same result with declarative configuration.

I ended up upgrading to grunt 0.4 (which causes some other problems, but that I'll be able to handle).
With grunt version 0.4 it is possible to use grunt.file.expandMapping:
jade: {
compile: {
options: {
pretty: true
},
files: grunt.file.expandMapping(['**/*.jade'], 'dist/', {
cwd: 'src/views',
rename: function(destBase, destPath) {
return destBase + destPath.replace(/\.jade$/, '.html');
}
})
}
},

If you want to change only the extension of the files from .jade to .html, another option would be using the flatten and ext parameters like so:
jade: {
compile: {
options: {
data: { debug: false, title: 'My awesome application' }
},
files: grunt.file.expandMapping(['**/*.jade'], '<%= yeoman.dist %>/views', {
cwd: '<%= yeoman.app %>/views',
flatten: true,
ext: '.html'
})
}
}
Or even better (as explained here):
jade: {
compile: {
options: {
data: { debug: false, title: 'My awesome application' },
pretty: true
},
files: [
{
expand: true,
cwd: '<%= yeoman.app %>/views',
src: ['**/*.jade'],
dest: '<%= yeoman.dist %>/views',
ext: '.html'
}
]}
}
Thanks.

Related

Grunt - Compile Multiple Jade Files using the Pug plugin

I have a Laravel directory structure and I have my Jade templates in the /resources/assets/jade/ folder.
Inside this folder will have multiple sub-directories which I will need to copy their exact structure to the /public/app/ directory where my app will be served from..
I have also got Typescript files being compiled into the same directory structure so its very important that the directory layout is copied as I have set it up.. I cant seem to do this successfully using the Grunt Pug plugin.. any help greatly appreciated, heres what I have so far:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
pug: {
compile: {
options: {
client: false,
pretty: true,
data: {
debug: false
}
},
files: [{
'public/app/index.html': ['resources/assets/jade/index.jade']
},
{
src: "resources/assets/jade/*.jade",
dest: "public/app",
expand: true,
ext: ".html"
} ]
}
},
});
grunt.loadNpmTasks('grunt-contrib-pug');
grunt.registerTask('default', ['pug'] );
};
Looks like the old grunt-contrib-jade syntax works with PUG although I didnt see it documented anywhere so for dexterity heres what works perfectly:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
pug: {
compile: {
options: {
client: false,
pretty: true
},
files: [ {
cwd: "resources/assets/jade",
src: "**/*.jade",
dest: "public/app",
expand: true,
ext: ".html"
} ]
}
},
});
grunt.loadNpmTasks('grunt-contrib-pug');
grunt.registerTask('default', ['pug'] );
};

Issue configuring grunt to run babel

I have a Gruntfile configured to, among other things, transpile an Express app to ES5 using Babel.
This is the configuration I have:
babel: {
es6: {
files: [
{
expand: true,
src: ['server/**/*.{js,json}'],
dest: 'output/',
ext: '.js'
}
]
}
},
This works pretty well. Most of my files are transpiled. The one issue that I run into is that the way my app is structured, the files aren't necessarily ending with just the .js extension. For example, I have in my transaction folder:
index.js
transaction.model.js
transaction.controller.js
transaction.model.spec.js
Therefore, in a hail mary I added the following to my configuration, to no avail.
babel: {
es6: {
files: [
{
expand: true,
src: ['server/**/*.{controller,model,transaction,js,json}'],
dest: 'output/',
ext: '.js'
}
]
}
},
How can I transpile these files with these 'custom' extensions?
Try doing this :
babel: {
es6: {
files: [
{
expand: true,
src: ['server/**/*.js'],
dest: 'output/',
ext: '.js'
}
]
}
}
or if for some reason it does not work try this
babel: {
es6: {
files: [
{
expand: true,
src: ['server/**/*.controller.js'], // just add the ext plus the .js
dest: 'output/',
ext: '.js'
}
]
}
}

Grunt: How to build the files object dynamically

I must be missing something very simple here. I'm trying to write a function task that deals with files. The Grunt API docs mention that you can [Build the files object dynamically], but for some reason I can't get this to work. A simplified version of my Gruntfile.js file looks like this:
module.exports = function(grunt) {
grunt.initConfig({
proj: {
build: {
files: [{
expand: true,
cwd: 'src',
src: ['**/*.js'],
dest: 'dist'
}]
}
}
});
grunt.registerTask('proj', function(){
var files = grunt.config('proj.build.files');
console.log(files);
});
};
I expect the log to show a list of file mappings from the src directory to the dist directory. What actually gets logged is the object proj.build.files from the config, like this:
Running "proj:build" task
[ { expand: true, cwd: 'src', src: [ '**/*.js' ], dest: 'dist' } ]
Done, without errors.
The API docs only talk about this type of configuration in terms of other tasks. I tried looking through the uglify task to see how the file mappings are retrieved, but I couldn't figure it out.
Here is the workaround I found to dynamically build filesets for Grunt tasks:
uglify: {
app: {
files: [{
src: '{<%= _prefixSrc(pkg.target, pkg.resources.js) %>}', // Note the brackets!
dest: '<%= pkg.target %>min/<%= pkg.name %>.min.js'
}]
}
},
_prefixSrc: function(prefix, files) {
return files.map(function(file){
return prefix + file;
});
},
See also this issue/feature request on GitHub and feel free to comment it if you find it useful: https://github.com/gruntjs/grunt/issues/1307
You can use rename function to change file name is files object like below...
build: {
files: [{
expand: true,
cwd: 'src',
src: ['**/*.js'],
dest: 'dist',
rename: function(dest, src) {
/*
rename logic
you will have access to src and dest name and can return desirect name from this function.
*/
return src+123;
}
}]
}

How to configure Grunt serve/livereload to combine mustache templates

I'm using Yeoman template to develop a static web site. grunt serve nicely works with the auto reload plugin.
For repeating elements I started to use {{mustache}} partials and it works like a blast. Now I want the auto reload to assemble my page, so I can look at the resulting page when editing one of the mustache files (either a main file or a partial).
I found a grunt task for it, but stitching it together eludes me. My config looks like this:
grunt.initConfig({
sass: {
dev: {
src: ['src/sass/*.sass'],
dest: 'dest/css/index.css',
},
},
watch: {
sass: {
// We watch and compile sass files as normal but don't live reload here
files: ['src/sass/*.sass'],
tasks: ['sass']
},
mustache: {
files: '**/*.mustache',
tasks: ['mustache_render'],
options: {
interrupt: true
},
},
livereload: {
options: { livereload: true },
files: ['dest/**/*']
}
},
mustache_render: {
options: {
{data: 'common-data.json'}
},
your_target: {
files: [
{expand: true,
template: '**/*.mustache',
dest: 'dest/'}
]
}
}
});
I must be missing something since the html files are not updated when I save the file.
You can add the livereload option directly to your mustache target options.
grunt.initConfig({
watch: {
mustache: {
files: '**/*.mustache',
tasks: ['mustache_render'],
options: {
interrupt: true,
livereload: true
},
}
},
mustache_render: {
options: {
{data: 'common-data.json'}
},
main: {
files: [
{expand: true,
template: '**/*.mustache',
dest: 'dest/'}
]
}
}
});
Also, if you're using grunt-contrib-connect to serve your files, don't forget to add the livereload option to it:
connect: {
http: {
options: {
hostname: "*",
port: process.env.PORT || 80,
livereload: true
}
}
}

Grunt compress : How could I only include runtime node module dependencies?

My application is MEAN stack style. I would like to generate a package including all Nodejs and AngularJs files, so I could just unzip the package and run in other environments.
I use grunt-contrib-compress to compress and generate a zip file. Everything works well, but there are many development node modules are included, such as grunt*. All I need is the runtime node modules which are defined in the package.json. It will dramatically reduce the package size.
I could include the node modules one by one, but is there a good way only include runtime modules while packaging?
OK, I found a solution, which load the package.json and map the runtime dependencies into target folders.
compress: {
main: {
options: {
archive: 'myapp.zip'
},
files: [
{src: ['dist/**','app/**','config/**','server.js'],dest:'.'},
{src: Object.keys(require('./package.json').dependencies).map(function(module){
return "node_modules/" +module+"/**"
}),dest:'.'},
]
}
}
I had exactly the same question today, and after asking and coming up with a very similar solution, I have found your question. Here is my, similar but slightly different approach:
function getDependencies(pkg) {
return Object.keys(pkg.dependencies).map(function(val) { return val + '/**'; });
}
module.exports = function(grunt) {
var pkg = grunt.file.readJSON('package.json');
var config = {
pkg: pkg,
clean: ["public/"],
compress: {
validate: {
options: {
archive: 'public/Lambda.zip'
},
files: [
{ expand: true, cwd: 'src/', src: ['**'], dest: '/' },
{ expand: true, cwd: 'node_modules/', src: getDependencies(pkg), dest: '/node_modules' }
]
}
}
};
grunt.initConfig(config);
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.registerTask('build', ['clean', 'compress']);
}

Resources