Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

feat(build): add Jade support #420

Open
wants to merge 3 commits into from

9 participants

@gonzaloruizdevilla

Added new --jade option to generator that will create jade templates (http://jade-lang.com/)

@eddiemonge
Owner

so many changes. @gonzaloruizdevilla can you rebase and merge conflicts please (again i think)(sorry)?

@gonzaloruizdevilla

Done. It was small conflict in app/index.js. In the PR, Bootstrap js dependencies are stored in a list before appending them to the html or jade index file. In the original file, they are passed directly as parameter to the function appendScripts.

@eddiemonge
Owner

can you fix the failing test?

@gonzaloruizdevilla

Please note that the build is failing because my fork project is "generator-angularexpress" and is the express suffix that is responsible for the failure. Mocha tests in my local machine and run in a folder named "generator-angular" pass without problem.

From TravisCi log:

generator-angular@0.5.1 test /home/travis/build/gonzaloruizdevilla/generator-angularexpress
mocha

That folder is responsible of the failing test.

@gonzaloruizdevilla

I have added another commit to the PR. I have modified de .travis.yml file to ensure that the working folder has the same name as the generator. This way the generator can be correctly tested, independently of the repo name.

app/index.js
((39 lines not shown))
};
Generator.prototype.createIndexHtml = function createIndexHtml() {
- this.write(path.join(this.appPath, 'index.html'), this.indexFile);
+ if(this.env.options.jade) {
+ this.write(path.join(this.appPath, 'index.jade'), this.indexFile);
@passy Owner
passy added a note

Could you just alter the file name? Something like var indexFile = 'index.' + this.env.options.jade ? 'jade' : 'html';

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
app/index.js
@@ -269,3 +315,74 @@ Generator.prototype.packageFiles = function () {
this.template('../../templates/common/_package.json', 'package.json');
this.template('../../templates/common/Gruntfile.js', 'Gruntfile.js');
};
+
+Generator.prototype.addMainView = function addMainView() {
+ if(this.env.options.jade) {
+ this.copy('../../templates/common/main.jade', 'app/views/main.jade');
@passy Owner
passy added a note

Same here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
app/index.js
((4 lines not shown))
+
+Generator.prototype.addMainView = function addMainView() {
+ if(this.env.options.jade) {
+ this.copy('../../templates/common/main.jade', 'app/views/main.jade');
+ } else {
+ this.copy('../../templates/common/main.html', 'app/views/main.html');
+ }
+};
+
+function appendScriptsJade(jade, optimizedPath, sourceFileList, attrs) {
+ return appendFilesToJade(jade, 'js', optimizedPath, sourceFileList, attrs);
+};
+
+function spacePrefix(jade, block){
+ var prefix;
+ jade.split("\n").forEach( function (line) { if( line.indexOf(block)> -1 ) {
@passy Owner
passy added a note

Single quotes please.

@passy Owner
passy added a note

And jshint white option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@eddiemonge eddiemonge commented on the diff
app/index.js
@@ -45,6 +45,19 @@ var Generator = module.exports = function Generator(args, options) {
this.env.options.coffee = this.options.coffee;
}
+ if (typeof this.env.options.jade === 'undefined') {

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

@eddiemonge Owner

if that works then something else is broken, such as the auto create jade files if one already exists.

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.

@eddiemonge Owner

yo angular:view new --jade should create a new new.jade file
yo 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 files

if 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

It is working that way. I have tried this:

$ yo angular
....creating proyect
$ yo angular:view myview1
   create app/views/myview1.html
$ yo angular:view myview2 --jade
   create app/views/myview2.jade
$ yo angular:view myview3
   create app/views/myview3.jade
$ yo angular:view myview4 --jade=false
   create app/views/myview4.html
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@gonzaloruizdevilla

I've added @passy recommendations and also jshinted the files.
I've added a new commit 48eaaa2 to the PR that fixes a small issue with the tests of AngularJs services.

@eddiemonge
Owner

can you pull the travis fix out and submit that as a new pr and then merge/rebase please?

@eddiemonge eddiemonge commented on the diff
app/index.js
((7 lines not shown))
};
+function spacePrefix(jade, block){
@eddiemonge Owner

I feel like all these functions should go in the utils file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@eddiemonge eddiemonge commented on the diff
app/index.js
@@ -205,16 +281,28 @@ Generator.prototype.bootstrapFiles = function bootstrapFiles() {
return 'styles/' + file.replace('.scss', '.css');
}),
searchPath: '.tmp'
- });
+ };
+
+ if (this.env.options.jade) {
@eddiemonge Owner
var appendFiles = this.env.options.jade ? appendFilesToJade : this.appendFiles;
appendFiles(filesToAppend)

Would something like that work better so you dont have this block repeated so many times?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@eddiemonge eddiemonge commented on the diff
app/index.js
((11 lines not shown))
}
};
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({
@eddiemonge Owner

config block should be a variable and passed into the functions so its not duplicated (at least it looks duplicated to me)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@eddiemonge eddiemonge commented on the diff
templates/common/Gruntfile.js
@@ -30,6 +30,10 @@ module.exports = function (grunt) {
files: ['<%%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
tasks: ['compass:server', 'autoprefixer']
},<% } %>
+ jade: {
@eddiemonge Owner

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

I thought about it. In my first try, there was a question when running yo angular and the answer was used for the conditionals inside the gruntfile template. However, now it's using an argument for jade templates, so this would mean that the first time this argument is used the Gruntfile must be modified directly, somehow duplicating the conditional logic inside the template.

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@eddiemonge eddiemonge commented on the diff
templates/common/_package.json
@@ -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",
@eddiemonge Owner

why grunt-jade instead of grunt-contrib-jade?

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@eddiemonge eddiemonge commented on the diff
templates/common/index.jade
((11 lines not shown))
+ title
+ meta(name="description", content="")
+ meta(name="viewport", content="width=device-width")
+ // Place favicon.ico and apple-touch-icon.png in the root directory
+ //- build:head
+ body(ng-app="<%= _.camelize(appname) %>App")
+ //[if lt IE 7]>
+ <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
+ <![endif]
+ //[if lt IE 9]>
+ <script src="bower_components/es5-shim/es5-shim.js"></script>
+ <script src="bower_components/json3/lib/json3.min.js"></script>
+ <![endif]
+
+ // Add your site or application content here
+ div(class="container", ng-view)
@eddiemonge Owner

.container(ng-view)

haha, good catch! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@eddiemonge eddiemonge commented on the diff
templates/common/index.jade
((1 lines not shown))
+!!!
+// [if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]
+// [if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]
+// [if IE 8]> <html class="no-js lt-ie9"> <![endif]
+// [if gt IE 8]><!
+html.no-js
+ //<![endif]
+ head
+ meta(charset="utf-8")
+ meta(http-equiv="X-UA-Compatible", content="IE=edge,chrome=1")
+ title
+ meta(name="description", content="")
+ meta(name="viewport", content="width=device-width")
+ // Place favicon.ico and apple-touch-icon.png in the root directory
+ //- build:head
+ body(ng-app="<%= _.camelize(appname) %>App")
@eddiemonge Owner

this needs to be updated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@eddiemonge
Owner

why were the view files moved?

@gonzaloruizdevilla

I concluded that files inside templates/common/root are copied as they are, without modifications, and the files that are manipulated like index.html are stored inside templates/common. Maybe this was a wrong assumption?

@eddiemonge
Owner

no i feel like you are right. what i did in my test branch (https://github.com/eddiemonge/generator-angular/tree/jade_support/templates) was create a new folder to hold these so they didnt clutter up other folders

@szimek

Does it put all generated HTML files in yeoman.app directory? Wouldn't .tmp be better?

@gonzaloruizdevilla

@szimek I agree with your suggestion, I'm going look at it.

@szimek

@gonzaloruizdevilla If you do change destination path to .tmp, remember to add '.tmp/**/*.html' to livereload.files config as well.

@eddiemonge
Owner

@szimek livereload should still look at the app/*/.jade but the tasks would be jade. it shouldnt watch the tmp folder for html files

@szimek

@eddiemonge I'm a bit lost :) Will livereload work correctly with jade files having the following config:

watch: {
  jade: {
    files: ['<%= yeoman.app %>/views/**/*.jade'],
    tasks: ['jade:server']
  },
  livereload: {
    options: {
      livereload: '<%= connect.options.livereload %>'
    },
    files: ['lots of other stuff', '<%= yeoman.app %>/views/**/*.jade']
  }
}

Will jade:server task always be executed before livereload reloads the page?

@eddiemonge
Owner

it will if you remove the jade files from livereload. the watch command triggers it automatically. the livereload target is a bit misleading as its really a bucket to catch everything else

@szimek

So if livereload target is set, it automatically turns livereload for all other targets and additionally for any files listed in its files option?

@eddiemonge
Owner

Sorry you need to set livereload to true in that target

@szimek

Got it. Thanks!

@nullivex

Hey guys, awesome work here. Is there any chance this will make it into a future release?

@dagumak

Great work guys! I'm excited to use this!

@eddiemonge
Owner

Im scared of this one but Im still meaning to get to it

@zakdances

This may be a far-future goal, but might it be a good idea to simplify the build process a bit so that stuff like this, and other small custom tasks, can be inserted by users? It'd be neat if there was an easy way to customize angular generator with my own initialization questions like "Would you like to use Jade?".

@eddiemonge eddiemonge referenced this pull request
Open

Generator Roadmap #553

2 of 15 tasks complete
@eddiemonge
Owner

@zakdances those are currently hidden behind a flag.

I do want to land this PR or one like it but got to get to other things first. This is a bug one keeping me from using this generator in my own work so it is a high personal priority but not as high on the project priority. That seems odd, I should change that.

@sindresorhus

ping @eddiemonge

also needs to fix merge conflict.

@eddiemonge eddiemonge added this to the 0.10.0: The Future milestone
@eddiemonge eddiemonge added the on-hold label
@nils-wisiol

Is this still a thing? I'd love to see this in my work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
4 .travis.yml
@@ -2,3 +2,7 @@ language: node_js
node_js:
- '0.10'
- '0.8'
+before_install:
+ - currentfolder=${PWD##*/}
+ - if [ "$currentfolder" != 'generator-angular' ]; then cd .. && eval "mv $currentfolder generator-angular" && cd generator-angular; fi
+
View
146 app/index.js
@@ -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') {

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

@eddiemonge Owner

if that works then something else is broken, such as the auto create jade files if one already exists.

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.

@eddiemonge Owner

yo angular:view new --jade should create a new new.jade file
yo 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 files

if 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

It is working that way. I have tried this:

$ yo angular
....creating proyect
$ yo angular:view myview1
   create app/views/myview1.html
$ yo angular:view myview2 --jade
   create app/views/myview2.jade
$ yo angular:view myview3
   create app/views/myview3.jade
$ yo angular:view myview4 --jade=false
   create app/views/myview4.html
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ 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){
@eddiemonge Owner

I feel like all these functions should go in the utils file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ 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,7 +273,7 @@ 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',
@@ -205,16 +281,28 @@ Generator.prototype.bootstrapFiles = function bootstrapFiles() {
return 'styles/' + file.replace('.scss', '.css');
}),
searchPath: '.tmp'
- });
+ };
+
+ if (this.env.options.jade) {
@eddiemonge Owner
var appendFiles = this.env.options.jade ? appendFilesToJade : this.appendFiles;
appendFiles(filesToAppend)

Would something like that work better so you dont have this block repeated so many times?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ 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,23 +340,37 @@ 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({
@eddiemonge Owner

config block should be a variable and passed into the functions so its not duplicated (at least it looks duplicated to me)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ 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 () {
@@ -269,3 +378,8 @@ Generator.prototype.packageFiles = function () {
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);
+};
View
12 readme.md
@@ -172,6 +172,18 @@ angular.module('myMod').config(function ($provide) {
## Options
In general, these options can be applied to any generator, though they only affect generators that produce scripts.
+### Jade
+For generators that output html, the `--jade` option will output Jade instead of html files.
+
+For example:
+```bash
+yo angular:view user --jade
+
+Produces `app/scripts/views/user.jade`:
+```jade
+p This is the user view.
+```
+
### CoffeeScript
For generators that output scripts, the `--coffee` option will output CoffeeScript instead of JavaScript.
View
44 script-base.js
@@ -46,6 +46,20 @@ var Generator = module.exports = function Generator() {
this.env.options.coffee = this.options.coffee;
}
+ this.env.options.jade = this.options.jade;
+ if (typeof this.env.options.jade === 'undefined') {
+ this.option('jade');
+
+ // 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.env.options.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');
this.env.options.minsafe = this.options.minsafe;
@@ -89,9 +103,25 @@ Generator.prototype.htmlTemplate = function (src, dest) {
]);
};
-Generator.prototype.addScriptToIndex = function (script) {
+function addScriptToIndexJade(script, env) {
try {
- var appPath = this.env.options.appPath;
+ var appPath = env.options.appPath;
+ var fullPath = path.join(appPath, 'index.jade');
+ angularUtils.rewriteFile({
+ file: fullPath,
+ needle: '// endbuild',
+ splicable: [
+ 'script(src="scripts/' + script + '.js")'
+ ]
+ });
+ } catch (e) {
+ console.log('\nUnable to find '.yellow + fullPath + '. Reference to '.yellow + script + '.js ' + 'not added.\n'.yellow);
+ }
+}
+
+function addScriptToIndexHtml(script, env) {
+ try {
+ var appPath = env.options.appPath;
var fullPath = path.join(appPath, 'index.html');
angularUtils.rewriteFile({
file: fullPath,
@@ -103,6 +133,14 @@ Generator.prototype.addScriptToIndex = function (script) {
} catch (e) {
console.log('\nUnable to find '.yellow + fullPath + '. Reference to '.yellow + script + '.js ' + 'not added.\n'.yellow);
}
+}
+
+Generator.prototype.addScriptToIndex = function (script) {
+ if (this.env.options.jade) {
+ addScriptToIndexJade(script, this.env);
+ } else {
+ addScriptToIndexHtml(script, this.env);
+ }
};
Generator.prototype.generateSourceAndTest = function (appTemplate, testTemplate, targetDirectory, skipAdd) {
@@ -111,4 +149,4 @@ Generator.prototype.generateSourceAndTest = function (appTemplate, testTemplate,
if (!skipAdd) {
this.addScriptToIndex(path.join(targetDirectory, this.name));
}
-};
+};
View
2  templates/coffeescript-min/spec/service.coffee
@@ -3,7 +3,7 @@
describe 'Service: <%= classedName %>', () ->
# load the service's module
- beforeEach module '<%= scriptAppName %>App'
+ beforeEach module '<%= scriptAppName %>'
# instantiate service
<%= classedName %> = {}
View
2  templates/coffeescript/spec/service.coffee
@@ -3,7 +3,7 @@
describe 'Service: <%= classedName %>', () ->
# load the service's module
- beforeEach module '<%= scriptAppName %>App'
+ beforeEach module '<%= scriptAppName %>'
# instantiate service
<%= classedName %> = {}
View
29 templates/common/Gruntfile.js
@@ -30,6 +30,10 @@ module.exports = function (grunt) {
files: ['<%%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
tasks: ['compass:server', 'autoprefixer']
},<% } %>
+ jade: {
@eddiemonge Owner

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

I thought about it. In my first try, there was a question when running yo angular and the answer was used for the conditionals inside the gruntfile template. However, now it's using an argument for jade templates, so this would mean that the first time this argument is used the Gruntfile must be modified directly, somehow duplicating the conditional logic inside the template.

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ 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',
View
1  templates/common/_package.json
@@ -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",
@eddiemonge Owner

why grunt-jade instead of grunt-contrib-jade?

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
"jshint-stylish": "~0.1.3"
},
"engines": {
View
41 templates/common/index.jade
@@ -0,0 +1,41 @@
+!!!
+// [if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]
+// [if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]
+// [if IE 8]> <html class="no-js lt-ie9"> <![endif]
+// [if gt IE 8]><!
+html.no-js
+ //<![endif]
+ head
+ meta(charset="utf-8")
+ meta(http-equiv="X-UA-Compatible", content="IE=edge,chrome=1")
+ title
+ meta(name="description", content="")
+ meta(name="viewport", content="width=device-width")
+ // Place favicon.ico and apple-touch-icon.png in the root directory
+ //- build:head
+ body(ng-app="<%= _.camelize(appname) %>App")
@eddiemonge Owner

this needs to be updated

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ //[if lt IE 7]>
+ <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
+ <![endif]
+ //[if lt IE 9]>
+ <script src="bower_components/es5-shim/es5-shim.js"></script>
+ <script src="bower_components/json3/lib/json3.min.js"></script>
+ <![endif]
+
+ // Add your site or application content here
+ div(class="container", ng-view)
@eddiemonge Owner

.container(ng-view)

haha, good catch! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+ // Google Analytics: change UA-XXXXX-X to be your site's ID.
+ script.
+ var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
+ (function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
+ g.src='//www.google-analytics.com/ga.js';
+ s.parentNode.insertBefore(g,s)}(document,'script'));
+ ga('create', 'UA-XXXXX-X');
+ ga('send', 'pageview');
+
+
+ script(src="bower_components/jquery/jquery.js")
+ script(src="bower_components/angular/angular.js")
+
+ //- build:body
View
0  templates/common/root/app/views/main.html → templates/common/main.html
File renamed without changes
View
8 templates/common/main.jade
@@ -0,0 +1,8 @@
+.hero-unit
+ h1 'Allo, 'Allo!
+ p You now have
+ ul
+ li Jade
+ li(ng-repeat="thing in awesomeThings") {{thing}}
+ p installed.
+ h3 Enjoy coding! - Yeoman
View
1  templates/common/view.jade
@@ -0,0 +1 @@
+p This is the <%= name %> view.
View
2  templates/javascript-min/spec/service.js
@@ -3,7 +3,7 @@
describe('Service: <%= classedName %>', function () {
// load the service's module
- beforeEach(module('<%= scriptAppName %>App'));
+ beforeEach(module('<%= scriptAppName %>'));
// instantiate service
var <%= classedName %>;
View
2  templates/javascript/spec/service.js
@@ -3,7 +3,7 @@
describe('Service: <%= classedName %>', function () {
// load the service's module
- beforeEach(module('<%= scriptAppName %>App'));
+ beforeEach(module('<%= scriptAppName %>'));
// instantiate service
var <%= classedName %>;
View
52 test/test-file-creation.js
@@ -101,6 +101,35 @@ describe('Angular generator', function () {
});
});
+ it('creates jade files', function (done) {
+ var expected = ['app/.htaccess',
+ 'app/404.html',
+ 'app/favicon.ico',
+ 'app/robots.txt',
+ 'app/styles/main.css',
+ 'app/views/main.jade',
+ ['.bowerrc', /"directory": "app\/bower_components"/],
+ 'Gruntfile.js',
+ 'package.json',
+ ['bower.json', /"name":\s+"temp"/],
+ 'app/scripts/app.js',
+ 'app/index.jade',
+ 'app/scripts/controllers/main.js',
+ 'test/spec/controllers/main.js'
+ ];
+ helpers.mockPrompt(angular, {
+ bootstrap: true,
+ compassBoostrap: true,
+ modules: []
+ });
+
+ angular.env.options.jade = true;
+ angular.run([], function () {
+ helpers.assertFiles(expected);
+ done();
+ });
+ });
+
/**
* Generic test function that can be used to cover the scenarios where a generator is creating both a source file
* and a test file. The function will run the respective generator, and then check for the existence of the two
@@ -168,7 +197,7 @@ describe('Angular generator', function () {
describe('Service', function () {
function serviceTest (generatorType, nameFn, done) {
generatorTest(generatorType, 'service', 'services', nameFn, _.classify, '', done);
- };
+ }
it('should generate a new constant', function (done) {
serviceTest('constant', _.camelize, done);
@@ -212,6 +241,27 @@ describe('Angular generator', function () {
});
});
+ it('should generate a new jade view', function (done) {
+ var angularView;
+ var deps = ['../../view'];
+ angularView = helpers.createGenerator('angular:view', deps, ['foo']);
+
+ helpers.mockPrompt(angular, {
+ bootstrap: true,
+ compassBoostrap: true,
+ modules: []
+ });
+ angularView.env.options.jade = true;
+ angular.run([], function (){
+ angularView.run([], function () {
+ helpers.assertFiles([
+ ['app/views/foo.jade']
+ ]);
+ done();
+ });
+ });
+ });
+
it('should generate a new view in subdirectories', function (done) {
var angularView;
var deps = ['../../view'];
View
9 view/index.js
@@ -1,11 +1,11 @@
'use strict';
var path = require('path');
var util = require('util');
-var yeoman = require('yeoman-generator');
+var ScriptBase = require('../script-base.js');
var Generator = module.exports = function Generator() {
- yeoman.generators.NamedBase.apply(this, arguments);
+ ScriptBase.apply(this, arguments);
this.sourceRoot(path.join(__dirname, '../templates'));
if (typeof this.env.options.appPath === 'undefined') {
@@ -16,8 +16,9 @@ var Generator = module.exports = function Generator() {
}
};
-util.inherits(Generator, yeoman.generators.NamedBase);
+util.inherits(Generator, ScriptBase);
Generator.prototype.createViewFiles = function createViewFiles() {
- this.template('common/view.html', path.join(this.env.options.appPath, 'views', this.name + '.html'));
+ var extension = this.env.options.jade ? '.jade' : '.html';
+ this.template('common/view' + extension, path.join(this.env.options.appPath, 'views', this.name + extension));
};
Something went wrong with that request. Please try again.