angular-cn/modules/@angular/router/src/url_tree.ts

133 lines
4.5 KiB
TypeScript
Raw Normal View History

2016-06-08 14:13:41 -04:00
import {PRIMARY_OUTLET} from './shared';
2016-06-14 17:55:59 -04:00
import {DefaultUrlSerializer, serializePath, serializePaths} from './url_serializer';
import {forEach, shallowEqual} from './utils/collection';
export function createEmptyUrlTree() {
2016-06-14 17:55:59 -04:00
return new UrlTree(new UrlSegment([], {}), {}, null);
}
2016-05-21 20:35:55 -04:00
export function containsTree(container: UrlTree, containee: UrlTree, exact: boolean): boolean {
if (exact) {
return equalSegments(container.root, containee.root);
} else {
return containsSegment(container.root, containee.root);
}
}
function equalSegments(container: UrlSegment, containee: UrlSegment): boolean {
if (!equalPath(container.pathsWithParams, containee.pathsWithParams)) return false;
if (Object.keys(container.children).length !== Object.keys(containee.children).length)
return false;
for (let c in containee.children) {
if (!container.children[c]) return false;
if (!equalSegments(container.children[c], containee.children[c])) return false;
}
return true;
}
function containsSegment(container: UrlSegment, containee: UrlSegment): boolean {
return containsSegmentHelper(container, containee, containee.pathsWithParams);
}
function containsSegmentHelper(
container: UrlSegment, containee: UrlSegment, containeePaths: UrlPathWithParams[]): boolean {
if (container.pathsWithParams.length > containeePaths.length) {
const current = container.pathsWithParams.slice(0, containeePaths.length);
if (!equalPath(current, containeePaths)) return false;
if (Object.keys(containee.children).length > 0) return false;
return true;
} else if (container.pathsWithParams.length === containeePaths.length) {
if (!equalPath(container.pathsWithParams, containeePaths)) return false;
for (let c in containee.children) {
if (!container.children[c]) return false;
if (!containsSegment(container.children[c], containee.children[c])) return false;
}
return true;
} else {
const current = containeePaths.slice(0, container.pathsWithParams.length);
const next = containeePaths.slice(container.pathsWithParams.length);
if (!equalPath(container.pathsWithParams, current)) return false;
return containsSegmentHelper(container.children[PRIMARY_OUTLET], containee, next);
}
}
2016-05-24 16:41:37 -04:00
/**
* A URL in the tree form.
*/
2016-06-14 17:55:59 -04:00
export class UrlTree {
/**
* @internal
*/
2016-06-08 14:13:41 -04:00
constructor(
2016-06-14 17:55:59 -04:00
public root: UrlSegment, public queryParams: {[key: string]: string},
public fragment: string) {}
2016-06-09 17:33:09 -04:00
toString(): string { return new DefaultUrlSerializer().serialize(this); }
2016-05-21 20:35:55 -04:00
}
export class UrlSegment {
public parent: UrlSegment = null;
2016-06-08 14:13:41 -04:00
constructor(
2016-06-14 17:55:59 -04:00
public pathsWithParams: UrlPathWithParams[], public children: {[key: string]: UrlSegment}) {
forEach(children, (v, k) => v.parent = this);
}
2016-05-23 19:14:23 -04:00
2016-06-14 17:55:59 -04:00
toString(): string { return serializePaths(this); }
2016-05-23 19:14:23 -04:00
}
2016-06-14 17:55:59 -04:00
export class UrlPathWithParams {
constructor(public path: string, public parameters: {[key: string]: string}) {}
toString(): string { return serializePath(this); }
}
export function equalPathsWithParams(a: UrlPathWithParams[], b: UrlPathWithParams[]): boolean {
2016-05-23 19:14:23 -04:00
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; ++i) {
if (a[i].path !== b[i].path) return false;
if (!shallowEqual(a[i].parameters, b[i].parameters)) return false;
}
return true;
}
export function equalPath(a: UrlPathWithParams[], b: UrlPathWithParams[]): boolean {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; ++i) {
if (a[i].path !== b[i].path) return false;
2016-05-23 19:14:23 -04:00
}
return true;
}
2016-06-14 17:55:59 -04:00
export function mapChildren(segment: UrlSegment, fn: (v: UrlSegment, k: string) => UrlSegment):
{[name: string]: UrlSegment} {
const newChildren: {[name: string]: UrlSegment} = {};
2016-06-14 17:55:59 -04:00
forEach(segment.children, (child, childOutlet) => {
if (childOutlet === PRIMARY_OUTLET) {
newChildren[childOutlet] = fn(child, childOutlet);
}
});
forEach(segment.children, (child, childOutlet) => {
if (childOutlet !== PRIMARY_OUTLET) {
newChildren[childOutlet] = fn(child, childOutlet);
}
});
return newChildren;
}
export function mapChildrenIntoArray<T>(
segment: UrlSegment, fn: (v: UrlSegment, k: string) => T[]): T[] {
let res = [];
forEach(segment.children, (child, childOutlet) => {
if (childOutlet === PRIMARY_OUTLET) {
res = res.concat(fn(child, childOutlet));
}
});
forEach(segment.children, (child, childOutlet) => {
if (childOutlet !== PRIMARY_OUTLET) {
res = res.concat(fn(child, childOutlet));
}
});
return res;
}