feat(router): serialize outlet names into the url
This commit is contained in:
parent
10d38cbb72
commit
a9e773b47b
|
@ -1,4 +1,5 @@
|
|||
import { UrlTree, UrlSegment } from './url_tree';
|
||||
import { PRIMARY_OUTLET } from './shared';
|
||||
import { rootNode, TreeNode } from './utils/tree';
|
||||
|
||||
/**
|
||||
|
@ -54,7 +55,8 @@ function serializeChildren(node: TreeNode<UrlSegment>): string {
|
|||
}
|
||||
|
||||
export function serializeSegment(segment: UrlSegment): string {
|
||||
return `${segment.path}${serializeParams(segment.parameters)}`;
|
||||
const outlet = segment.outlet === PRIMARY_OUTLET ? '' : `${segment.outlet}:`;
|
||||
return `${outlet}${segment.path}${serializeParams(segment.parameters)}`;
|
||||
}
|
||||
|
||||
function serializeParams(params: {[key: string]: string}): string {
|
||||
|
@ -105,41 +107,58 @@ class UrlParser {
|
|||
|
||||
parseRootSegment(): TreeNode<UrlSegment> {
|
||||
if (this.remaining == '' || this.remaining == '/') {
|
||||
return new TreeNode<UrlSegment>(new UrlSegment('', {}), []);
|
||||
return new TreeNode<UrlSegment>(new UrlSegment('', {}, PRIMARY_OUTLET), []);
|
||||
} else {
|
||||
let segments = this.parseSegments();
|
||||
return new TreeNode<UrlSegment>(new UrlSegment('', {}), segments);
|
||||
const segments = this.parseSegments(false);
|
||||
return new TreeNode<UrlSegment>(new UrlSegment('', {}, PRIMARY_OUTLET), segments);
|
||||
}
|
||||
}
|
||||
|
||||
parseSegments(): TreeNode<UrlSegment>[] {
|
||||
parseSegments(hasOutletName: boolean): TreeNode<UrlSegment>[] {
|
||||
if (this.remaining.length == 0) {
|
||||
return [];
|
||||
}
|
||||
if (this.peekStartsWith('/')) {
|
||||
this.capture('/');
|
||||
}
|
||||
var path = matchUrlSegment(this.remaining);
|
||||
let path = matchUrlSegment(this.remaining);
|
||||
this.capture(path);
|
||||
|
||||
var matrixParams: {[key: string]: any} = {};
|
||||
let outletName;
|
||||
if (hasOutletName) {
|
||||
if (path.indexOf(":") === -1) {
|
||||
throw new Error("Not outlet name is provided");
|
||||
}
|
||||
if (path.indexOf(":") > -1 && hasOutletName) {
|
||||
let parts = path.split(":");
|
||||
outletName = parts[0];
|
||||
path = parts[1];
|
||||
}
|
||||
} else {
|
||||
if (path.indexOf(":") > -1) {
|
||||
throw new Error("Not outlet name is allowed");
|
||||
}
|
||||
outletName = PRIMARY_OUTLET;
|
||||
}
|
||||
|
||||
let matrixParams: {[key: string]: any} = {};
|
||||
if (this.peekStartsWith(';')) {
|
||||
matrixParams = this.parseMatrixParams();
|
||||
}
|
||||
|
||||
var secondary = [];
|
||||
let secondary = [];
|
||||
if (this.peekStartsWith('(')) {
|
||||
secondary = this.parseSecondarySegments();
|
||||
}
|
||||
|
||||
var children: TreeNode<UrlSegment>[] = [];
|
||||
let children: TreeNode<UrlSegment>[] = [];
|
||||
if (this.peekStartsWith('/') && !this.peekStartsWith('//')) {
|
||||
this.capture('/');
|
||||
children = this.parseSegments();
|
||||
children = this.parseSegments(false);
|
||||
}
|
||||
|
||||
let segment = new UrlSegment(path, matrixParams);
|
||||
let node = new TreeNode<UrlSegment>(segment, children);
|
||||
const segment = new UrlSegment(path, matrixParams, outletName);
|
||||
const node = new TreeNode<UrlSegment>(segment, children);
|
||||
return [node].concat(secondary);
|
||||
}
|
||||
|
||||
|
@ -215,7 +234,7 @@ class UrlParser {
|
|||
this.capture('(');
|
||||
|
||||
while (!this.peekStartsWith(')') && this.remaining.length > 0) {
|
||||
segments = segments.concat(this.parseSegments());
|
||||
segments = segments.concat(this.parseSegments(true));
|
||||
if (this.peekStartsWith('//')) {
|
||||
this.capture('//');
|
||||
}
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import { Tree, TreeNode } from './utils/tree';
|
||||
import { shallowEqual } from './utils/collection';
|
||||
import { PRIMARY_OUTLET } from './shared';
|
||||
|
||||
export function createEmptyUrlTree() {
|
||||
return new UrlTree(new TreeNode<UrlSegment>(new UrlSegment("", {}, PRIMARY_OUTLET), []), {}, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A URL in the tree form.
|
||||
|
@ -11,17 +16,18 @@ export class UrlTree extends Tree<UrlSegment> {
|
|||
}
|
||||
|
||||
export class UrlSegment {
|
||||
constructor(public path: string, public parameters: {[key: string]: string}) {}
|
||||
constructor(public path: string, public parameters: {[key: string]: string}, public outlet: string) {}
|
||||
|
||||
toString() {
|
||||
let params = [];
|
||||
const params = [];
|
||||
for (let prop in this.parameters) {
|
||||
if (this.parameters.hasOwnProperty(prop)) {
|
||||
params.push(`${prop}=${this.parameters[prop]}`);
|
||||
}
|
||||
}
|
||||
const paramsString = params.length > 0 ? `(${params.join(',')})` : '';
|
||||
return `${this.path}${paramsString}`;
|
||||
const outlet = this.outlet === PRIMARY_OUTLET ? '' : `${this.outlet}:`;
|
||||
return `${outlet}${this.path}${paramsString}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,60 +2,61 @@ import {DefaultUrlSerializer, serializeSegment} from '../src/url_serializer';
|
|||
import {UrlSegment} from '../src/url_tree';
|
||||
|
||||
describe('url serializer', () => {
|
||||
let url = new DefaultUrlSerializer();
|
||||
const url = new DefaultUrlSerializer();
|
||||
|
||||
it('should parse the root url', () => {
|
||||
let tree = url.parse("/");
|
||||
const tree = url.parse("/");
|
||||
expectSegment(tree.root, "");
|
||||
expect(url.serialize(tree)).toEqual("");
|
||||
});
|
||||
|
||||
it('should parse non-empty urls', () => {
|
||||
let tree = url.parse("one/two");
|
||||
let one = tree.firstChild(tree.root);
|
||||
const tree = url.parse("one/two");
|
||||
const one = tree.firstChild(tree.root);
|
||||
|
||||
expectSegment(one, "one");
|
||||
expectSegment(tree.firstChild(<any>one), "two");
|
||||
expect(url.serialize(tree)).toEqual("/one/two");
|
||||
});
|
||||
|
||||
it("should parse multiple secondary segments", () => {
|
||||
let tree = url.parse("/one/two(three//four)/five");
|
||||
let c = tree.children(<any>tree.firstChild(tree.root));
|
||||
const tree = url.parse("/one/two(left:three//right:four)/five");
|
||||
const c = tree.children(<any>tree.firstChild(tree.root));
|
||||
|
||||
expectSegment(c[0], "two");
|
||||
expectSegment(c[1], "three");
|
||||
expectSegment(c[2], "four");
|
||||
expectSegment(c[1], "left:three");
|
||||
expectSegment(c[2], "right:four");
|
||||
|
||||
expectSegment(tree.firstChild(c[0]), "five");
|
||||
|
||||
expect(url.serialize(tree)).toEqual("/one/two(three//four)/five");
|
||||
expect(url.serialize(tree)).toEqual("/one/two(left:three//right:four)/five");
|
||||
});
|
||||
|
||||
it("should parse secondary segments that have secondary segments", () => {
|
||||
let tree = url.parse("/one(/two(/three))");
|
||||
let c = tree.children(tree.root);
|
||||
const tree = url.parse("/one(left:two(right:three))");
|
||||
const c = tree.children(tree.root);
|
||||
|
||||
expectSegment(c[0], "one");
|
||||
expectSegment(c[1], "two");
|
||||
expectSegment(c[2], "three");
|
||||
expectSegment(c[1], "left:two");
|
||||
expectSegment(c[2], "right:three");
|
||||
|
||||
expect(url.serialize(tree)).toEqual("/one(two//three)");
|
||||
expect(url.serialize(tree)).toEqual("/one(left:two//right:three)");
|
||||
});
|
||||
|
||||
it("should parse secondary segments that have children", () => {
|
||||
let tree = url.parse("/one(/two/three)");
|
||||
let c = tree.children(tree.root);
|
||||
const tree = url.parse("/one(left:two/three)");
|
||||
const c = tree.children(tree.root);
|
||||
|
||||
expectSegment(c[0], "one");
|
||||
expectSegment(c[1], "two");
|
||||
expectSegment(c[1], "left:two");
|
||||
expectSegment(tree.firstChild(c[1]), "three");
|
||||
|
||||
expect(url.serialize(tree)).toEqual("/one(two/three)");
|
||||
expect(url.serialize(tree)).toEqual("/one(left:two/three)");
|
||||
});
|
||||
|
||||
it("should parse an empty secondary segment group", () => {
|
||||
let tree = url.parse("/one()");
|
||||
let c = tree.children(tree.root);
|
||||
const tree = url.parse("/one()");
|
||||
const c = tree.children(tree.root);
|
||||
|
||||
expectSegment(c[0], "one");
|
||||
expect(tree.children(c[0]).length).toEqual(0);
|
||||
|
@ -64,48 +65,48 @@ describe('url serializer', () => {
|
|||
});
|
||||
|
||||
it("should parse key-value matrix params", () => {
|
||||
let tree = url.parse("/one;a=11a;b=11b(two;c=22//three;d=33)");
|
||||
let c = tree.children(tree.root);
|
||||
const tree = url.parse("/one;a=11a;b=11b(left:two;c=22//right:three;d=33)");
|
||||
const c = tree.children(tree.root);
|
||||
|
||||
expectSegment(c[0], "one;a=11a;b=11b");
|
||||
expectSegment(c[1], "two;c=22");
|
||||
expectSegment(c[2], "three;d=33");
|
||||
expectSegment(c[1], "left:two;c=22");
|
||||
expectSegment(c[2], "right:three;d=33");
|
||||
|
||||
expect(url.serialize(tree)).toEqual("/one;a=11a;b=11b(two;c=22//three;d=33)");
|
||||
expect(url.serialize(tree)).toEqual("/one;a=11a;b=11b(left:two;c=22//right:three;d=33)");
|
||||
});
|
||||
|
||||
it("should parse key only matrix params", () => {
|
||||
let tree = url.parse("/one;a");
|
||||
const tree = url.parse("/one;a");
|
||||
|
||||
let c = tree.firstChild(tree.root);
|
||||
const c = tree.firstChild(tree.root);
|
||||
expectSegment(c, "one;a=true");
|
||||
|
||||
expect(url.serialize(tree)).toEqual("/one;a=true");
|
||||
});
|
||||
|
||||
it("should parse query params", () => {
|
||||
let tree = url.parse("/one?a=1&b=2");
|
||||
const tree = url.parse("/one?a=1&b=2");
|
||||
expect(tree.queryParameters).toEqual({a: '1', b: '2'});
|
||||
});
|
||||
|
||||
it("should parse key only query params", () => {
|
||||
let tree = url.parse("/one?a");
|
||||
const tree = url.parse("/one?a");
|
||||
expect(tree.queryParameters).toEqual({a: 'true'});
|
||||
});
|
||||
|
||||
it("should serializer query params", () => {
|
||||
let tree = url.parse("/one?a");
|
||||
const tree = url.parse("/one?a");
|
||||
expect(url.serialize(tree)).toEqual("/one?a=true");
|
||||
});
|
||||
|
||||
it("should parse fragment", () => {
|
||||
let tree = url.parse("/one#two");
|
||||
const tree = url.parse("/one#two");
|
||||
expect(tree.fragment).toEqual("two");
|
||||
expect(url.serialize(tree)).toEqual("/one#two");
|
||||
});
|
||||
|
||||
it("should parse empty fragment", () => {
|
||||
let tree = url.parse("/one#");
|
||||
const tree = url.parse("/one#");
|
||||
expect(tree.fragment).toEqual("");
|
||||
expect(url.serialize(tree)).toEqual("/one#");
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue