Permalink
Browse files

feat(app): add support for --typescript option

Uses grunt-tsd to retrieve an initial set of typescript definitions.
Adds templates for typescript versions of angular items.

Based upon commit 'refs/pull/539/head' of github.com:yeoman/generator-angular
1 parent 8a9a8af commit e579df9d5d2133300f9fe0c3686bc9efbbb5260e @awk awk committed with eddiemonge May 28, 2015
View
@@ -56,6 +56,21 @@ var Generator = module.exports = function Generator(args, options) {
this.env.options.coffee = this.options.coffee;
}
+ if (typeof this.env.options.typescript === 'undefined') {
+ this.option('typescript', {
+ desc: 'Generate TypeScript instead of JavaScript'
+ });
+
+ // attempt to detect if user is using TS or not
+ // if cml arg provided, use that; else look for the existence of ts
+ if (!this.options.typescript &&
+ this.expandFiles(path.join(this.appPath, '/scripts/**/*.ts'), {}).length > 0) {
+ this.options.typescript = true;
+ }
+
+ this.env.options.typescript = this.options.typescript;
+ }
+
this.hookFor('angular:common', {
args: args
});
@@ -303,10 +318,14 @@ Generator.prototype.createIndexHtml = function createIndexHtml() {
Generator.prototype.packageFiles = function packageFiles() {
this.coffee = this.env.options.coffee;
+ this.typescript = this.env.options.typescript;
this.template('root/_bower.json', 'bower.json');
this.template('root/_bowerrc', '.bowerrc');
this.template('root/_package.json', 'package.json');
this.template('root/_Gruntfile.js', 'Gruntfile.js');
+ if (this.typescript) {
+ this.template('root/_tsd.json', 'tsd.json');
+ }
this.template('root/README.md', 'README.md');
};
View
@@ -12,6 +12,9 @@ util.inherits(Generator, ScriptBase);
Generator.prototype.createAppFile = function createAppFile() {
this.angularModules = this.env.options.angularDeps;
+ this.ngCookies = this.env.options.ngCookies;
+ this.ngResource = this.env.options.ngResource;
+ this.ngSanitize = this.env.options.ngSanitize;
this.ngRoute = this.env.options.ngRoute;
this.appTemplate('app', 'scripts/app');
};
View
@@ -188,8 +188,8 @@ 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.
-### CoffeeScript
-For generators that output scripts, the `--coffee` option will output CoffeeScript instead of JavaScript.
+### CoffeeScript and TypeScript
+For generators that output scripts, the `--coffee` option will output CoffeeScript instead of JavaScript, and `--typescript` will output TypeScript instead of JavaScript.
For example:
```bash
@@ -202,9 +202,42 @@ angular.module('myMod')
.controller 'UserCtrl', ($scope) ->
```
-A project can mix CoffeScript and JavaScript files.
+For example:
+```bash
+yo angular:controller user --typescript
+```
+
+Produces `app/scripts/controller/user.ts`:
+```typescript
+/// <reference path="../app.ts" />
+
+'use strict';
+
+module demoApp {
+ export interface IUserScope extends ng.IScope {
+ awesomeThings: any[];
+ }
+
+ export class UserCtrl {
+
+ constructor (private $scope:IUserScope) {
+ $scope.awesomeThings = [
+ 'HTML5 Boilerplate',
+ 'AngularJS',
+ 'Karma'
+ ];
+ }
+ }
+}
+
+angular.module('demoApp')
+ .controller('UserCtrl', demoApp.UserCtrl);
+```
+
+
+A project can mix TypeScript, CoffeScript, and JavaScript files.
-To output JavaScript files, even if CoffeeScript files exist (the default is to output CoffeeScript files if the generator finds any in the project), use `--coffee=false`.
+To output JavaScript files, even if CoffeeScript (or TypeScript) files exist (the default is to output CoffeeScript files if the generator finds any in the project), use `--coffee=false` and/or `--typescript=false`.
### Minification Safe
View
@@ -14,10 +14,12 @@ var Generator = module.exports = function Generator() {
required: false
});
+ var coffee = this.env.options.coffee;
+ var typescript = this.env.options.typescript;
var bower = require(path.join(process.cwd(), 'bower.json'));
var match = require('fs').readFileSync(path.join(
this.env.options.appPath,
- 'scripts/app.' + (this.env.options.coffee ? 'coffee' : 'js')
+ 'scripts/app.' + (coffee ? 'coffee' : typescript ? 'ts': 'js')
), 'utf-8').match(/\.when/);
if (
@@ -52,10 +54,11 @@ Generator.prototype.rewriteAppJs = function () {
this.uri = this.options.uri;
}
+ var typescript = this.env.options.typescript;
var config = {
file: path.join(
this.env.options.appPath,
- 'scripts/app.' + (coffee ? 'coffee' : 'js')
+ 'scripts/app.' + (coffee ? 'coffee' : typescript ? 'ts': 'js')
),
needle: '.otherwise',
splicable: [
View
@@ -34,6 +34,20 @@ var Generator = module.exports = function Generator() {
this.env.options.testPath = this.env.options.testPath || bowerJson.testPath || 'test/spec';
+ this.env.options.typescript = this.options.typescript;
+ if (typeof this.env.options.typescript === 'undefined') {
+ this.option('typescript');
+
+ // attempt to detect if user is using TS or not
+ // if cml arg provided, use that; else look for the existence of ts
+ if (!this.options.typescript &&
+ this.expandFiles(path.join(this.env.options.appPath, '/scripts/**/*.ts'), {}).length > 0) {
+ this.options.typescript = true;
+ }
+
+ this.env.options.typescript = this.options.typescript;
+ }
+
this.env.options.coffee = this.options.coffee;
if (typeof this.env.options.coffee === 'undefined') {
this.option('coffee');
@@ -56,6 +70,11 @@ var Generator = module.exports = function Generator() {
this.scriptSuffix = '.coffee';
}
+ if (this.env.options.typescript) {
+ sourceRoot = '/templates/typescript';
+ this.scriptSuffix = '.ts';
+ }
+
this.sourceRoot(path.join(__dirname, sourceRoot));
};
@@ -1 +1,2 @@
-*.coffee
+*.coffee
+*.ts
@@ -44,6 +44,14 @@ module.exports = function (grunt) {
coffeeTest: {
files: ['test/spec/{,*/}*.{coffee,litcoffee,coffee.md}'],
tasks: ['newer:coffee:test', 'karma']
+ },<% } else if (typescript) { %>
+ typescript: {
+ files: ['<%%= yeoman.app %>/scripts/{,*/}*.ts'],
+ tasks: ['typescript:base']
+ },
+ typescriptTest: {
+ files: ['test/spec/{,*/}*.ts'],
+ tasks: ['typescript:test', 'karma']
},<% } else { %>
js: {
files: ['<%%= yeoman.app %>/scripts/{,*/}*.js'],
@@ -73,7 +81,7 @@ module.exports = function (grunt) {
},
files: [
'<%%= yeoman.app %>/{,*/}*.html',
- '.tmp/styles/{,*/}*.css',<% if (coffee) { %>
+ '.tmp/styles/{,*/}*.css',<% if (coffee || typescript) { %>
'.tmp/scripts/{,*/}*.js',<% } %>
'<%%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
]
@@ -139,10 +147,10 @@ module.exports = function (grunt) {
},
all: {
src: [
- 'Gruntfile.js'<% if (!coffee) { %>,
+ 'Gruntfile.js'<% if (!coffee && !typescript) { %>,
'<%%= yeoman.app %>/scripts/{,*/}*.js'<% } %>
]
- }<% if (!coffee) { %>,
+ }<% if (!coffee && !typescript) { %>,
test: {
options: {
jshintrc: 'test/.jshintrc'
@@ -248,7 +256,41 @@ module.exports = function (grunt) {
src: ['<%%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
ignorePath: /(\.\.\/){1,2}bower_components\//
}<% } %>
- },<% if (coffee) { %>
+ }, <% if (typescript) { %>
+ // Compiles TypeScript to JavaScript
+ typescript: {
+ base: {
+ src: ['<%%= yeoman.app %>/scripts/{,*/}*.ts'],
+ dest: '.tmp/scripts',
+ options: {
+ module: 'amd', //or commonjs
+ target: 'es5', //or es3
+ 'base_path': '<%%= yeoman.app %>/scripts', //quoting base_path to get around jshint warning.
+ sourcemap: true,
+ declaration: true
+ }
+ },
+ test: {
+ src: ['test/spec/{,*/}*.ts', 'test/e2e/{,*/}*.ts'],
+ dest: '.tmp/spec',
+ options: {
+ module: 'amd', //or commonjs
+ target: 'es5', //or es3
+ sourcemap: true,
+ declaration: true
+ }
+ }
+ },
+ tsd: {
+ refresh: {
+ options: {
+ // execute a command
+ command: 'reinstall',
+ config: 'tsd.json'
+ }
+ }
+ },
+ <% } %><% if (coffee) { %>
// Compiles CoffeeScript to JavaScript
coffee: {
@@ -496,17 +538,20 @@ module.exports = function (grunt) {
// Run some tasks in parallel to speed up the build process
concurrent: {
server: [<% if (coffee) { %>
- 'coffee:dist',<% } %><% if (compass) { %>
+ 'coffee:dist',<% } %><% if (typescript) { %>
+ 'typescript:base',<% } %><% if (compass) { %>
'compass:server'<% } else { %>
'copy:styles'<% } %>
],
test: [<% if (coffee) { %>
- 'coffee',<% } %><% if (compass) { %>
+ 'coffee',<% } %><% if (typescript) { %>
+ 'typescript',<% } %><% if (compass) { %>
'compass'<% } else { %>
'copy:styles'<% } %>
],
dist: [<% if (coffee) { %>
- 'coffee',<% } %><% if (compass) { %>
+ 'coffee',<% } %><% if (typescript) { %>
+ 'typescript',<% } %><% if (compass) { %>
'compass:dist',<% } else { %>
'copy:styles',<% } %>
'imagemin',
@@ -534,7 +579,8 @@ module.exports = function (grunt) {
grunt.task.run([
'clean:server',
- 'wiredep',
+ 'wiredep',<% if (typescript) { %>
+ 'tsd:refresh',<% } %>
'concurrent:server',
'postcss:server',
'connect:livereload',
@@ -549,7 +595,8 @@ module.exports = function (grunt) {
grunt.registerTask('test', [
'clean:server',
- 'wiredep',
+ 'wiredep',<% if (typescript) { %>
+ 'tsd:refresh',<% } %>
'concurrent:test',
'postcss',
'connect:test',
@@ -558,7 +605,8 @@ module.exports = function (grunt) {
grunt.registerTask('build', [
'clean:dist',
- 'wiredep',
+ 'wiredep',<% if (typescript) { %>
+ 'tsd:refresh',<% } %>
'useminPrepare',
'concurrent:dist',
'postcss',
@@ -24,7 +24,9 @@
"grunt-newer": "^1.1.0",
"grunt-ng-annotate": "^0.9.2",
"grunt-postcss": "^0.5.5",
- "grunt-svgmin": "^2.0.0",
+ "grunt-svgmin": "^2.0.0",<% if (typescript) { %>
+ "grunt-tsd": "^0.1.0",
+ "grunt-typescript": "^0.6.2",<% } %>
"grunt-usemin": "^3.0.0",
"grunt-wiredep": "^2.0.0",
"jit-grunt": "^0.9.1",
@@ -0,0 +1,33 @@
+{
+ "version": "v4",
+ "repo": "borisyankov/DefinitelyTyped",
+ "ref": "master",
+ "path": "typings",
+ "bundle": "typings/tsd.d.ts",
+ "installed": {
+ "jquery/jquery.d.ts": {
+ "commit": "f3244190e20af6901e865f4cc58127d19216baa1"
+ },
+ "angularjs/angular.d.ts": {
+ "commit": "f3244190e20af6901e865f4cc58127d19216baa1"
+ },
+ "angularjs/angular-resource.d.ts": {
+ "commit": "aadd63ecae3feb76ea2d4be80511e266b5c2c4a7"
+ },
+ "angularjs/angular-route.d.ts": {
+ "commit": "f23cd55e319a0f67362ca0dbc4cf3e2ec1339f4e"
+ },
+ "angularjs/angular-mocks.d.ts": {
+ "commit": "f23cd55e319a0f67362ca0dbc4cf3e2ec1339f4e"
+ },
+ "angularjs/angular-cookies.d.ts": {
+ "commit": "f23cd55e319a0f67362ca0dbc4cf3e2ec1339f4e"
+ },
+ "angularjs/angular-sanitize.d.ts": {
+ "commit": "f23cd55e319a0f67362ca0dbc4cf3e2ec1339f4e"
+ },
+ "jasmine/jasmine.d.ts": {
+ "commit": "f23cd55e319a0f67362ca0dbc4cf3e2ec1339f4e"
+ }
+ }
+}
@@ -0,0 +1,19 @@
+/// <reference path="../../typings/angularjs/angular.d.ts" /><% if (ngCookies) { %>
+/// <reference path="../../typings/angularjs/angular-cookies.d.ts" /><% } %><% if (ngResource) { %>
+/// <reference path="../../typings/angularjs/angular-resource.d.ts" /><% } %><% if (ngSanitize) { %>
+/// <reference path="../../typings/angularjs/angular-sanitize.d.ts" /><% } %><% if (ngRoute) { %>
+/// <reference path="../../typings/angularjs/angular-route.d.ts" /><% } %>
+
+'use strict';
+
+angular.module('<%= scriptAppName %>', [<%= angularModules %>])<% if (ngRoute) { %>
+ .config(($routeProvider:ng.route.IRouteProvider) => {
+ $routeProvider
+ .when('/', {
+ templateUrl: 'views/main.html',
+ controller: 'MainCtrl'
+ })
+ .otherwise({
+ redirectTo: '/'
+ });
+ })<% } %>;
@@ -0,0 +1,23 @@
+/// <reference path="../app.ts" />
+
+'use strict';
+
+module <%= scriptAppName %> {
+ export interface I<%= classedName %>Scope extends ng.IScope {
+ awesomeThings: any[];
+ }
+
+ export class <%= classedName %>Ctrl {
+
+ constructor (private $scope: I<%= classedName %>Scope) {
+ $scope.awesomeThings = [
+ 'HTML5 Boilerplate',
+ 'AngularJS',
+ 'Karma'
+ ];
+ }
+ }
+}
+
+angular.module('<%= scriptAppName %>')
+ .controller('<%= classedName %>Ctrl', <%= scriptAppName %>.<%= classedName %>Ctrl);
Oops, something went wrong.

0 comments on commit e579df9

Please sign in to comment.