Skip to content

Commit 24a13bf

Browse files
committed
feat(gen): added support for jade templates
When jade flag is set, '--jade', project generates with jade templates. Additionally, any new routes and views generated will use Jade templates if jade is found in your views folder. closes #19
1 parent c6ae81c commit 24a13bf

File tree

21 files changed

+413
-37
lines changed

21 files changed

+413
-37
lines changed

Diff for: app/index.js

+126-11
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,21 @@ var Generator = module.exports = function Generator(args, options) {
5353
args.push('--minsafe');
5454
}
5555

56+
if (typeof this.env.options.jade === 'undefined') {
57+
this.option('jade', {
58+
desc: 'Generate views using Jade templates'
59+
});
60+
61+
// attempt to detect if user is using jade or not
62+
// if cml arg provided, use that; else look for the existence of cs
63+
if (!this.options.coffee &&
64+
this.expandFiles(path.join(this.appPath, '/views/**/*.jade'), {}).length > 0) {
65+
this.options.jade = true;
66+
}
67+
68+
this.env.options.jade = this.options.jade;
69+
}
70+
5671
this.hookFor('angular-fullstack:common', {
5772
args: args
5873
});
@@ -201,7 +216,13 @@ Generator.prototype.askForMongo = function askForMongo() {
201216
};
202217

203218
Generator.prototype.readIndex = function readIndex() {
204-
this.indexFile = this.engine(this.read('../../templates/common/index.html'), this);
219+
this.jade = this.env.options.jade;
220+
221+
if(this.jade) {
222+
this.indexFile = this.engine(this.read('../../templates/views/jade/index.jade'), this);
223+
} else {
224+
this.indexFile = this.engine(this.read('../../templates/views/html/index.html'), this);
225+
}
205226
};
206227

207228
// Waiting a more flexible solution for #138
@@ -224,15 +245,21 @@ Generator.prototype.bootstrapFiles = function bootstrapFiles() {
224245
this.copy(source + file, 'app/styles/' + file);
225246
}.bind(this));
226247

227-
this.indexFile = this.appendFiles({
248+
var appendOptions = {
228249
html: this.indexFile,
229250
fileType: 'css',
230251
optimizedPath: 'styles/main.css',
231252
sourceFileList: files.map(function (file) {
232253
return 'styles/' + file.replace('.scss', '.css');
233254
}),
234255
searchPath: ['.tmp', 'app']
235-
});
256+
};
257+
258+
if (this.jade) {
259+
this.indexFile = appendFilesToJade(appendOptions);
260+
} else {
261+
this.indexFile = this.appendFiles(appendOptions);
262+
}
236263
};
237264

238265
Generator.prototype.bootstrapJS = function bootstrapJS() {
@@ -241,7 +268,7 @@ Generator.prototype.bootstrapJS = function bootstrapJS() {
241268
}
242269

243270
// Wire Twitter Bootstrap plugins
244-
this.indexFile = this.appendFiles({
271+
var appendOptions = {
245272
html: this.indexFile,
246273
fileType: 'js',
247274
optimizedPath: 'scripts/plugins.js',
@@ -260,7 +287,13 @@ Generator.prototype.bootstrapJS = function bootstrapJS() {
260287
'bower_components/sass-bootstrap/js/popover.js'
261288
],
262289
searchPath: 'app'
263-
});
290+
};
291+
292+
if (this.jade) {
293+
this.indexFile = appendFilesToJade(appendOptions);
294+
} else {
295+
this.indexFile = this.appendFiles(appendOptions);
296+
}
264297
};
265298

266299
Generator.prototype.extraModules = function extraModules() {
@@ -282,28 +315,110 @@ Generator.prototype.extraModules = function extraModules() {
282315
}
283316

284317
if (modules.length) {
285-
this.indexFile = this.appendFiles({
318+
var appendOptions = {
286319
html: this.indexFile,
287320
fileType: 'js',
288321
optimizedPath: 'scripts/modules.js',
289322
sourceFileList: modules,
290323
searchPath: 'app'
291-
});
324+
};
325+
326+
if (this.jade) {
327+
this.indexFile = appendFilesToJade(appendOptions);
328+
} else {
329+
this.indexFile = this.appendFiles(appendOptions);
330+
}
292331
}
293332
};
294333

