feat(router): add angular 1.x router

This commit is contained in:
Brian Ford 2015-04-29 15:46:42 -07:00
parent 78a8ba2307
commit fde026a9e4
19 changed files with 1977 additions and 4 deletions

View File

@ -36,6 +36,7 @@ env:
- MODE=saucelabs DART_CHANNEL=dev
- MODE=dart_experimental DART_CHANNEL=dev
- MODE=js DART_CHANNEL=dev
- MODE=router DART_CHANNEL=dev
- MODE=lint DART_CHANNEL=dev
matrix:

View File

@ -37,6 +37,7 @@ var util = require('./tools/build/util');
var bundler = require('./tools/build/bundle');
var replace = require('gulp-replace');
var insert = require('gulp-insert');
var buildRouter = require('./modules/angular1_router/build');
var uglify = require('gulp-uglify');
var shouldLog = require('./tools/build/logging');
var tslint = require('gulp-tslint');
@ -604,6 +605,34 @@ gulp.task('!test.unit.js/karma-run', function(done) {
runKarma('karma-js.conf.js', done);
});
gulp.task('test.unit.router', function (done) {
runSequence(
'!test.unit.router/karma-server',
function() {
watch('modules/**', [
'buildRouter.dev',
'!test.unit.router/karma-run'
]);
}
);
});
gulp.task('!test.unit.router/karma-server', function() {
karma.server.start({configFile: __dirname + '/modules/angular1_router/karma-router.conf.js'});
});
gulp.task('!test.unit.router/karma-run', function(done) {
karma.runner.run({configFile: __dirname + '/modules/angular1_router/karma-router.conf.js'}, function(exitCode) {
// ignore exitCode, we don't want to fail the build in the interactive (non-ci) mode
// karma will print all test failures
done();
});
});
gulp.task('buildRouter.dev', function () {
buildRouter();
});
gulp.task('test.unit.dart', function (done) {
runSequence(
@ -641,6 +670,12 @@ gulp.task('!test.unit.dart/karma-server', function() {
});
gulp.task('test.unit.router/ci', function (done) {
var browserConf = getBrowsersFromCLI();
karma.server.start({configFile: __dirname + '/modules/angular1_router/karma-router.conf.js',
singleRun: true, reporters: ['dots'], browsers: browserConf.browsersToRun}, done);
});
gulp.task('test.unit.js/ci', function (done) {
var browserConf = getBrowsersFromCLI();
karma.server.start({configFile: __dirname + '/karma-js.conf.js',

View File

@ -27,6 +27,7 @@ module.exports = function(config) {
exclude: [
'dist/dart/**/packages/**',
'modules/angular1_router/**'
],
karmaDartImports: {

View File

@ -31,6 +31,7 @@ module.exports = function(config) {
exclude: [
'dist/js/dev/es5/**/e2e_test/**',
'dist/angular1_router.js'
],
customLaunchers: sauceConf.customLaunchers,

123
modules/angular1_router/build.js vendored Normal file
View File

@ -0,0 +1,123 @@
var fs = require('fs');
var ts = require('typescript');
var files = [
'lifecycle_annotations_impl.ts',
'url_parser.ts',
'path_recognizer.ts',
'route_config_impl.ts',
'async_route_handler.ts',
'sync_route_handler.ts',
'route_recognizer.ts',
'instruction.ts',
'route_config_nomalizer.ts',
'route_lifecycle_reflector.ts',
'route_registry.ts',
'router.ts'
];
var PRELUDE = '(function(){\n';
var POSTLUDE = '\n}());\n';
var FACADES = fs.readFileSync(__dirname + '/lib/facades.es5', 'utf8');
var TRACEUR_RUNTIME = fs.readFileSync(__dirname + '/../../node_modules/traceur/bin/traceur-runtime.js', 'utf8');
var DIRECTIVES = fs.readFileSync(__dirname + '/src/ng_outlet.js', 'utf8');
function main() {
var dir = __dirname + '/../angular2/src/router/';
var out = '';
var sharedCode = '';
files.forEach(function (file) {
var moduleName = 'router/' + file.replace(/\.ts$/, '');
sharedCode += transform(moduleName, fs.readFileSync(dir + file, 'utf8'));
});
out += "angular.module('ngComponentRouter')";
out += angularFactory('$router', ['$q', '$location', '$$controllerIntrospector',
'$browser', '$rootScope', '$injector'], [
FACADES,
"var exports = {Injectable: function () {}};",
"var require = function () {return exports;};",
sharedCode,
"var RouteConfig = exports.RouteConfig;",
"angular.annotations = {RouteConfig: RouteConfig, CanActivate: exports.CanActivate};",
"angular.stringifyInstruction = exports.stringifyInstruction;",
"var RouteRegistry = exports.RouteRegistry;",
"var RootRouter = exports.RootRouter;",
//TODO: move this code into a templated JS file
"var registry = new RouteRegistry();",
"var location = new Location();",
"$$controllerIntrospector(function (name, constructor) {",
"if (constructor.$canActivate) {",
"constructor.annotations = constructor.annotations || [];",
"constructor.annotations.push(new angular.annotations.CanActivate(function (instruction) {",
"return $injector.invoke(constructor.$canActivate, constructor, {",
"$routeParams: instruction.component ? instruction.component.params : instruction.params",
"});",
"}));",
"}",
"if (constructor.annotations) {",
"constructor.annotations.forEach(function(annotation) {",
"if (annotation instanceof RouteConfig) {",
"annotation.configs.forEach(function (config) {",
"registry.config(constructor, config);",
"});",
"}",
"});",
"}",
"});",
"var router = new RootRouter(registry, undefined, location, new Object());",
"$rootScope.$watch(function () { return $location.path(); }, function (path) { router.navigate(path); });",
"return router;"
].join('\n'));
return PRELUDE + TRACEUR_RUNTIME + DIRECTIVES + out + POSTLUDE;
}
/*
* Given a directory name and a file's TypeScript content, return an object with the ES5 code,
* sourcemap, anf exported variable identifier name for the content.
*/
var IMPORT_RE = new RegExp("import \\{?([\\w\\n_, ]+)\\}? from '(.+)';?", 'g');
function transform(dir, contents) {
contents = contents.replace(IMPORT_RE, function (match, imports, includePath) {
//TODO: remove special-case
if (isFacadeModule(includePath) || includePath === './router_outlet') {
return '';
}
return match;
});
return ts.transpile(contents, {
target: ts.ScriptTarget.ES5,
module: ts.ModuleKind.CommonJS,
sourceRoot: dir
});
}
function angularFactory(name, deps, body) {
return ".factory('" + name + "', [" +
deps.map(function (service) {
return "'" + service + "', ";
}).join('') +
"function (" + deps.join(', ') + ") {\n" + body + "\n}])";
}
function isFacadeModule(modulePath) {
return modulePath.indexOf('facade') > -1 ||
modulePath === 'angular2/src/reflection/reflection';
}
module.exports = function () {
var dist = __dirname + '/../../dist';
if (!fs.existsSync(dist)) {
fs.mkdirSync(dist);
}
fs.writeFileSync(dist + '/angular_1_router.js', main(files));
};

View File

@ -0,0 +1,22 @@
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div ng-app="myApp" ng-controller="MyCtrl">
</div>
<script src="../../node_modules/angular/angular.js"></script>
<script src="../../dist/angular_1_router.js"></script>
<script>
angular.module('myApp', ['ngComponentRouter'])
.controller('MyCtrl', ['$router', function ($router) {
console.log($router);
$router.navigate('/')
.then(console.log.bind(console, 'resolve'), console.log.bind(console, 'reject'));
}]);
</script>
</body>
</html>

View File

@ -0,0 +1,28 @@
'use strict';
var sauceConf = require('../../sauce.conf');
// This runs the tests for the router in Angular 1.x
module.exports = function (config) {
var options = {
frameworks: ['jasmine'],
files: [
'../../node_modules/angular/angular.js',
'../../node_modules/angular-animate/angular-animate.js',
'../../node_modules/angular-mocks/angular-mocks.js',
'../../dist/angular_1_router.js',
'test/*.es5.js',
'test/*_spec.js'
],
customLaunchers: sauceConf.customLaunchers,
browsers: ['ChromeCanary']
};
config.set(options);
};

View File

@ -0,0 +1,305 @@
function CONST() {
return (function(target) {
return target;
});
}
function IMPLEMENTS(_) {
return (function(t) {
return t;
});
}
function CONST_EXPR(expr) {
return expr;
}
function isPresent (x) {
return !!x;
}
function isBlank (x) {
return !x;
}
function isString(obj) {
return typeof obj === 'string';
}
function isType (x) {
return typeof x === 'function';
}
function isStringMap(obj) {
return typeof obj === 'object' && obj !== null;
}
function isArray(obj) {
return Array.isArray(obj);
}
var PromiseWrapper = {
resolve: function (reason) {
return $q.when(reason);
},
reject: function (reason) {
return $q.reject(reason);
},
catchError: function (promise, fn) {
return promise.then(null, fn);
},
all: function (promises) {
return $q.all(promises);
}
};
var RegExpWrapper = {
create: function(regExpStr, flags) {
flags = flags ? flags.replace(/g/g, '') : '';
return new RegExp(regExpStr, flags + 'g');
},
firstMatch: function(regExp, input) {
regExp.lastIndex = 0;
return regExp.exec(input);
},
matcher: function (regExp, input) {
regExp.lastIndex = 0;
return { re: regExp, input: input };
}
};
var reflector = {
annotations: function (fn) {
//TODO: implement me
return fn.annotations || [];
}
};
var MapWrapper = {
create: function() {
return new Map();
},
get: function(m, k) {
return m.get(k);
},
set: function(m, k, v) {
return m.set(k, v);
},
contains: function (m, k) {
return m.has(k);
},
forEach: function (m, fn) {
return m.forEach(fn);
}
};
var StringMapWrapper = {
create: function () {
return {};
},
set: function (m, k, v) {
return m[k] = v;
},
get: function (m, k) {
return m.hasOwnProperty(k) ? m[k] : undefined;
},
contains: function (m, k) {
return m.hasOwnProperty(k);
},
keys: function(map) {
return Object.keys(map);
},
isEmpty: function(map) {
for (var prop in map) {
if (map.hasOwnProperty(prop)) {
return false;
}
}
return true;
},
delete: function(map, key) {
delete map[key];
},
forEach: function (m, fn) {
for (prop in m) {
if (m.hasOwnProperty(prop)) {
fn(m[prop], prop);
}
}
},
equals: function (m1, m2) {
var k1 = Object.keys(m1);
var k2 = Object.keys(m2);
if (k1.length != k2.length) {
return false;
}
var key;
for (var i = 0; i < k1.length; i++) {
key = k1[i];
if (m1[key] !== m2[key]) {
return false;
}
}
return true;
},
merge: function(m1, m2) {
var m = {};
for (var attr in m1) {
if (m1.hasOwnProperty(attr)) {
m[attr] = m1[attr];
}
}
for (var attr in m2) {
if (m2.hasOwnProperty(attr)) {
m[attr] = m2[attr];
}
}
return m;
}
};
var List = Array;
var ListWrapper = {
create: function () {
return [];
},
push: function (l, v) {
return l.push(v);
},
forEach: function (l, fn) {
return l.forEach(fn);
},
first: function(array) {
if (!array)
return null;
return array[0];
},
map: function (l, fn) {
return l.map(fn);
},
join: function (l, str) {
return l.join(str);
},
reduce: function(list, fn, init) {
return list.reduce(fn, init);
},
filter: function(array, pred) {
return array.filter(pred);
},
concat: function(a, b) {
return a.concat(b);
},
slice: function(l) {
var from = arguments[1] !== (void 0) ? arguments[1] : 0;
var to = arguments[2] !== (void 0) ? arguments[2] : null;
return l.slice(from, to === null ? undefined : to);
},
maximum: function(list, predicate) {
if (list.length == 0) {
return null;
}
var solution = null;
var maxValue = -Infinity;
for (var index = 0; index < list.length; index++) {
var candidate = list[index];
if (isBlank(candidate)) {
continue;
}
var candidateValue = predicate(candidate);
if (candidateValue > maxValue) {
solution = candidate;
maxValue = candidateValue;
}
}
return solution;
}
};
var StringWrapper = {
equals: function (s1, s2) {
return s1 === s2;
},
split: function(s, re) {
return s.split(re);
},
substring: function(s, start, end) {
return s.substr(start, end);
},
replaceAll: function(s, from, replace) {
return s.replace(from, replace);
},
startsWith: function(s, start) {
return s.startsWith(start);
},
replaceAllMapped: function(s, from, cb) {
return s.replace(from, function(matches) {
// Remove offset & string from the result array
matches.splice(-2, 2);
// The callback receives match, p1, ..., pn
return cb.apply(null, matches);
});
},
contains: function(s, substr) {
return s.indexOf(substr) != -1;
}
};
//TODO: implement?
// I think it's too heavy to ask 1.x users to bring in Rx for the router...
function EventEmitter() {
}
var BaseException = Error;
var ObservableWrapper = {
callNext: function(){}
};
// TODO: https://github.com/angular/angular.js/blob/master/src/ng/browser.js#L227-L265
var $__router_47_location__ = {
Location: Location
};
function Location(){}
Location.prototype.subscribe = function () {
//TODO: implement
};
Location.prototype.path = function () {
return $location.path();
};
Location.prototype.go = function (url) {
return $location.path(url);
};

432
modules/angular1_router/src/ng_outlet.js vendored Normal file
View File

@ -0,0 +1,432 @@
'use strict';
/*
* A module for adding new a routing system Angular 1.
*/
angular.module('ngComponentRouter', [])
.factory('$componentMapper', $componentMapperFactory)
.directive('ngOutlet', ngOutletDirective)
.directive('ngOutlet', ngOutletFillContentDirective)
.directive('ngLink', ngLinkDirective)
.directive('a', anchorLinkDirective); // TODO: make the anchor link feature configurable
/*
* A module for inspecting controller constructors
*/
angular.module('ng')
.provider('$$controllerIntrospector', $$controllerIntrospectorProvider)
.config(controllerProviderDecorator);
/*
* decorates with routing info
*/
function controllerProviderDecorator($controllerProvider, $$controllerIntrospectorProvider) {
var register = $controllerProvider.register;
$controllerProvider.register = function (name, ctrl) {
$$controllerIntrospectorProvider.register(name, ctrl);
return register.apply(this, arguments);
};
}
// TODO: decorate $controller ?
/*
* private service that holds route mappings for each controller
*/
function $$controllerIntrospectorProvider() {
var controllers = [];
var controllersByName = {};
var onControllerRegistered = null;
return {
register: function (name, constructor) {
if (angular.isArray(constructor)) {
constructor = constructor[constructor.length - 1];
}
controllersByName[name] = constructor;
constructor.$$controllerName = name;
if (onControllerRegistered) {
onControllerRegistered(name, constructor);
} else {
controllers.push({name: name, constructor: constructor});
}
},
$get: ['$componentMapper', function ($componentMapper) {
var fn = function (newOnControllerRegistered) {
onControllerRegistered = function (name, constructor) {
name = $componentMapper.component(name);
return newOnControllerRegistered(name, constructor);
};
while (controllers.length > 0) {
var rule = controllers.pop();
onControllerRegistered(rule.name, rule.constructor);
}
};
fn.getTypeByName = function (name) {
return controllersByName[name];
};
return fn;
}]
};
}
/**
* @name ngOutlet
*
* @description
* An ngOutlet is where resolved content goes.
*
* ## Use
*
* ```html
* <div ng-outlet="name"></div>
* ```
*
* The value for the `ngOutlet` attribute is optional.
*/
function ngOutletDirective($animate, $injector, $q, $router, $componentMapper, $controller,
$$controllerIntrospector, $templateRequest) {
var rootRouter = $router;
return {
restrict: 'AE',
transclude: 'element',
terminal: true,
priority: 400,
require: ['?^^ngOutlet', 'ngOutlet'],
link: outletLink,
controller: function () {},
controllerAs: '$$ngOutlet'
};
function outletLink(scope, $element, attrs, ctrls, $transclude) {
var outletName = attrs.ngOutlet || 'default',
parentCtrl = ctrls[0],
myCtrl = ctrls[1],
router = (parentCtrl && parentCtrl.$$router) || rootRouter;
var childRouter,
currentInstruction,
currentScope,
currentController,
currentElement,
previousLeaveAnimation;
function cleanupLastView() {
if (previousLeaveAnimation) {
$animate.cancel(previousLeaveAnimation);
previousLeaveAnimation = null;
}
if (currentScope) {
currentScope.$destroy();
currentScope = null;
}
if (currentElement) {
previousLeaveAnimation = $animate.leave(currentElement);
previousLeaveAnimation.then(function () {
previousLeaveAnimation = null;
});
currentElement = null;
}
}
router.registerOutlet({
commit: function (instruction) {
var next;
var componentInstruction = instruction.component;
if (componentInstruction.reuse) {
// todo(shahata): lifecycle - onReuse
next = $q.when(true);
} else {
var self = this;
next = this.deactivate(instruction).then(function () {
return self.activate(componentInstruction);
});
}
return next.then(function () {
if (childRouter) {
return childRouter.commit(instruction.child);
} else {
return $q.when(true);
}
});
},
canReuse: function (nextInstruction) {
var result;
var componentInstruction = nextInstruction.component;
if (!currentInstruction ||
currentInstruction.componentType !== componentInstruction.componentType) {
result = false;
} else {
// todo(shahata): lifecycle - canReuse
result = componentInstruction === currentInstruction ||
angular.equals(componentInstruction.params, currentInstruction.params);
}
return $q.when(result).then(function (result) {
// TODO: this is a hack
componentInstruction.reuse = result;
return result;
});
},
canDeactivate: function (instruction) {
if (currentInstruction && currentController && currentController.canDeactivate) {
return $q.when(currentController.canDeactivate(instruction && instruction.component, currentInstruction));
}
return $q.when(true);
},
deactivate: function (instruction) {
// todo(shahata): childRouter.dectivate, dispose component?
var result = $q.when();
return result.then(function () {
if (currentController && currentController.onDeactivate) {
return currentController.onDeactivate(instruction && instruction.component, currentInstruction);
}
});
},
activate: function (instruction) {
var previousInstruction = currentInstruction;
currentInstruction = instruction;
childRouter = router.childRouter(instruction.componentType);
var controllerConstructor, componentName;
controllerConstructor = instruction.componentType;
componentName = $componentMapper.component(controllerConstructor.$$controllerName);
var componentTemplateUrl = $componentMapper.template(componentName);
return $templateRequest(componentTemplateUrl).then(function (templateHtml) {
myCtrl.$$router = childRouter;
myCtrl.$$template = templateHtml;
}).then(function () {
var newScope = scope.$new();
var locals = {
$scope: newScope,
$router: childRouter,
$routeParams: (instruction.params || {})
};
// todo(shahata): controllerConstructor is not minify friendly
currentController = $controller(controllerConstructor, locals);
var clone = $transclude(newScope, function (clone) {
$animate.enter(clone, null, currentElement || $element);
cleanupLastView();
});
var controllerAs = $componentMapper.controllerAs(componentName) || componentName;
newScope[controllerAs] = currentController;
currentElement = clone;
currentScope = newScope;
if (currentController.onActivate) {
return currentController.onActivate(instruction, previousInstruction);
}
});
}
}, outletName);
}
}
function ngOutletFillContentDirective($compile) {
return {
restrict: 'EA',
priority: -400,
require: 'ngOutlet',
link: function (scope, $element, attrs, ctrl) {
var template = ctrl.$$template;
$element.html(template);
var link = $compile($element.contents());
link(scope);
}
};
}
/**
* @name ngLink
* @description
* Lets you link to different parts of the app, and automatically generates hrefs.
*
* ## Use
* The directive uses a simple syntax: `ng-link="componentName({ param: paramValue })"`
*
* ## Example
*
* ```js
* angular.module('myApp', ['ngFuturisticRouter'])
* .controller('AppController', ['$router', function($router) {
* $router.config({ path: '/user/:id' component: 'user' });
* this.user = { name: 'Brian', id: 123 };
* });
* ```
*
* ```html
* <div ng-controller="AppController as app">
* <a ng-link="user({id: app.user.id})">{{app.user.name}}</a>
* </div>
* ```
*/
function ngLinkDirective($router, $location, $parse) {
var rootRouter = $router;
return {
require: '?^^ngOutlet',
restrict: 'A',
link: ngLinkDirectiveLinkFn
};
function ngLinkDirectiveLinkFn(scope, elt, attrs, ctrl) {
var router = (ctrl && ctrl.$$router) || rootRouter;
if (!router) {
return;
}
var link = attrs.ngLink || '';
function getLink(params) {
return './' + angular.stringifyInstruction(router.generate(params));
}
var routeParamsGetter = $parse(link);
// we can avoid adding a watcher if it's a literal
if (routeParamsGetter.constant) {
var params = routeParamsGetter();
elt.attr('href', getLink(params));
} else {
scope.$watch(function () {
return routeParamsGetter(scope);
}, function (params) {
elt.attr('href', getLink(params));
}, true);
}
}
}
function anchorLinkDirective($router) {
return {
restrict: 'E',
link: function (scope, element) {
// If the linked element is not an anchor tag anymore, do nothing
if (element[0].nodeName.toLowerCase() !== 'a') {
return;
}
// SVGAElement does not use the href attribute, but rather the 'xlinkHref' attribute.
var hrefAttrName = Object.prototype.toString.call(element.prop('href')) === '[object SVGAnimatedString]' ?
'xlink:href' : 'href';
element.on('click', function (event) {
if (event.which !== 1) {
return;
}
var href = element.attr(hrefAttrName);
if (href && $router.recognize(href)) {
$router.navigate(href);
event.preventDefault();
}
});
}
};
}
/**
* @name $componentMapperFactory
* @description
*
* This lets you configure conventions for what controllers are named and where to load templates from.
*
* The default behavior is to dasherize and serve from `./components`. A component called `myWidget`
* uses a controller named `MyWidgetController` and a template loaded from `./components/my-widget/my-widget.html`.
*
* A component is:
* - a controller
* - a template
* - an optional router
*
* This service makes it easy to group all of them into a single concept.
*/
function $componentMapperFactory() {
var DEFAULT_SUFFIX = 'Controller';
var componentToCtrl = function componentToCtrlDefault(name) {
return name[0].toUpperCase() + name.substr(1) + DEFAULT_SUFFIX;
};
var componentToTemplate = function componentToTemplateDefault(name) {
var dashName = dashCase(name);
return './components/' + dashName + '/' + dashName + '.html';
};
var ctrlToComponent = function ctrlToComponentDefault(name) {
return name[0].toLowerCase() + name.substr(1, name.length - DEFAULT_SUFFIX.length - 1);
};
var componentToControllerAs = function componentToControllerAsDefault(name) {
return name;
};
return {
controllerName: function (name) {
return componentToCtrl(name);
},
controllerAs: function (name) {
return componentToControllerAs(name);
},
template: function (name) {
return componentToTemplate(name);
},
component: function (name) {
return ctrlToComponent(name);
},
/**
* @name $componentMapper#setCtrlNameMapping
* @description takes a function for mapping component names to component controller names
*/
setCtrlNameMapping: function (newFn) {
componentToCtrl = newFn;
return this;
},
/**
* @name $componentMapper#setCtrlAsMapping
* @description takes a function for mapping component names to controllerAs name in the template
*/
setCtrlAsMapping: function (newFn) {
componentToControllerAs = newFn;
return this;
},
/**
* @name $componentMapper#setComponentFromCtrlMapping
* @description takes a function for mapping component controller names to component names
*/
setComponentFromCtrlMapping: function (newFn) {
ctrlToComponent = newFn;
return this;
},
/**
* @name $componentMapper#setTemplateMapping
* @description takes a function for mapping component names to component template URLs
*/
setTemplateMapping: function (newFn) {
componentToTemplate = newFn;
return this;
}
};
}
function dashCase(str) {
return str.replace(/([A-Z])/g, function ($1) {
return '-' + $1.toLowerCase();
});
}

View File

@ -0,0 +1,77 @@
'use strict';
describe('$componentMapper', function () {
var elt,
$compile,
$rootScope,
$router,
$templateCache;
function Ctrl() {
this.message = 'howdy';
}
beforeEach(function() {
module('ng');
module('ngComponentRouter');
module(function ($controllerProvider) {
$controllerProvider.register('myComponentController', Ctrl);
});
});
it('should convert a component name to a controller name', inject(function ($componentMapper) {
expect($componentMapper.controllerName('foo')).toBe('FooController');
}));
it('should convert a controller name to a component name', inject(function ($componentMapper) {
expect($componentMapper.component('FooController')).toBe('foo');
}));
it('should convert a component name to a template URL', inject(function ($componentMapper) {
expect($componentMapper.template('foo')).toBe('./components/foo/foo.html');
}));
it('should work with a controller constructor fn and a template url', inject(function ($componentMapper) {
var routes = {};
$componentMapper.setCtrlNameMapping(function (name) {
return routes[name].controller;
});
$componentMapper.setTemplateMapping(function (name) {
return routes[name].templateUrl;
});
$componentMapper.setCtrlAsMapping(function (name) {
return 'ctrl';
});
routes.myComponent = {
controller: Ctrl,
templateUrl: '/foo'
};
inject(function(_$compile_, _$rootScope_, _$router_, _$templateCache_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
$router = _$router_;
$templateCache = _$templateCache_;
});
$templateCache.put('/foo', [200, '{{ctrl.message}}', {}]);
compile('<ng-outlet></ng-outlet>');
$router.config([
{ path: '/', component: Ctrl }
]);
$router.navigate('/');
$rootScope.$digest();
expect(elt.text()).toBe('howdy');
}));
function compile(template) {
elt = $compile('<div>' + template + '</div>')($rootScope);
$rootScope.$digest();
return elt;
}
});

View File

@ -0,0 +1,38 @@
'use strict';
describe('$$controllerIntrospector', function () {
var $controllerProvider;
beforeEach(function() {
module('ng');
module('ngComponentRouter');
module(function(_$controllerProvider_) {
$controllerProvider = _$controllerProvider_;
});
});
it('should call the introspector function whenever a controller is registered', inject(function ($$controllerIntrospector) {
var spy = jasmine.createSpy();
$$controllerIntrospector(spy);
function Ctrl(){}
$controllerProvider.register('SomeController', Ctrl);
expect(spy).toHaveBeenCalledWith('some', Ctrl);
}));
it('should call the introspector function whenever a controller is registered with array annotations', inject(function ($$controllerIntrospector) {
var spy = jasmine.createSpy();
$$controllerIntrospector(spy);
function Ctrl(foo){}
$controllerProvider.register('SomeController', ['foo', Ctrl]);
expect(spy).toHaveBeenCalledWith('some', Ctrl);
}));
it('should retrieve a constructor', inject(function ($$controllerIntrospector) {
function Ctrl(foo){}
$controllerProvider.register('SomeController', ['foo', Ctrl]);
expect($$controllerIntrospector.getTypeByName('SomeController')).toBe(Ctrl);
}));
});

View File

@ -0,0 +1,800 @@
'use strict';
describe('ngOutlet', function () {
var elt,
$compile,
$rootScope,
$router,
$templateCache,
$controllerProvider,
$componentMapperProvider;
var OneController, TwoController, UserController;
function instructionFor(componentType) {
return jasmine.objectContaining({componentType: componentType});
}
beforeEach(function () {
module('ng');
module('ngComponentRouter');
module(function (_$controllerProvider_, _$componentMapperProvider_) {
$controllerProvider = _$controllerProvider_;
$componentMapperProvider = _$componentMapperProvider_;
});
inject(function (_$compile_, _$rootScope_, _$router_, _$templateCache_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
$router = _$router_;
$templateCache = _$templateCache_;
});
UserController = registerComponent('user', '<div>hello {{user.name}}</div>', function ($routeParams) {
this.name = $routeParams.name;
});
OneController = registerComponent('one', '<div>{{one.number}}</div>', boringController('number', 'one'));
TwoController = registerComponent('two', '<div>{{two.number}}</div>', boringController('number', 'two'));
});
it('should work in a simple case', function () {
compile('<ng-outlet></ng-outlet>');
$router.config([
{ path: '/', component: OneController }
]);
$router.navigate('/');
$rootScope.$digest();
expect(elt.text()).toBe('one');
});
// See https://github.com/angular/router/issues/105
xit('should warn when instantiating a component with no controller', function () {
put('noController', '<div>{{ 2 + 2 }}</div>');
$router.config([
{ path: '/', component: 'noController' }
]);
spyOn(console, 'warn');
compile('<ng-outlet></ng-outlet>');
$router.navigate('/');
expect(console.warn).toHaveBeenCalledWith('Could not find controller for', 'NoControllerController');
expect(elt.text()).toBe('4');
});
it('should navigate between components with different parameters', function () {
$router.config([
{ path: '/user/:name', component: UserController }
]);
compile('<ng-outlet></ng-outlet>');
$router.navigate('/user/brian');
$rootScope.$digest();
expect(elt.text()).toBe('hello brian');
$router.navigate('/user/igor');
$rootScope.$digest();
expect(elt.text()).toBe('hello igor');
});
it('should not reactivate a parent when navigating between child components with different parameters', function () {
var spy = jasmine.createSpy('onActivate');
function ParentController() {}
ParentController.$routeConfig = [
{ path: '/user/:name', component: UserController }
];
ParentController.prototype.onActivate = spy;
registerComponent('parent', 'parent { <ng-outlet></ng-outlet> }', ParentController);
$router.config([
{ path: '/parent/...', component: ParentController }
]);
compile('<ng-outlet></ng-outlet>');
$router.navigate('/parent/user/brian');
$rootScope.$digest();
expect(spy).toHaveBeenCalled();
expect(elt.text()).toBe('parent { hello brian }');
spy.calls.reset();
$router.navigate('/parent/user/igor');
$rootScope.$digest();
expect(spy).not.toHaveBeenCalled();
expect(elt.text()).toBe('parent { hello igor }');
});
it('should work with nested outlets', function () {
var childComponent = registerComponent('childComponent', '<div>inner { <div ng-outlet></div> }</div>', [
{ path: '/b', component: OneController }
]);
$router.config([
{ path: '/a/...', component: childComponent }
]);
compile('<div>outer { <div ng-outlet></div> }</div>');
$router.navigate('/a/b');
$rootScope.$digest();
expect(elt.text()).toBe('outer { inner { one } }');
});
it('should work with recursive nested outlets', function () {
put('two', '<div>recur { <div ng-outlet></div> }</div>');
$router.config([
{ path: '/recur', component: TwoController },
{ path: '/', component: OneController }
]);
compile('<div>root { <div ng-outlet></div> }</div>');
$router.navigate('/');
$rootScope.$digest();
expect(elt.text()).toBe('root { one }');
});
it('should allow linking from the parent to the child', function () {
put('one', '<div>{{number}}</div>');
$router.config([
{ path: '/a', component: OneController },
{ path: '/b', component: TwoController, as: 'two' }
]);
compile('<a ng-link="[\'/two\']">link</a> | outer { <div ng-outlet></div> }');
$router.navigate('/a');
$rootScope.$digest();
expect(elt.find('a').attr('href')).toBe('./b');
});
it('should allow linking from the child and the parent', function () {
put('one', '<div><a ng-link="[\'/two\']">{{number}}</a></div>');
$router.config([
{ path: '/a', component: OneController },
{ path: '/b', component: TwoController, as: 'two' }
]);
compile('outer { <div ng-outlet></div> }');
$router.navigate('/a');
$rootScope.$digest();
expect(elt.find('a').attr('href')).toBe('./b');
});
it('should allow params in routerLink directive', function () {
put('router', '<div>outer { <div ng-outlet></div> }</div>');
put('one', '<div><a ng-link="[\'/two\', {param: \'lol\'}]">{{number}}</a></div>');
$router.config([
{ path: '/a', component: OneController },
{ path: '/b/:param', component: TwoController, as: 'two' }
]);
compile('<div ng-outlet></div>');
$router.navigate('/a');
$rootScope.$digest();
expect(elt.find('a').attr('href')).toBe('./b/lol');
});
// TODO: test dynamic links
it('should update the href of links with bound params', function () {
put('router', '<div>outer { <div ng-outlet></div> }</div>');
put('one', '<div><a ng-link="[\'/two\', {param: one.number}]">{{one.number}}</a></div>');
$router.config([
{ path: '/a', component: OneController },
{ path: '/b/:param', component: TwoController, as: 'two' }
]);
compile('<div ng-outlet></div>');
$router.navigate('/a');
$rootScope.$digest();
expect(elt.find('a').attr('href')).toBe('./b/one');
});
it('should run the activate hook of controllers', function () {
var spy = jasmine.createSpy('activate');
var activate = registerComponent('activate', '', {
onActivate: spy
});
$router.config([
{ path: '/a', component: activate }
]);
compile('<div>outer { <div ng-outlet></div> }</div>');
$router.navigate('/a');
$rootScope.$digest();
expect(spy).toHaveBeenCalled();
});
it('should pass instruction into the activate hook of a controller', function () {
var spy = jasmine.createSpy('activate');
var UserController = registerComponent('user', '', {
onActivate: spy
});
$router.config([
{ path: '/user/:name', component: UserController }
]);
compile('<div ng-outlet></div>');
$router.navigate('/user/brian');
$rootScope.$digest();
expect(spy).toHaveBeenCalledWith(instructionFor(UserController), undefined);
});
it('should pass previous instruction into the activate hook of a controller', function () {
var spy = jasmine.createSpy('activate');
var activate = registerComponent('activate', '', {
onActivate: spy
});
$router.config([
{ path: '/user/:name', component: OneController },
{ path: '/post/:id', component: activate }
]);
compile('<div ng-outlet></div>');
$router.navigate('/user/brian');
$rootScope.$digest();
$router.navigate('/post/123');
$rootScope.$digest();
expect(spy).toHaveBeenCalledWith(instructionFor(activate),
instructionFor(OneController));
});
it('should inject $scope into the controller constructor', function () {
var injectedScope;
var UserController = registerComponent('user', '', function ($scope) {
injectedScope = $scope;
});
$router.config([
{ path: '/user', component: UserController }
]);
compile('<div ng-outlet></div>');
$router.navigate('/user');
$rootScope.$digest();
expect(injectedScope).toBeDefined();
});
it('should run the deactivate hook of controllers', function () {
var spy = jasmine.createSpy('deactivate');
var deactivate = registerComponent('deactivate', '', {
onDeactivate: spy
});
$router.config([
{ path: '/a', component: deactivate },
{ path: '/b', component: OneController }
]);
compile('<div ng-outlet></div>');
$router.navigate('/a');
$rootScope.$digest();
$router.navigate('/b');
$rootScope.$digest();
expect(spy).toHaveBeenCalled();
});
it('should pass instructions into the deactivate hook of controllers', function () {
var spy = jasmine.createSpy('deactivate');
var deactivate = registerComponent('deactivate', '', {
onDeactivate: spy
});
$router.config([
{ path: '/user/:name', component: deactivate },
{ path: '/post/:id', component: OneController }
]);
compile('<div ng-outlet></div>');
$router.navigate('/user/brian');
$rootScope.$digest();
$router.navigate('/post/123');
$rootScope.$digest();
expect(spy).toHaveBeenCalledWith(instructionFor(OneController),
instructionFor(deactivate));
});
it('should run the deactivate hook before the activate hook', function () {
var log = [];
var activate = registerComponent('activate', '', {
onActivate: function () {
log.push('activate');
}
});
var deactivate = registerComponent('deactivate', '', {
onDeactivate: function () {
log.push('deactivate');
}
});
$router.config([
{ path: '/a', component: deactivate },
{ path: '/b', component: activate }
]);
compile('outer { <div ng-outlet></div> }');
$router.navigate('/a');
$rootScope.$digest();
$router.navigate('/b');
$rootScope.$digest();
expect(log).toEqual(['deactivate', 'activate']);
});
it('should not activate a component when canActivate returns false', function () {
var spy = jasmine.createSpy('activate');
var activate = registerComponent('activate', '', {
canActivate: function () {
return false;
},
onActivate: spy
});
$router.config([
{ path: '/a', component: activate }
]);
compile('outer { <div ng-outlet></div> }');
$router.navigate('/a');
$rootScope.$digest();
expect(spy).not.toHaveBeenCalled();
expect(elt.text()).toBe('outer { }');
});
it('should activate a component when canActivate returns true', function () {
var spy = jasmine.createSpy('activate');
var activate = registerComponent('activate', 'hi', {
canActivate: function () {
return true;
},
onActivate: spy
});
$router.config([
{ path: '/a', component: activate }
]);
compile('<div ng-outlet></div>');
$router.navigate('/a');
$rootScope.$digest();
expect(spy).toHaveBeenCalled();
expect(elt.text()).toBe('hi');
});
it('should activate a component when canActivate returns a resolved promise', inject(function ($q) {
var spy = jasmine.createSpy('activate');
var activate = registerComponent('activate', 'hi', {
canActivate: function () {
return $q.when(true);
},
onActivate: spy
});
$router.config([
{ path: '/a', component: activate }
]);
compile('<div ng-outlet></div>');
$router.navigate('/a');
$rootScope.$digest();
expect(spy).toHaveBeenCalled();
expect(elt.text()).toBe('hi');
}));
it('should inject into the canActivate hook of controllers', inject(function ($http) {
var spy = jasmine.createSpy('canActivate').and.returnValue(true);
var activate = registerComponent('activate', '', {
canActivate: spy
});
spy.$inject = ['$routeParams', '$http'];
$router.config([
{ path: '/user/:name', component: activate }
]);
compile('<div ng-outlet></div>');
$router.navigate('/user/brian');
$rootScope.$digest();
expect(spy).toHaveBeenCalledWith({name: 'brian'}, $http);
}));
it('should not navigate when canDeactivate returns false', function () {
var activate = registerComponent('activate', 'hi', {
canDeactivate: function () {
return false;
}
});
$router.config([
{ path: '/a', component: activate },
{ path: '/b', component: OneController }
]);
compile('outer { <div ng-outlet></div> }');
$router.navigate('/a');
$rootScope.$digest();
expect(elt.text()).toBe('outer { hi }');
$router.navigate('/b');
$rootScope.$digest();
expect(elt.text()).toBe('outer { hi }');
});
it('should navigate when canDeactivate returns true', function () {
var activate = registerComponent('activate', 'hi', {
canDeactivate: function () {
return true;
}
});
$router.config([
{ path: '/a', component: activate },
{ path: '/b', component: OneController }
]);
compile('outer { <div ng-outlet></div> }');
$router.navigate('/a');
$rootScope.$digest();
expect(elt.text()).toBe('outer { hi }');
$router.navigate('/b');
$rootScope.$digest();
expect(elt.text()).toBe('outer { one }');
});
it('should activate a component when canActivate returns true', function () {
var spy = jasmine.createSpy('activate');
var activate = registerComponent('activate', 'hi', {
canActivate: function () {
return true;
},
onActivate: spy
});
$router.config([
{ path: '/a', component: activate }
]);
compile('<div ng-outlet></div>');
$router.navigate('/a');
$rootScope.$digest();
expect(spy).toHaveBeenCalled();
expect(elt.text()).toBe('hi');
});
it('should pass instructions into the canDeactivate hook of controllers', function () {
var spy = jasmine.createSpy('canDeactivate').and.returnValue(true);
var deactivate = registerComponent('deactivate', '', {
canDeactivate: spy
});
$router.config([
{ path: '/user/:name', component: deactivate },
{ path: '/post/:id', component: OneController }
]);
compile('<div ng-outlet></div>');
$router.navigate('/user/brian');
$rootScope.$digest();
$router.navigate('/post/123');
$rootScope.$digest();
expect(spy).toHaveBeenCalledWith(instructionFor(OneController),
instructionFor(deactivate));
});
it('should change location path', inject(function ($location) {
$router.config([
{ path: '/user', component: UserController }
]);
compile('<div ng-outlet></div>');
$router.navigate('/user');
$rootScope.$digest();
expect($location.path()).toBe('/user');
}));
// TODO: test injecting $scope
it('should navigate on left-mouse click when a link url matches a route', function () {
$router.config([
{ path: '/', component: OneController },
{ path: '/two', component: TwoController }
]);
compile('<a href="/two">link</a> | <div ng-outlet></div>');
$rootScope.$digest();
expect(elt.text()).toBe('link | one');
elt.find('a')[0].click();
$rootScope.$digest();
expect(elt.text()).toBe('link | two');
});
it('should not navigate on non-left mouse click when a link url matches a route', inject(function ($router) {
$router.config([
{ path: '/', component: OneController },
{ path: '/two', component: TwoController }
]);
compile('<a href="./two">link</a> | <div ng-outlet></div>');
$rootScope.$digest();
expect(elt.text()).toBe('link | one');
elt.find('a').triggerHandler({ type: 'click', which: 3 });
$rootScope.$digest();
expect(elt.text()).toBe('link | one');
}));
// See https://github.com/angular/router/issues/206
it('should not navigate a link without an href', function () {
$router.config([
{ path: '/', component: OneController },
{ path: '/two', component: TwoController }
]);
expect(function () {
compile('<a>link</a>');
$rootScope.$digest();
expect(elt.text()).toBe('link');
elt.find('a')[0].click();
$rootScope.$digest();
}).not.toThrow();
});
it('should change location to the canonical route', inject(function ($location) {
compile('<div ng-outlet></div>');
$router.config([
{ path: '/', redirectTo: '/user' },
{ path: '/user', component: UserController }
]);
$router.navigate('/');
$rootScope.$digest();
expect($location.path()).toBe('/user');
}));
it('should change location to the canonical route with nested components', inject(function ($location) {
var childRouter = registerComponent('childRouter', '<div>inner { <div ng-outlet></div> }</div>', [
{ path: '/old-child', redirectTo: '/new-child' },
{ path: '/new-child', component: OneController},
{ path: '/old-child-two', redirectTo: '/new-child-two' },
{ path: '/new-child-two', component: TwoController}
]);
$router.config([
{ path: '/old-parent', redirectTo: '/new-parent' },
{ path: '/new-parent/...', component: childRouter }
]);
compile('<div ng-outlet></div>');
$router.navigate('/old-parent/old-child');
$rootScope.$digest();
expect($location.path()).toBe('/new-parent/new-child');
expect(elt.text()).toBe('inner { one }');
$router.navigate('/old-parent/old-child-two');
$rootScope.$digest();
expect($location.path()).toBe('/new-parent/new-child-two');
expect(elt.text()).toBe('inner { two }');
}));
it('should navigate when the location path changes', inject(function ($location) {
$router.config([
{ path: '/one', component: OneController }
]);
compile('<div ng-outlet></div>');
$location.path('/one');
$rootScope.$digest();
expect(elt.text()).toBe('one');
}));
it('should expose a "navigating" property on $router', inject(function ($q) {
var defer;
var pendingActivate = registerComponent('pendingActivate', '', {
onActivate: function () {
defer = $q.defer();
return defer.promise;
}
});
$router.config([
{ path: '/pendingActivate', component: pendingActivate }
]);
compile('<div ng-outlet></div>');
$router.navigate('/pendingActivate');
$rootScope.$digest();
expect($router.navigating).toBe(true);
defer.resolve();
$rootScope.$digest();
expect($router.navigating).toBe(false);
}));
function registerComponent(name, template, config) {
var Ctrl;
if (!template) {
template = '';
}
if (!config) {
Ctrl = function () {};
} else if (angular.isArray(config)) {
Ctrl = function () {};
Ctrl.annotations = [new angular.annotations.RouteConfig(config)];
} else if (typeof config === 'function') {
Ctrl = config;
} else {
Ctrl = function () {};
if (config.canActivate) {
Ctrl.$canActivate = config.canActivate;
delete config.canActivate;
}
Ctrl.prototype = config;
}
$controllerProvider.register(componentControllerName(name), Ctrl);
put(name, template);
return Ctrl;
}
function boringController(model, value) {
return function () {
this[model] = value;
};
}
function put(name, template) {
$templateCache.put(componentTemplatePath(name), [200, template, {}]);
}
function compile(template) {
elt = $compile('<div>' + template + '</div>')($rootScope);
$rootScope.$digest();
return elt;
}
});
describe('ngOutlet animations', function () {
var elt,
$animate,
$compile,
$rootScope,
$router,
$templateCache,
$controllerProvider;
function UserController($routeParams) {
this.name = $routeParams.name;
}
beforeEach(function () {
module('ngAnimate');
module('ngAnimateMock');
module('ngComponentRouter');
module(function (_$controllerProvider_) {
$controllerProvider = _$controllerProvider_;
});
inject(function (_$animate_, _$compile_, _$rootScope_, _$router_, _$templateCache_) {
$animate = _$animate_;
$compile = _$compile_;
$rootScope = _$rootScope_;
$router = _$router_;
$templateCache = _$templateCache_;
});
put('user', '<div>hello {{user.name}}</div>');
$controllerProvider.register('UserController', UserController);
});
afterEach(function () {
expect($animate.queue).toEqual([]);
});
it('should work in a simple case', function () {
var item;
compile('<div ng-outlet></div>');
$router.config([
{ path: '/user/:name', component: UserController }
]);
$router.navigate('/user/brian');
$rootScope.$digest();
expect(elt.text()).toBe('hello brian');
// "user" component enters
item = $animate.queue.shift();
expect(item.event).toBe('enter');
// navigate to pete
$router.navigate('/user/pete');
$rootScope.$digest();
expect(elt.text()).toBe('hello pete');
// "user pete" component enters
item = $animate.queue.shift();
expect(item.event).toBe('enter');
expect(item.element.text()).toBe('hello pete');
// "user brian" component leaves
item = $animate.queue.shift();
expect(item.event).toBe('leave');
expect(item.element.text()).toBe('hello brian');
});
function put(name, template) {
$templateCache.put(componentTemplatePath(name), [200, template, {}]);
}
function compile(template) {
elt = $compile('<div>' + template + '</div>')($rootScope);
$rootScope.$digest();
return elt;
}
});

View File

@ -0,0 +1,85 @@
/*
* Helpers to keep tests DRY
*/
function componentTemplatePath(name) {
return './components/' + dashCase(name) + '/' + dashCase(name) + '.html';
}
function componentControllerName(name) {
return name[0].toUpperCase() + name.substr(1) + 'Controller';
}
function dashCase(str) {
return str.replace(/([A-Z])/g, function ($1) {
return '-' + $1.toLowerCase();
});
}
function boringController (model, value) {
return function () {
this[model] = value;
};
}
function provideHelpers(fn, preInject) {
return function () {
var elt,
$compile,
$rootScope,
$router,
$templateCache,
$controllerProvider;
module('ng');
module('ngNewRouter');
module(function(_$controllerProvider_) {
$controllerProvider = _$controllerProvider_;
});
inject(function(_$compile_, _$rootScope_, _$router_, _$templateCache_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
$router = _$router_;
$templateCache = _$templateCache_;
});
function registerComponent(name, template, config) {
if (!template) {
template = '';
}
var ctrl;
if (!config) {
ctrl = function () {};
} else if (angular.isArray(config)) {
ctrl = function () {};
ctrl.$routeConfig = config;
} else if (typeof config === 'function') {
ctrl = config;
} else {
ctrl = function () {};
ctrl.prototype = config;
}
$controllerProvider.register(componentControllerName(name), ctrl);
put(name, template);
}
function put (name, template) {
$templateCache.put(componentTemplatePath(name), [200, template, {}]);
}
function compile(template) {
var elt = $compile('<div>' + template + '</div>')($rootScope);
$rootScope.$digest();
return elt;
}
fn({
registerComponent: registerComponent,
$router: $router,
put: put,
compile: compile
})
}
}

View File

@ -35,6 +35,8 @@
},
"devDependencies": {
"angular": "1.3.5",
"angular-animate": "1.3.5",
"angular-mocks": "1.3.5",
"base64-js": "^0.0.8",
"bower": "^1.3.12",
"broccoli": "^0.15.3",

11
scripts/ci/build_router.sh Executable file
View File

@ -0,0 +1,11 @@
#!/bin/bash
set -e
echo =============================================================================
# go to project dir
SCRIPT_DIR=$(dirname $0)
# this is needed because we're running JS tests in Dartium too
source $SCRIPT_DIR/env_dart.sh
cd $SCRIPT_DIR/../..
./node_modules/.bin/gulp buildRouter.dev

10
scripts/ci/test_router.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/bash
set -e
echo =============================================================================
# go to project dir
SCRIPT_DIR=$(dirname $0)
source $SCRIPT_DIR/env_dart.sh
cd $SCRIPT_DIR/../..
./node_modules/.bin/gulp test.unit.router/ci --browsers=${KARMA_BROWSERS:-ChromeCanary}

View File

@ -76,6 +76,7 @@ module.exports = function makeBrowserTree(options, destinationPath) {
exclude: [
'**/*.cjs',
'benchmarks/e2e_test/**',
'angular1_router/**',
// Exclude ES6 polyfill typings when tsc target=ES6
'angular2/traceur-runtime.d.ts',
'angular2/typings/es6-promise/**'

View File

@ -56,7 +56,7 @@ function stripModulePrefix(relativePath: string): string {
function getSourceTree() {
// Transpile everything in 'modules' except for rtts_assertions.
var tsInputTree = modulesFunnel(['**/*.js', '**/*.ts', '**/*.dart']);
var tsInputTree = modulesFunnel(['**/*.js', '**/*.ts', '**/*.dart'], ['angular1_router/**/*']);
var transpiled = ts2dart(tsInputTree, {
generateLibraryName: true,
generateSourceMap: false,
@ -147,7 +147,7 @@ function getDocsTree() {
var licenses = new MultiCopy('', {
srcPath: 'LICENSE',
targetPatterns: ['modules/*'],
exclude: ['*/rtts_assert', '*/http', '*/upgrade'], // Not in dart.
exclude: ['*/rtts_assert', '*/http', '*/upgrade', '*/angular1_router'] // Not in dart.
});
licenses = stew.rename(licenses, stripModulePrefix);
@ -157,7 +157,7 @@ function getDocsTree() {
relativePath => relativePath.replace(/\.dart\.md$/, '.md'));
// Copy all assets, ignore .js. and .dart. (handled above).
var docs = modulesFunnel(['**/*.md', '**/*.png', '**/*.html', '**/*.css', '**/*.scss'],
['**/*.js.md', '**/*.dart.md']);
['**/*.js.md', '**/*.dart.md', 'angular1_router/**/*']);
var assets = modulesFunnel(['examples/**/*.json']);

View File

@ -23,7 +23,8 @@ module.exports = function makeNodeTree(destinationPath) {
'angular2/test/core/zone/**',
'angular2/test/test_lib/fake_async_spec.ts',
'angular2/test/render/xhr_impl_spec.ts',
'angular2/test/forms/**'
'angular2/test/forms/**',
'angular1_router/**'
]
});