Skip to content
This repository was archived by the owner on Mar 26, 2018. It is now read-only.

Adding typescript support to generator-angular #1098

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
Expand Down Expand Up @@ -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');
};

Expand Down
3 changes: 3 additions & 0 deletions main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
};
41 changes: 37 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down
7 changes: 5 additions & 2 deletions route/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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: [
Expand Down
19 changes: 19 additions & 0 deletions script-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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));
};

Expand Down
3 changes: 2 additions & 1 deletion templates/common/app/.buildignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.coffee
*.coffee
*.ts
68 changes: 58 additions & 10 deletions templates/common/root/_Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,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'],
Expand Down Expand Up @@ -69,7 +77,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}'
]
Expand Down Expand Up @@ -135,10 +143,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'
Expand Down Expand Up @@ -225,7 +233,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: {
Expand Down Expand Up @@ -474,17 +516,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',
Expand Down Expand Up @@ -512,7 +557,8 @@ module.exports = function (grunt) {

grunt.task.run([
'clean:server',
'wiredep',
'wiredep',<% if (typescript) { %>
'tsd:refresh',<% } %>
'concurrent:server',
'autoprefixer:server',
'connect:livereload',
Expand All @@ -527,7 +573,8 @@ module.exports = function (grunt) {

grunt.registerTask('test', [
'clean:server',
'wiredep',
'wiredep',<% if (typescript) { %>
'tsd:refresh',<% } %>
'concurrent:test',
'autoprefixer',
'connect:test',
Expand All @@ -536,7 +583,8 @@ module.exports = function (grunt) {

grunt.registerTask('build', [
'clean:dist',
'wiredep',
'wiredep',<% if (typescript) { %>
'tsd:refresh',<% } %>
'useminPrepare',
'concurrent:dist',
'autoprefixer',
Expand Down
4 changes: 3 additions & 1 deletion templates/common/root/_package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
"grunt-google-cdn": "^0.4.3",
"grunt-newer": "^1.1.0",
"grunt-ng-annotate": "^0.9.2",
"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",
"jshint-stylish": "^1.0.0",
Expand Down
33 changes: 33 additions & 0 deletions templates/common/root/_tsd.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
}
19 changes: 19 additions & 0 deletions templates/typescript/app.ts
Original file line number Diff line number Diff line change
@@ -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: '/'
});
})<% } %>;
23 changes: 23 additions & 0 deletions templates/typescript/controller.ts
Original file line number Diff line number Diff line change
@@ -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);
Loading