334+
function generateJadeBlock(blockType, optimizedPath, filesBlock, searchPath, prefix) {
335+
var blockStart, blockEnd;
336+
var blockSearchPath = '';
337+
338+
if (searchPath !== undefined) {
339+
if (util.isArray(searchPath)) {
340+
searchPath = '{' + searchPath.join(',') + '}';
341+
}
342+
blockSearchPath = '(' + searchPath + ')';
343+
}
344+
345+
blockStart = '\n' + prefix + '<!-- build:' + blockType + blockSearchPath + ' ' + optimizedPath + ' -->\n';
346+
blockEnd = prefix + '<!-- endbuild -->\n' + prefix;
347+
return blockStart + filesBlock + blockEnd;
348+
}
349+
350+
function appendJade(jade, tag, blocks){
351+
var mark = "//- build:" + tag,
352+
position = jade.indexOf(mark);
353+
return [jade.slice(0, position), blocks, jade.slice(position)].join('');
354+
}
355+
356+
function appendFilesToJade(jadeOrOptions, fileType, optimizedPath, sourceFileList, attrs, searchPath) {
357+
var blocks, updatedContent,
358+
jade = jadeOrOptions,
359+
prefix = ' ',
360+
files = '';
361+
362+
if (typeof jadeOrOptions === 'object') {
363+
jade = jadeOrOptions.html;
364+
fileType = jadeOrOptions.fileType;
365+
optimizedPath = jadeOrOptions.optimizedPath;
366+
sourceFileList = jadeOrOptions.sourceFileList;
367+
attrs = jadeOrOptions.attrs;
368+
searchPath = jadeOrOptions.searchPath;
369+
}
370+
371+
if (fileType === 'js') {
372+
sourceFileList.forEach(function (el) {
373+
files += prefix + '<script ' + (attrs||'') + 'src="' + el + '"></script>\n';
374+
});
375+
blocks = generateJadeBlock('js', optimizedPath, files, searchPath, prefix);
376+
updatedContent = appendJade(jade, 'body', blocks);
377+
} else if (fileType === 'css') {
378+
sourceFileList.forEach(function (el) {
379+
files += prefix + '<link ' + (attrs||'') + 'rel="stylesheet" href="' + el + '">\n';
380+
});
381+
blocks = generateJadeBlock('css', optimizedPath, files, searchPath, prefix);
382+
updatedContent = appendJade(jade, 'head', blocks);
383+
}
384+
return updatedContent;
385+
}
386+
295387
Generator.prototype.appJs = function appJs() {
296-
this.indexFile = this.appendFiles({
388+
var appendOptions = {
297389
html: this.indexFile,
298390
fileType: 'js',
299391
optimizedPath: 'scripts/scripts.js',
300392
sourceFileList: ['scripts/app.js', 'scripts/controllers/main.js'],
301393
searchPath: ['.tmp', 'app']
302-
});
394+
};
395+
if (this.jade) {
396+
this.indexFile = appendFilesToJade(appendOptions);
397+
} else {
398+
this.indexFile = this.appendFiles(appendOptions);
399+
}
400+
};
401+
402+
Generator.prototype.createIndex = function createIndex() {
403+
if (this.jade) {
404+
this.write(path.join(this.appPath, 'views', 'index.jade'), this.indexFile);
405+
} else {
406+
this.write(path.join(this.appPath, 'views', 'index.html'), this.indexFile);
407+
}
303408
};
304409

