feat(router): add link that support only absolute urls
This commit is contained in:
parent
446657bdd5
commit
fa5bfe4b64
|
@ -0,0 +1,64 @@
|
||||||
|
import {Tree, TreeNode, UrlSegment, RouteSegment, rootNode} from './segments';
|
||||||
|
import {isBlank, isString, isStringMap} from 'angular2/src/facade/lang';
|
||||||
|
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
|
export function link(segment: RouteSegment, tree: Tree<UrlSegment>,
|
||||||
|
change: any[]): Tree<UrlSegment> {
|
||||||
|
if (change.length === 0) return tree;
|
||||||
|
let normalizedChange = (change.length === 1 && change[0] == "/") ? change : ["/"].concat(change);
|
||||||
|
return new Tree<UrlSegment>(_update(rootNode(tree), normalizedChange));
|
||||||
|
}
|
||||||
|
|
||||||
|
function _update(node: TreeNode<UrlSegment>, changes: any[]): TreeNode<UrlSegment> {
|
||||||
|
let rest = changes.slice(1);
|
||||||
|
let outlet = _outlet(changes);
|
||||||
|
let segment = _segment(changes);
|
||||||
|
if (isString(segment) && segment[0] == "/") segment = segment.substring(1);
|
||||||
|
|
||||||
|
// reach the end of the tree => create new tree nodes.
|
||||||
|
if (isBlank(node)) {
|
||||||
|
let urlSegment = new UrlSegment(segment, null, outlet);
|
||||||
|
let children = rest.length === 0 ? [] : [_update(null, rest)];
|
||||||
|
return new TreeNode<UrlSegment>(urlSegment, children);
|
||||||
|
|
||||||
|
// different outlet => preserve the subtree
|
||||||
|
} else if (outlet != node.value.outlet) {
|
||||||
|
return node;
|
||||||
|
|
||||||
|
// same outlet => modify the subtree
|
||||||
|
} else {
|
||||||
|
let urlSegment = isStringMap(segment) ? new UrlSegment(null, segment, null) :
|
||||||
|
new UrlSegment(segment, null, outlet);
|
||||||
|
if (rest.length === 0) {
|
||||||
|
return new TreeNode<UrlSegment>(urlSegment, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TreeNode<UrlSegment>(urlSegment,
|
||||||
|
_updateMany(ListWrapper.clone(node.children), rest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _updateMany(nodes: TreeNode<UrlSegment>[], changes: any[]): TreeNode<UrlSegment>[] {
|
||||||
|
let outlet = _outlet(changes);
|
||||||
|
let nodesInRightOutlet = nodes.filter(c => c.value.outlet == outlet);
|
||||||
|
if (nodesInRightOutlet.length > 0) {
|
||||||
|
let nodeRightOutlet = nodesInRightOutlet[0]; // there can be only one
|
||||||
|
nodes[nodes.indexOf(nodeRightOutlet)] = _update(nodeRightOutlet, changes);
|
||||||
|
} else {
|
||||||
|
nodes.push(_update(null, changes));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _segment(changes: any[]): any {
|
||||||
|
if (!isString(changes[0])) return changes[0];
|
||||||
|
let parts = changes[0].toString().split(":");
|
||||||
|
return parts.length > 1 ? parts[1] : changes[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function _outlet(changes: any[]): string {
|
||||||
|
if (!isString(changes[0])) return null;
|
||||||
|
let parts = changes[0].toString().split(":");
|
||||||
|
return parts.length > 1 ? parts[0] : null;
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
import {
|
||||||
|
ComponentFixture,
|
||||||
|
AsyncTestCompleter,
|
||||||
|
TestComponentBuilder,
|
||||||
|
beforeEach,
|
||||||
|
ddescribe,
|
||||||
|
xdescribe,
|
||||||
|
describe,
|
||||||
|
el,
|
||||||
|
expect,
|
||||||
|
iit,
|
||||||
|
inject,
|
||||||
|
beforeEachProviders,
|
||||||
|
it,
|
||||||
|
xit
|
||||||
|
} from 'angular2/testing_internal';
|
||||||
|
|
||||||
|
import {RouteSegment, UrlSegment, Tree} from 'angular2/src/alt_router/segments';
|
||||||
|
import {link} from 'angular2/src/alt_router/link';
|
||||||
|
import {DefaultRouterUrlSerializer} from 'angular2/src/alt_router/router_url_serializer';
|
||||||
|
|
||||||
|
export function main() {
|
||||||
|
describe('link', () => {
|
||||||
|
let parser = new DefaultRouterUrlSerializer();
|
||||||
|
|
||||||
|
it("should return the original tree when given an empty array", () => {
|
||||||
|
let p = parser.parse("/");
|
||||||
|
let t = link(s(p.root), p, []);
|
||||||
|
expect(t).toBe(p);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should support going to root", () => {
|
||||||
|
let p = parser.parse("/");
|
||||||
|
let t = link(s(p.root), p, ["/"]);
|
||||||
|
expect(parser.serialize(t)).toEqual("");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should support positional params", () => {
|
||||||
|
let p = parser.parse("/");
|
||||||
|
let t = link(s(p.root), p, ["/one", 11, "two", 22]);
|
||||||
|
expect(parser.serialize(t)).toEqual("/one/11/two/22");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should preserve route siblings when changing the main route", () => {
|
||||||
|
let p = parser.parse("/a/11/b(c)");
|
||||||
|
let t = link(s(p.root), p, ["/a", 11, 'd']);
|
||||||
|
expect(parser.serialize(t)).toEqual("/a/11/d(aux:c)");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should preserve route siblings when changing a aux route", () => {
|
||||||
|
let p = parser.parse("/a/11/b(c)");
|
||||||
|
let t = link(s(p.root), p, ["/a", 11, 'aux:d']);
|
||||||
|
expect(parser.serialize(t)).toEqual("/a/11/b(aux:d)");
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should update parameters', () => {
|
||||||
|
let p = parser.parse("/a;aa=11");
|
||||||
|
let t = link(s(p.root), p, ["/a", {aa: 22, bb: 33}]);
|
||||||
|
expect(parser.serialize(t)).toEqual("/a;aa=22;bb=33");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function s(u: UrlSegment): RouteSegment {
|
||||||
|
return new RouteSegment([u], {}, null, null, null);
|
||||||
|
}
|
Loading…
Reference in New Issue