Reputation: 10244
I'm trying to configure my Gruntfile to compile all of my Jade files to individual HTML files. For example, if I have the following source folder:
source
└── templates
├── first.jade
├── second.jade
└── third.jade
Then I would expect grunt jade
to output:
build
└── templates
├── first.html
├── second.html
└── third.html
Here's my Gruntfile using grunt-contrib-jade
:
module.exports = function(grunt) {
grunt.initConfig({
jade: {
compile: {
options: {
client: false,
pretty: true
},
files: [ {
src: "*.jade",
dest: "build/templates/",
ext: "html",
cwd: "source/templates/"
} ]
}
},
});
grunt.loadNpmTasks("grunt-contrib-jade");
};
However, when I run the jade command I get the following errors:
Running "jade:compile" (jade) task
>> Source file "first.jade" not found.
>> Source file "second.jade" not found.
>> Source file "third.jade" not found.
What am I doing wrong?
Upvotes: 22
Views: 15542
Reputation: 616
To complete the above answer
jade: {
compile: {
options: {
client: false,
pretty: true
},
files: [ {
cwd: "app/views",
src: "**/*.jade",
dest: "build/templates",
expand: true,
ext: ".html"
} ]
}
}
So if your source is structured as so:
app
└── views
└── main.jade
└── user
└── signup.jade
└── preferences.jade
grunt jade
will create the following structure
build
└── templates
└── main.html
└── user
└── signup.html
└── preferences.html
EDIT:
The grunt-contrib-jade
is deprecated. You should rather use grunt-contrib-pug
. It is exactly the same, but they had to rename jade to pug!
Upvotes: 50
Reputation: 41
Just in case anyone needs it. Nothing above worked. This is how it finally worked for me.
I'm using grunt.loadNpmTasks('grunt-contrib-pug');
I dunno if contrib-jade as since been deprecated but this solution works for me. I need the first file object to handle just the index.jade and the 2nd to deal with the templates. Now if I don't split it up and just point to the project directory the jade compiler gets lost inside my npm package folder so this runs much faster.
pug: {
compile: {
options: {
client: false,
pretty: true,
data: {
debug: false
}
},
files: [
{
'dist/index.html': ['index.jade']
},
{
src: "templates/*.jade",
dest: "dist",
expand: true,
ext: ".html"
} ]
}
}
Upvotes: 3
Reputation: 1032
I know this is an old post but I kept coming back here whilst trying to solve a similar problem. I wanted to output multiple html files from a single jade template file using a for-loop. So needed greater control of the 'files' object.
The two problems I came across and eventually solved, was setting the output filename (a javascript object literal KEY) and making sure inline javascript functions are run immediately so that the loop variables are available.
Here is my full source code with comments. I hope this is of use to anyone else stumbling across this post.
Gruntfile.js:
module.exports = function(grunt) {
// Create basic grunt config (e.g. watch files)
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
grunt: { files: ['Gruntfile.js'] },
jade: {
files: 'src/*.jade',
tasks: ['jade']
}
}
});
// Load json to populate jade templates and build loop
var json = grunt.file.readJSON('test.json');
for(var i = 0; i < json.length; i++) {
var obj = json[i];
// For each json item create a new jade task with a custom 'target' name.
// Because a custom target is provided don't nest options/data/file parameters
// in another target like 'compile' as grunt wont't be able to find them
// Make sure that functions are called using immediate invocation or the variables will be lost
// http://stackoverflow.com/questions/939386/immediate-function-invocation-syntax
grunt.config(['jade', obj.filename], {
options: {
// Pass data to the jade template
data: (function(dest, src) {
return {
myJadeName: obj.myname,
from: src,
to: dest
};
}()) // <-- n.b. using() for immediate invocation
},
// Add files using custom function
files: (function() {
var files = {};
files['build/' + obj.filename + '.html'] = 'src/index.jade';
return files;
}()) // <-- n.b. using () for immediate invocation
});
}
grunt.loadNpmTasks('grunt-contrib-jade');
grunt.loadNpmTasks('grunt-contrib-watch');
// Register all the jade tasks using top level 'jade' task
// You can also run subtasks using the target name e.g. 'jade:cats'
grunt.registerTask('default', ['jade', 'watch']);
};
src/index.jade:
doctype html
html(lang="en")
head
title= pageTitle
script(type='text/javascript').
if (foo) {
bar(1 + 5)
}
body
h1 #{myJadeName} - node template engine
#container.col
p.
Jade is a terse and simple
templating language with a
strong focus on performance
and powerful features.
test.json:
[{
"id" : "1",
"filename" : "cats",
"tid" : "2016-01-01 23:35",
"myname": "Cat Lady"
},
{
"id" : "2",
"filename" : "dogs",
"tid" : "2016-01-01 23:45",
"myname": "Dog Man"
}]
After running 'grunt' the output should be:
build/cats.html
build/dogs.html
Upvotes: 1