305-
Generator.prototype.createIndexHtml = function createIndexHtml() {
306-
this.write(path.join(this.appPath, 'views', 'index.html'), this.indexFile);
410+
Generator.prototype.addJadeViews = function addHtmlJade() {
411+
if(this.jade) {
412+
this.copy('../../templates/views/jade/partials/main.jade', 'app/views/partials/main.jade');
413+
this.copy('../../templates/views/jade/404.jade', 'app/views/404.jade');
414+
}
415+
};
416+
417+
Generator.prototype.addHtmlViews = function addHtmlViews() {
418+
if(!this.jade) {
419+
this.copy('../../templates/views/html/partials/main.html', 'app/views/partials/main.html');
420+
this.copy('../../templates/views/html/404.html', 'app/views/404.html');
421+
}
307422
};
308423

309424
Generator.prototype.packageFiles = function () {

Diff for: deploy/index.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ Generator.prototype.herokuCreate = function herokuCreate() {
6666
if (err) {
6767
this.log.error(err);
6868
} else {
69-
console.log('stdout: ' + stdout);
70-
console.log(chalk.green('You\'re all set! Now push to heroku with\n\t' + chalk.bold('git push heroku master') +
71-
'\nfrom your new heroku folder'));
72-
console.log(chalk.yellow('After app modification run\n\t' + chalk.bold('grunt heroku') +
73-
'\nthen commit and push the heroku folder'));
69+
console.log('stdout: ' + stdout);
70+
console.log(chalk.green('You\'re all set! Now push to heroku with\n\t' + chalk.bold('git push heroku master') +
71+
'\nfrom your new heroku folder'));
72+
console.log(chalk.yellow('After app modification run\n\t' + chalk.bold('grunt heroku') +
73+
'\nthen commit and push the heroku folder'));
7474
}
7575
done();
7676
}.bind(this));

Diff for: readme.md

+15-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ Featuring:
77
* Express server integrated with grunt tasks
88
* Livereload of client and server files
99
* Easy deployment workflow.
10-
* **NEW** Optional mongoDB integration
10+
* Optional mongoDB integration
11+
* **NEW** Support for jade templates
1112

1213
Based on [generator-angular](https://github.com/yeoman/generator-angular)
1314

@@ -33,17 +34,17 @@ yo angular-fullstack [app-name]
3334

3435
Launch your express server in development mode.
3536
```
36-
grunt serv
37+
grunt serve
3738
```
3839

3940
Launch your express server in production mode, uses the minified/optimized production app folder.
4041
```
41-
grunt serv:dist
42+
grunt serve:dist
4243
```
4344

4445
### Livereload
4546

46-
`grunt server` will watch client files in `app/`, and server files inside `lib/`, restarting the Express server when a change is detected.
47+
`grunt serve` will watch client files in `app/`, and server files inside `lib/`, restarting the Express server when a change is detected.
4748

4849
### Deployment
4950

@@ -222,6 +223,16 @@ angular.module('myMod').config(function ($provide) {
222223
## Options
223224
In general, these options can be applied to any generator, though they only affect generators that produce scripts.
224225

226+
### Jade
227+
For generators that output views, the `--jade` option will output Jade instead of HTML.
228+
229+
For example:
230+
```bash
231+
yo angular-fullstack --jade
232+
```
233+
234+
Changes the rendering engine from EJS to Jade, and generates your views as jade files instead of HTML.
235+
225236
### CoffeeScript
226237
For generators that output scripts, the `--coffee` option will output CoffeeScript instead of JavaScript.
227238

Diff for: route/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Generator.prototype.rewriteAppJs = function () {
2222
),
2323
needle: '.otherwise',
2424
splicable: [
25-
" templateUrl: 'views/partials/" + this.name + ".html'" + (coffee ? "" : "," ),
25+
" templateUrl: 'partials/" + this.name + "'" + (coffee ? "" : "," ),
2626
" controller: '" + this.classedName + "Ctrl'"
2727
]
2828
};

Diff for: script-base.js

+22-2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,26 @@ var Generator = module.exports = function Generator() {
6363
sourceRoot += '-min';
6464
}
6565

66+
if (typeof this.env.options.jade === 'undefined') {
67+
this.option('jade', {
68+
desc: 'Generate views using Jade templates'
69+
});
70+
71+
// attempt to detect if user is using jade or not
72+
// if cml arg provided, use that; else look for the existence of cs
73+
if (!this.options.jade &&
74+
this.expandFiles(path.join(this.env.options.appPath, '/views/**/*.jade'), {}).length > 0) {
75+
this.options.jade = true;
76+
}
77+
78+
this.env.options.jade = this.options.jade;
79+
}
80+
81+
this.viewSuffix = '.html';
82+
if (this.env.options.jade) {
83+
this.viewSuffix = '.jade';
84+
}
85+
6686
this.sourceRoot(path.join(__dirname, sourceRoot));
6787
};
6888

@@ -92,7 +112,7 @@ Generator.prototype.htmlTemplate = function (src, dest) {
92112
Generator.prototype.addScriptToIndex = function (script) {
93113
try {
94114
var appPath = this.env.options.appPath;
95-
var fullPath = path.join(appPath, 'views', 'index.html');
115+
var fullPath = path.join(appPath, 'views', 'index' + this.viewSuffix);
96116
angularUtils.rewriteFile({
97117
file: fullPath,
98118
needle: '<!-- endbuild -->',
@@ -111,4 +131,4 @@ Generator.prototype.generateSourceAndTest = function (appTemplate, testTemplate,
111131
if (!skipAdd) {
112132
this.addScriptToIndex(path.join(targetDirectory, this.name));
113133
}
114-
};
134+
};

Diff for: templates/coffeescript-min/app.coffee

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ angular.module('<%= scriptAppName %>', [<%= angularModules %>])
44
.config ['$routeProvider', '$locationProvider', ($routeProvider, $locationProvider) ->
55
$routeProvider
66
.when '/',
7-
templateUrl: 'views/main.html'
7+
templateUrl: 'views/main'
88
controller: 'MainCtrl'
99
.otherwise
1010
redirectTo: '/'

Diff for: templates/coffeescript/app.coffee

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ angular.module('<%= scriptAppName %>', [<%= angularModules %>])
44
.config ($routeProvider, $locationProvider) ->
55
$routeProvider
66
.when '/',
7-
templateUrl: 'views/main.html'
7+
templateUrl: 'views/main'
88
controller: 'MainCtrl'
99
.otherwise
1010
redirectTo: '/'

Diff for: templates/common/Gruntfile.js

+12-4
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ module.exports = function (grunt) {
6969
},<% } %>
7070
livereload: {
7171
files: [
72-
'<%%= yeoman.app %>/<%%= yeoman.views %>/{,*//*}*.html',
72+
'<%%= yeoman.app %>/<%%= yeoman.views %>/{,*//*}*.{html,jade}',
7373
'{.tmp,<%%= yeoman.app %>}/styles/{,*//*}*.css',
7474
'{.tmp,<%%= yeoman.app %>}/scripts/{,*//*}*.js',
7575
'<%%= yeoman.app %>/images/{,*//*}*.{png,jpg,jpeg,gif,webp,svg}',
@@ -230,15 +230,17 @@ module.exports = function (grunt) {
230230
// concat, minify and revision files. Creates configurations in memory so
231231
// additional tasks can operate on them
232232
useminPrepare: {
233-
html: '<%%= yeoman.app %>/<%%= yeoman.views %>/index.html',
233+
html: ['<%%= yeoman.app %>/<%%= yeoman.views %>/index.html',
234+
'<%%= yeoman.app %>/<%%= yeoman.views %>/index.jade'],
234235
options: {
235236
dest: '<%%= yeoman.dist %>'
236237
}
237238
},
238239

239240
// Performs rewrites based on rev and the useminPrepare configuration
240241
usemin: {
241-
html: ['<%%= yeoman.views %>/{,*/}*.html'],
242+
html: ['<%%= yeoman.views %>/{,*/}*.html',
243+
'<%%= yeoman.views %>/{,*/}*.jade'],
242244
css: ['<%%= yeoman.dist %>/styles/{,*/}*.css'],
243245
options: {
244246
assetsDirs: ['<%%= yeoman.dist %>']
@@ -322,6 +324,12 @@ module.exports = function (grunt) {
322324
'images/{,*/}*.{webp}',
323325
'fonts/*'
324326
]
327+
}, {
328+
expand: true,
329+
dot: true,
330+
cwd: '<%%= yeoman.app %>/<%%= yeoman.views %>',
331+
dest: '<%%= yeoman.views %>',
332+
src: '**/*.jade',
325333
}, {
326334
expand: true,
327335
cwd: '.tmp/images',
@@ -338,7 +346,7 @@ module.exports = function (grunt) {
338346
dest: 'heroku',
339347
src: [
340348
'<%%= yeoman.dist %>/**',
341-
'<%= yeoman.views %>/**'
349+
'<%%= yeoman.views %>/**'
342350
]
343351
}, {
344352
expand: true,

0 commit comments

Comments
 (0)