fix(router): add segmentPath to the link DSL
This commit is contained in:
parent
99989f5d3f
commit
4f17dbc721
|
@ -101,17 +101,21 @@ function normalizeCommands(commands: any[]): NormalizedNavigationCommands {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof c === 'object' && c.segmentPath !== undefined) {
|
||||||
|
res.push(c.segmentPath);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(typeof c === 'string')) {
|
if (!(typeof c === 'string')) {
|
||||||
res.push(c);
|
res.push(c);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parts = c.split('/');
|
if (i === 0) {
|
||||||
for (let j = 0; j < parts.length; ++j) {
|
const parts = c.split('/');
|
||||||
let cc = parts[j];
|
for (let j = 0; j < parts.length; ++j) {
|
||||||
|
let cc = parts[j];
|
||||||
|
|
||||||
// first exp is treated in a special way
|
|
||||||
if (i == 0) {
|
|
||||||
if (j == 0 && cc == '.') { // './a'
|
if (j == 0 && cc == '.') { // './a'
|
||||||
// skip it
|
// skip it
|
||||||
} else if (j == 0 && cc == '') { // '/a'
|
} else if (j == 0 && cc == '') { // '/a'
|
||||||
|
@ -121,12 +125,9 @@ function normalizeCommands(commands: any[]): NormalizedNavigationCommands {
|
||||||
} else if (cc != '') {
|
} else if (cc != '') {
|
||||||
res.push(cc);
|
res.push(cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
|
||||||
if (cc != '') {
|
|
||||||
res.push(cc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
res.push(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -220,9 +220,14 @@ export class Router {
|
||||||
* // create /team/33;expand=true/user/11
|
* // create /team/33;expand=true/user/11
|
||||||
* router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]);
|
* router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]);
|
||||||
*
|
*
|
||||||
* // you can collapse static fragments like this
|
* // you can collapse static segments like this (this works only with the first passed-in value):
|
||||||
* router.createUrlTree(['/team/33/user', userId]);
|
* router.createUrlTree(['/team/33/user', userId]);
|
||||||
*
|
*
|
||||||
|
* If the first segment can contain slashes, and you do not want the router to split it, you
|
||||||
|
* can do the following:
|
||||||
|
*
|
||||||
|
* router.createUrlTree([{segmentPath: '/one/two'}]);
|
||||||
|
*
|
||||||
* // create /team/33/(user/11//aux:chat)
|
* // create /team/33/(user/11//aux:chat)
|
||||||
* router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: 'chat'}}]);
|
* router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: 'chat'}}]);
|
||||||
*
|
*
|
||||||
|
|
|
@ -225,19 +225,24 @@ function serializeSegment(segment: UrlSegmentGroup, root: boolean): string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function encode(s: string): string {
|
||||||
|
return encodeURIComponent(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function decode(s: string): string {
|
||||||
|
return decodeURIComponent(s);
|
||||||
|
}
|
||||||
|
|
||||||
export function serializePath(path: UrlSegment): string {
|
export function serializePath(path: UrlSegment): string {
|
||||||
return `${encodeURIComponent(path.path)}${serializeParams(path.parameters)}`;
|
return `${encode(path.path)}${serializeParams(path.parameters)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function serializeParams(params: {[key: string]: string}): string {
|
function serializeParams(params: {[key: string]: string}): string {
|
||||||
return pairs(params)
|
return pairs(params).map(p => `;${encode(p.first)}=${encode(p.second)}`).join('');
|
||||||
.map(p => `;${encodeURIComponent(p.first)}=${encodeURIComponent(p.second)}`)
|
|
||||||
.join('');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function serializeQueryParams(params: {[key: string]: string}): string {
|
function serializeQueryParams(params: {[key: string]: string}): string {
|
||||||
const strs =
|
const strs = pairs(params).map(p => `${encode(p.first)}=${encode(p.second)}`);
|
||||||
pairs(params).map(p => `${encodeURIComponent(p.first)}=${encodeURIComponent(p.second)}`);
|
|
||||||
return strs.length > 0 ? `?${strs.join("&")}` : '';
|
return strs.length > 0 ? `?${strs.join("&")}` : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +353,7 @@ class UrlParser {
|
||||||
if (this.peekStartsWith(';')) {
|
if (this.peekStartsWith(';')) {
|
||||||
matrixParams = this.parseMatrixParams();
|
matrixParams = this.parseMatrixParams();
|
||||||
}
|
}
|
||||||
return new UrlSegment(decodeURIComponent(path), matrixParams);
|
return new UrlSegment(decode(path), matrixParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseQueryParams(): {[key: string]: any} {
|
parseQueryParams(): {[key: string]: any} {
|
||||||
|
@ -366,7 +371,7 @@ class UrlParser {
|
||||||
|
|
||||||
parseFragment(): string {
|
parseFragment(): string {
|
||||||
if (this.peekStartsWith('#')) {
|
if (this.peekStartsWith('#')) {
|
||||||
return decodeURIComponent(this.remaining.substring(1));
|
return decode(this.remaining.substring(1));
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -397,7 +402,7 @@ class UrlParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
params[decodeURIComponent(key)] = decodeURIComponent(value);
|
params[decode(key)] = decode(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseQueryParam(params: {[key: string]: any}): void {
|
parseQueryParam(params: {[key: string]: any}): void {
|
||||||
|
@ -415,7 +420,7 @@ class UrlParser {
|
||||||
this.capture(value);
|
this.capture(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
params[decodeURIComponent(key)] = decodeURIComponent(value);
|
params[decode(key)] = decode(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseParens(allowPrimary: boolean): {[key: string]: UrlSegmentGroup} {
|
parseParens(allowPrimary: boolean): {[key: string]: UrlSegmentGroup} {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {ActivatedRoute, ActivatedRouteSnapshot, advanceActivatedRoute} from '../
|
||||||
import {PRIMARY_OUTLET, Params} from '../src/shared';
|
import {PRIMARY_OUTLET, Params} from '../src/shared';
|
||||||
import {DefaultUrlSerializer, UrlSegment, UrlSegmentGroup, UrlTree} from '../src/url_tree';
|
import {DefaultUrlSerializer, UrlSegment, UrlSegmentGroup, UrlTree} from '../src/url_tree';
|
||||||
|
|
||||||
describe('createUrlTree', () => {
|
fdescribe('createUrlTree', () => {
|
||||||
const serializer = new DefaultUrlSerializer();
|
const serializer = new DefaultUrlSerializer();
|
||||||
|
|
||||||
it('should navigate to the root', () => {
|
it('should navigate to the root', () => {
|
||||||
|
@ -42,6 +42,12 @@ describe('createUrlTree', () => {
|
||||||
expect(params[1].path).toEqual('11');
|
expect(params[1].path).toEqual('11');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support first segments contaings slashes', () => {
|
||||||
|
const p = serializer.parse('/');
|
||||||
|
const t = createRoot(p, [{segmentPath: '/one'}, 'two/three']);
|
||||||
|
expect(serializer.serialize(t)).toEqual('/%2Fone/two%2Fthree');
|
||||||
|
});
|
||||||
|
|
||||||
it('should preserve secondary segments', () => {
|
it('should preserve secondary segments', () => {
|
||||||
const p = serializer.parse('/a/11/b(right:c)');
|
const p = serializer.parse('/a/11/b(right:c)');
|
||||||
const t = createRoot(p, ['/a', 11, 'd']);
|
const t = createRoot(p, ['/a', 11, 'd']);
|
||||||
|
@ -98,7 +104,7 @@ describe('createUrlTree', () => {
|
||||||
|
|
||||||
it('should create matrix parameters together with other segments', () => {
|
it('should create matrix parameters together with other segments', () => {
|
||||||
const p = serializer.parse('/a');
|
const p = serializer.parse('/a');
|
||||||
const t = createRoot(p, ['/a', '/b', {aa: 22, bb: 33}]);
|
const t = createRoot(p, ['/a', 'b', {aa: 22, bb: 33}]);
|
||||||
expect(serializer.serialize(t)).toEqual('/a/b;aa=22;bb=33');
|
expect(serializer.serialize(t)).toEqual('/a/b;aa=22;bb=33');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {PRIMARY_OUTLET} from '../src/shared';
|
import {PRIMARY_OUTLET} from '../src/shared';
|
||||||
import {DefaultUrlSerializer, UrlSegmentGroup, serializePath} from '../src/url_tree';
|
import {DefaultUrlSerializer, UrlSegmentGroup, decode, encode, serializePath} from '../src/url_tree';
|
||||||
|
|
||||||
describe('url serializer', () => {
|
describe('url serializer', () => {
|
||||||
const url = new DefaultUrlSerializer();
|
const url = new DefaultUrlSerializer();
|
||||||
|
@ -181,7 +181,7 @@ describe('url serializer', () => {
|
||||||
describe('encoding/decoding', () => {
|
describe('encoding/decoding', () => {
|
||||||
it('should encode/decode path segments and parameters', () => {
|
it('should encode/decode path segments and parameters', () => {
|
||||||
const u =
|
const u =
|
||||||
`/${encodeURIComponent("one two")};${encodeURIComponent("p 1")}=${encodeURIComponent("v 1")};${encodeURIComponent("p 2")}=${encodeURIComponent("v 2")}`;
|
`/${encode("one two")};${encode("p 1")}=${encode("v 1")};${encode("p 2")}=${encode("v 2")}`;
|
||||||
const tree = url.parse(u);
|
const tree = url.parse(u);
|
||||||
|
|
||||||
expect(tree.root.children[PRIMARY_OUTLET].segments[0].path).toEqual('one two');
|
expect(tree.root.children[PRIMARY_OUTLET].segments[0].path).toEqual('one two');
|
||||||
|
@ -190,9 +190,16 @@ describe('url serializer', () => {
|
||||||
expect(url.serialize(tree)).toEqual(u);
|
expect(url.serialize(tree)).toEqual(u);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should encode/decode "slash" in path segments and parameters', () => {
|
||||||
|
const u = `/${encode("one/two")};${encode("p/1")}=${encode("v/1")}/three`;
|
||||||
|
const tree = url.parse(u);
|
||||||
|
expect(tree.root.children[PRIMARY_OUTLET].segments[0].path).toEqual('one/two');
|
||||||
|
expect(tree.root.children[PRIMARY_OUTLET].segments[0].parameters).toEqual({['p/1']: 'v/1'});
|
||||||
|
expect(url.serialize(tree)).toEqual(u);
|
||||||
|
});
|
||||||
|
|
||||||
it('should encode/decode query params', () => {
|
it('should encode/decode query params', () => {
|
||||||
const u =
|
const u = `/one?${encode("p 1")}=${encode("v 1")}&${encode("p 2")}=${encode("v 2")}`;
|
||||||
`/one?${encodeURIComponent("p 1")}=${encodeURIComponent("v 1")}&${encodeURIComponent("p 2")}=${encodeURIComponent("v 2")}`;
|
|
||||||
const tree = url.parse(u);
|
const tree = url.parse(u);
|
||||||
|
|
||||||
expect(tree.queryParams).toEqual({['p 1']: 'v 1', ['p 2']: 'v 2'});
|
expect(tree.queryParams).toEqual({['p 1']: 'v 1', ['p 2']: 'v 2'});
|
||||||
|
@ -200,7 +207,7 @@ describe('url serializer', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should encode/decode fragment', () => {
|
it('should encode/decode fragment', () => {
|
||||||
const u = `/one#${encodeURIComponent("one two")}`;
|
const u = `/one#${encode("one two")}`;
|
||||||
const tree = url.parse(u);
|
const tree = url.parse(u);
|
||||||
|
|
||||||
expect(tree.fragment).toEqual('one two');
|
expect(tree.fragment).toEqual('one two');
|
||||||
|
|
Loading…
Reference in New Issue