Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: router url join is invalid in Windows #4265

Merged
merged 7 commits into from
Apr 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/plugin-router/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 2.0.0

- fix: router path is invalid after using `path.join` function

## 1.9.5

- [fix] support customRouterProps of renderRouter
Expand Down
3 changes: 2 additions & 1 deletion packages/plugin-router/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@types/glob": "^7.1.1",
"@types/history": "^4.7.5",
"@types/node": "^12.12.12",
"path-to-regexp": "^6.2.0",
"typescript": "^4.0.0"
},
"files": [
Expand All @@ -42,4 +43,4 @@
"test": "echo \"Error: run tests from root\" && exit 1"
},
"gitHead": "6bbf8de986f2e6d4820c2dc7f92fa87d917b23f7"
}
}
6 changes: 3 additions & 3 deletions packages/plugin-router/src/runtime/formatRoutes.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import * as React from 'react';
import * as path from 'path';
import * as queryString from 'query-string';
import { IRouterConfig } from '../types';
import joinPath from '../utils/joinPath';

const { useEffect, useState } = React;

export default function formatRoutes(routes: IRouterConfig[], parentPath: string) {
return routes.map((item) => {
if (item.path) {
const joinPath = path.join(parentPath || '', item.path);
item.path = joinPath === '/' ? '/' : joinPath.replace(/\/$/, '');
const routePath = joinPath(parentPath || '', item.path);
item.path = routePath === '/' ? '/' : routePath.replace(/\/$/, '');
}
if (item.children) {
item.children = formatRoutes(item.children, item.path);
Expand Down
77 changes: 77 additions & 0 deletions packages/plugin-router/src/utils/__tests__/joinPath.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { pathToRegexp } from 'path-to-regexp';
import joinPath from '../joinPath';

const joinTests: [string[], string][] = [
[[], ''],
[['', '/'], '/'],
[[' ', '/'], ' /'],
[['', 'foo'], 'foo'],
[['foo', '/bar', 'aa'], 'foo/bar/aa'],
[['', '/foo'], '/foo'],
[['', '', '/foo'], '/foo'],
[['', '', 'foo'], 'foo'],
[['foo', ''], 'foo'],
[['foo/', ''], 'foo/'],
[['foo', '', '/bar'], 'foo/bar'],
[['/'], '/'],
[[' /foo'], ' /foo'],
[[' ', 'foo'], ' /foo'],
[[' ', ''], ' '],
[['/', 'foo'], '/foo'],
[['/', '/foo'], '/foo'],
[['/', '//foo'], '/foo'],
[['/', '', '/foo'], '/foo'],
[['', '/', 'foo'], '/foo'],
[['', '/', '/foo'], '/foo'],

[['/', '/:id'], '/:id'],
[['/user', '/:id'], '/user/:id'],
[['/user', '/:test(\\d+)+'], '/user/:test(\\d+)+']
];

describe('path join', () => {
joinTests.forEach(p => {
test(`input: ${JSON.stringify(p[0])} expected: ${p[1]}`, () => {
const actual = joinPath(...p[0]);
expect(actual).toStrictEqual(p[1]);
});
});

test('will throw Error', () => {
expect(() => joinPath(null)).toThrowError();
});
});

const regexpPathTests: [string[], string, string[] | null][] = [
[['/', '/:id'], '/123', ['/123', '123']],
[['/user', '/:id'], '/user/123', ['/user/123', '123']],
[['/user', '/:id', '/abc'], '/user/123/abc', ['/user/123/abc', '123']],
[['/:uid', '/:id'], '/12345/123', ['/12345/123', '12345', '123']],
[['/login', '/:test(\\d+)+'], '/abc/123/456/789', null],
[['/login', '/:test(\\d+)+'], '/login/123/456/789', ['/login/123/456/789', '123/456/789']],
[['/login', '/:path(abc|xyz)*'], '/login/abc', ['/login/abc', 'abc']],
[['/login', '/:path(abc|xyz)*'], '/login/xyz', ['/login/xyz', 'xyz']],
[['/login', '/:path(abc|xyz)*'], '/login/abc/abc', ['/login/abc/abc', 'abc/abc']],
[['/login', '/:path(abc|xyz)*'], '/login/xxx', null],
[['/login', '/(.*)'], '/login/xxx', ['/login/xxx', 'xxx']],
[['/abc', '/:test((?!login)[^/]+)'], '/abc/xxx', ['/abc/xxx', 'xxx']],
[['/abc', '/:test((?!login)[^/]+)'], '/abc/login', null],
[['/abc', '/user(s)?/:user'], '/abc/user/123', ['/abc/user/123', undefined, '123']],
[['/abc', '/user(s)?/:user'], '/abc/users/123', ['/abc/users/123', 's', '123']],
];

describe('path-to-regexp', () => {
regexpPathTests.forEach(p => {
const [pathJoinArray, input, expected] = p;
test(`pathArray: ${JSON.stringify(pathJoinArray)} input: ${input} expected: ${JSON.stringify(expected)}`, () => {
const re = pathToRegexp(joinPath(...pathJoinArray));
expect(exec(re, input)).toStrictEqual(expected);
});
});
});

function exec(re: RegExp, str: string) {
const match = re.exec(str);

return match && Array.prototype.slice.call(match);
}
33 changes: 33 additions & 0 deletions packages/plugin-router/src/utils/joinPath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Join the route paths.
* @param strArray
* @returns string
*/
function joinPath(...strArray: string[]): string {
if (strArray.length === 0) {
return '';
}
const resultArray = [];
const filterStrArray = strArray.filter(str => str !== '');
filterStrArray.forEach((str, index) => {
if (typeof str !== 'string') {
throw new Error(`Path must be a string. Received ${str}`);
}
let routePath = str;
// Fork from https://github.com/jfromaniello/url-join@4.0.1
if (index > 0) {
routePath = routePath.replace(/^[/]+/, '');
}
if (index < filterStrArray.length - 1) {
// Removing the ending slashes for each component but the last.
routePath = routePath.replace(/[/]+$/, '');
} else {
// For the last component we will combine multiple slashes to a single one.
routePath = routePath.replace(/[/]+$/, '/');
}
resultArray.push(routePath);
});
return resultArray.join('/');
}

export default joinPath;
3 changes: 2 additions & 1 deletion packages/plugin-router/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
},
},
"exclude": [
"templates"
"templates",
"src/utils/__tests__"
]
}