-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
feat(build): add Jade support #420
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,6 +45,21 @@ var Generator = module.exports = function Generator(args, options) { | |
this.env.options.coffee = this.options.coffee; | ||
} | ||
|
||
if (typeof this.env.options.jade === 'undefined') { | ||
this.option('jade', { | ||
desc: 'Generate Jade templates instead of HTML' | ||
}); | ||
|
||
// attempt to detect if user is using jade or not | ||
// if cml arg provided, use that; else look for the existence of cs | ||
if (!this.options.jade && | ||
this.expandFiles(path.join(this.appPath, '/**/*.jade'), {}).length > 0) { | ||
this.options.jade = true; | ||
} | ||
|
||
this.env.options.jade = this.options.jade; | ||
} | ||
|
||
if (typeof this.env.options.minsafe === 'undefined') { | ||
this.option('minsafe', { | ||
desc: 'Generate AngularJS minification safe code' | ||
|
@@ -174,11 +189,72 @@ Generator.prototype.askForModules = function askForModules() { | |
}; | ||
|
||
Generator.prototype.readIndex = function readIndex() { | ||
this.indexFile = this.engine(this.read('../../templates/common/index.html'), this); | ||
var extension = this.env.options.jade ? "jade" : "html"; | ||
this.indexFile = this.engine(this.read('../../templates/common/index.' + extension), this); | ||
}; | ||
|
||
function spacePrefix(jade, block){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like all these functions should go in the utils file |
||
var prefix; | ||
jade.split('\n').forEach( function (line) { if( line.indexOf(block)> -1 ) { | ||
prefix = line.split("/")[0]; | ||
}}); | ||
return prefix; | ||
} | ||
|
||
function generateJadeBlock(blockType, optimizedPath, filesBlock, searchPath, prefix) { | ||
var blockStart, blockEnd; | ||
var blockSearchPath = ''; | ||
|
||
if (searchPath !== undefined) { | ||
if (util.isArray(searchPath)) { | ||
searchPath = '{' + searchPath.join(',') + '}'; | ||
} | ||
blockSearchPath = '(' + searchPath + ')'; | ||
} | ||
|
||
blockStart = '\n' + prefix + '// build:' + blockType + blockSearchPath + ' ' + optimizedPath + ' \n'; | ||
blockEnd = prefix + '// endbuild\n' + prefix; | ||
return blockStart + filesBlock + blockEnd; | ||
} | ||
|
||
function appendJade(jade, tag, blocks){ | ||
var mark = "//- build:" + tag, | ||
position = jade.indexOf(mark); | ||
return [jade.slice(0, position), blocks, jade.slice(position)].join(''); | ||
} | ||
|
||
function appendFilesToJade(jadeOrOptions, fileType, optimizedPath, sourceFileList, attrs, searchPath) { | ||
var blocks, updatedContent, prefix, jade, files = ''; | ||
jade = jadeOrOptions; | ||
if (typeof jadeOrOptions === 'object') { | ||
jade = jadeOrOptions.html; | ||
fileType = jadeOrOptions.fileType; | ||
optimizedPath = jadeOrOptions.optimizedPath; | ||
sourceFileList = jadeOrOptions.sourceFileList; | ||
attrs = jadeOrOptions.attrs; | ||
searchPath = jadeOrOptions.searchPath; | ||
} | ||
if (fileType === 'js') { | ||
prefix = spacePrefix(jade, "build:body"); | ||
sourceFileList.forEach(function (el) { | ||
files += prefix + 'script(' + (attrs||'') + 'src="' + el + '")\n'; | ||
}); | ||
blocks = generateJadeBlock('js', optimizedPath, files, searchPath, prefix); | ||
updatedContent = appendJade(jade, 'body', blocks); | ||
} else if (fileType === 'css') { | ||
prefix = spacePrefix(jade, "build:head"); | ||
sourceFileList.forEach(function (el) { | ||
files += prefix + 'link(' + (attrs||'') + 'rel="stylesheet", href="' + el + '")\n'; | ||
}); | ||
blocks = generateJadeBlock('css', optimizedPath, files, searchPath, prefix); | ||
updatedContent = appendJade(jade, 'head', blocks); | ||
} | ||
return updatedContent; | ||
} | ||
|
||
// Waiting a more flexible solution for #138 | ||
Generator.prototype.bootstrapFiles = function bootstrapFiles() { | ||
var filesToAppend; | ||
var sass = this.compassBootstrap; | ||
var files = []; | ||
var source = 'styles/' + ( sass ? 's' : '' ) + 'css/'; | ||
|
@@ -197,24 +273,36 @@ Generator.prototype.bootstrapFiles = function bootstrapFiles() { | |
this.copy(source + file, 'app/styles/' + file); | ||
}.bind(this)); | ||
|
||
this.indexFile = this.appendFiles({ | ||
filesToAppend = { | ||
html: this.indexFile, | ||
fileType: 'css', | ||
optimizedPath: 'styles/main.css', | ||
sourceFileList: files.map(function (file) { | ||
return 'styles/' + file.replace('.scss', '.css'); | ||
}), | ||
searchPath: '.tmp' | ||
}); | ||
}; | ||
|
||
if (this.env.options.jade) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Would something like that work better so you dont have this block repeated so many times? |
||
this.indexFile = appendFilesToJade(filesToAppend); | ||
} else { | ||
this.indexFile = this.appendFiles(filesToAppend); | ||
} | ||
}; | ||
|
||
|
||
function appendScriptsJade(jade, optimizedPath, sourceFileList, attrs) { | ||
return appendFilesToJade(jade, 'js', optimizedPath, sourceFileList, attrs); | ||
} | ||
|
||
Generator.prototype.bootstrapJS = function bootstrapJS() { | ||
var list; | ||
if (!this.bootstrap) { | ||
return; // Skip if disabled. | ||
} | ||
|
||
// Wire Twitter Bootstrap plugins | ||
this.indexFile = this.appendScripts(this.indexFile, 'scripts/plugins.js', [ | ||
list = [ | ||
'bower_components/sass-bootstrap/js/affix.js', | ||
'bower_components/sass-bootstrap/js/alert.js', | ||
'bower_components/sass-bootstrap/js/button.js', | ||
|
@@ -226,8 +314,15 @@ Generator.prototype.bootstrapJS = function bootstrapJS() { | |
'bower_components/sass-bootstrap/js/scrollspy.js', | ||
'bower_components/sass-bootstrap/js/tab.js', | ||
'bower_components/sass-bootstrap/js/tooltip.js', | ||
'bower_components/sass-bootstrap/js/transition.js', | ||
]); | ||
'bower_components/sass-bootstrap/js/transition.js' | ||
]; | ||
|
||
if (this.env.options.jade) { | ||
this.indexFile = appendScriptsJade(this.indexFile, 'scripts/plugins.js', list); | ||
} else { | ||
this.indexFile = this.appendScripts(this.indexFile, 'scripts/plugins.js', list); | ||
} | ||
|
||
}; | ||
|
||
Generator.prototype.extraModules = function extraModules() { | ||
|
@@ -245,27 +340,46 @@ Generator.prototype.extraModules = function extraModules() { | |
} | ||
|
||
if (modules.length) { | ||
this.indexFile = this.appendScripts(this.indexFile, 'scripts/modules.js', | ||
modules); | ||
if (this.env.options.jade) { | ||
this.indexFile = appendScriptsJade(this.indexFile, 'scripts/plugins.js', modules); | ||
} else { | ||
this.indexFile = this.appendScripts(this.indexFile, 'scripts/plugins.js', modules); | ||
} | ||
} | ||
}; | ||
|
||
Generator.prototype.appJs = function appJs() { | ||
this.indexFile = this.appendFiles({ | ||
html: this.indexFile, | ||
fileType: 'js', | ||
optimizedPath: 'scripts/scripts.js', | ||
sourceFileList: ['scripts/app.js', 'scripts/controllers/main.js'], | ||
searchPath: ['.tmp', 'app'] | ||
}); | ||
if (this.env.options.jade) { | ||
this.indexFile = appendFilesToJade({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. config block should be a variable and passed into the functions so its not duplicated (at least it looks duplicated to me) |
||
html: this.indexFile, | ||
fileType: 'js', | ||
optimizedPath: 'scripts/scripts.js', | ||
sourceFileList: ['scripts/app.js'], | ||
searchPath: ['.tmp', 'app'] | ||
}); | ||
} else { | ||
this.indexFile = this.appendFiles({ | ||
html: this.indexFile, | ||
fileType: 'js', | ||
optimizedPath: 'scripts/scripts.js', | ||
sourceFileList: ['scripts/app.js', 'scripts/controllers/main.js'], | ||
searchPath: ['.tmp', 'app'] | ||
}); | ||
} | ||
}; | ||
|
||
Generator.prototype.createIndexHtml = function createIndexHtml() { | ||
this.write(path.join(this.appPath, 'index.html'), this.indexFile); | ||
var indexFile = 'index.' + (this.env.options.jade ? 'jade' : 'html'); | ||
this.write(path.join(this.appPath, indexFile), this.indexFile); | ||
}; | ||
|
||
Generator.prototype.packageFiles = function () { | ||
this.template('../../templates/common/_bower.json', 'bower.json'); | ||
this.template('../../templates/common/_package.json', 'package.json'); | ||
this.template('../../templates/common/Gruntfile.js', 'Gruntfile.js'); | ||
}; | ||
|
||
Generator.prototype.addMainView = function addMainView() { | ||
var mainFile = 'main.' + (this.env.options.jade ? 'jade' : 'html'); | ||
this.copy('../../templates/common/' + mainFile, 'app/views/' + mainFile); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,10 @@ module.exports = function (grunt) { | |
files: ['<%%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], | ||
tasks: ['compass:server', 'autoprefixer'] | ||
},<% } %> | ||
jade: { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need conditionals for all these. I know there arent really a lot currently in the file for other things but im hoping that will change soon There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought about it. In my first try, there was a question when running The same happens with coffescript. If conditionals are used for the coffescript tasks, do you have any ideas of how to modify the gruntfile in a clean way when in a later moment the user decides to use coffescript? |
||
files: ['<%%= yeoman.app %>/**/*.jade'], | ||
tasks: ['jade'] | ||
}, | ||
styles: { | ||
files: ['<%%= yeoman.app %>/styles/{,*/}*.css'], | ||
tasks: ['copy:styles', 'autoprefixer'] | ||
|
@@ -174,6 +178,28 @@ module.exports = function (grunt) { | |
} | ||
} | ||
}, | ||
jade: { | ||
index: { | ||
files: { | ||
'<%%= yeoman.app %>/': ['<%%= yeoman.app %>/index.jade'] | ||
}, | ||
options: { | ||
basePath: '<%%= yeoman.app %>/', | ||
client: false, | ||
pretty: true | ||
} | ||
}, | ||
views: { | ||
files: { | ||
'<%%= yeoman.app %>/views/': ['<%%= yeoman.app %>/views/**/*.jade'] | ||
}, | ||
options: { | ||
basePath: '<%%= yeoman.app %>/views', | ||
client: false, | ||
pretty: true | ||
} | ||
} | ||
}, | ||
useminPrepare: { | ||
html: '<%%= yeoman.app %>/index.html', | ||
options: { | ||
|
@@ -274,16 +300,19 @@ module.exports = function (grunt) { | |
}, | ||
concurrent: { | ||
server: [ | ||
'jade', | ||
'coffee:dist',<% if (compassBootstrap) { %> | ||
'compass:server',<% } %> | ||
'copy:styles' | ||
], | ||
test: [ | ||
'jade', | ||
'coffee',<% if (compassBootstrap) { %> | ||
'compass',<% } %> | ||
'copy:styles' | ||
], | ||
dist: [ | ||
'jade', | ||
'coffee',<% if (compassBootstrap) { %> | ||
'compass:dist',<% } %> | ||
'copy:styles', | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ | |
"grunt-google-cdn": "~0.2.0", | ||
"grunt-ngmin": "~0.0.2", | ||
"time-grunt": "~0.1.0", | ||
"grunt-jade": "~0.4.0", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why grunt-jade instead of grunt-contrib-jade? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've been using grunt-jade for a long time and it has worked fine. I'm going to check grunt-contrib-jade and verify that a few issues I had a long ago with grunt-jade are not present. |
||
"jshint-stylish": "~0.1.3" | ||
}, | ||
"engines": { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need to allow jade=false to work like: https://github.com/yeoman/generator-angular/blob/master/script-base.js#L35
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is working right now. I tried:
yo angular --jade
and then
yo angular:view miview
which created a jade file:
create app/views/miview.jade
and
yo angular:view miview2 --jade=false
with created an html file:
create app/views/miview2.html
Anyway, I'm going to add a description for the Jade option, so it is correctly displayed when typing
yo angular -help
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if that works then something else is broken, such as the auto create jade files if one already exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain a little bit more? When jade files exist, yo is informing that they are identical or that there is a conflict and asking how to solve it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yo angular:view new --jade
should create a new new.jade fileyo angular:view another
should create another.jade file (automatically creating the jade file since there are already jade files in the project)yo angular:view last --jade=false
should create last.html since jade false is specified, even though are already jade filesif you dont pass in the jade option then (lines)[https://github.com/gonzaloruizdevilla/generator-angularexpress/blob/72e994c9d4e63dea0f4e6a7d5d78e06724601e3f/app/index.js#L53-L54] should automatically create jade files. passing in false should also do that since this.env.options.jade is undefined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is working that way. I have tried this: