Skip to content

Commit 8f15fa6

Browse files
committed
split
1 parent 2bd0c5b commit 8f15fa6

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import * as assert from 'node:assert/strict';
2+
import { describe, it } from 'node:test';
3+
4+
import { split } from './split.ts';
5+
6+
describe('split', () => {
7+
it('splits route patterns into protocol, hostname, pathname, search', () => {
8+
const cases: Array<[string, ReturnType<typeof split>]> = [
9+
[
10+
'http(s)://(*host.:sub.)remix.run/products(/:id/v:version)/*?q=1',
11+
{
12+
protocol: 'http(s)',
13+
hostname: '(*host.:sub.)remix.run',
14+
pathname: 'products(/:id/v:version)/*',
15+
search: 'q=1',
16+
},
17+
],
18+
19+
// protocol + ...
20+
['http://host.com', { protocol: 'http', hostname: 'host.com' }],
21+
[
22+
'http://host.com/path/:id',
23+
{ protocol: 'http', hostname: 'host.com', pathname: 'path/:id' },
24+
],
25+
['http://host.com?q=1', { protocol: 'http', hostname: 'host.com', search: 'q=1' }],
26+
[
27+
'http://host.com/path/:id?q=1',
28+
{
29+
protocol: 'http',
30+
hostname: 'host.com',
31+
pathname: 'path/:id',
32+
search: 'q=1',
33+
},
34+
],
35+
36+
// hostname + ...
37+
['://host.com', { hostname: 'host.com' }],
38+
['://host.com/path/:id', { hostname: 'host.com', pathname: 'path/:id' }],
39+
['://host.com?q=1', { hostname: 'host.com', search: 'q=1' }],
40+
['://host.com/path/:id?q=1', { hostname: 'host.com', pathname: 'path/:id', search: 'q=1' }],
41+
42+
// pathname + ...
43+
['path/:id', { pathname: 'path/:id' }],
44+
['path/:id?q=1', { pathname: 'path/:id', search: 'q=1' }],
45+
46+
// search + ...
47+
['?q=1', { search: 'q=1' }],
48+
];
49+
for (const [input, expected] of cases) {
50+
assert.deepStrictEqual(split(input), expected);
51+
}
52+
});
53+
});
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
export function split(source: string) {
2+
const result: {
3+
protocol?: string;
4+
hostname?: string;
5+
pathname?: string;
6+
search?: string;
7+
} = {};
8+
9+
// search
10+
const searchStart = source.indexOf('?');
11+
if (searchStart !== -1) {
12+
result.search = source.slice(searchStart + 1);
13+
source = source.slice(0, searchStart);
14+
}
15+
16+
let index = 0;
17+
const solidus = source.indexOf('://');
18+
if (solidus !== -1) {
19+
// protocol
20+
if (solidus !== 0) {
21+
result.protocol = source.slice(0, solidus);
22+
}
23+
index = solidus + 3;
24+
25+
// hostname
26+
const hostnameEnd = source.indexOf('/', index);
27+
if (hostnameEnd === -1) {
28+
result.hostname = source.slice(index, source.length);
29+
return result;
30+
}
31+
result.hostname = source.slice(index, hostnameEnd);
32+
index = hostnameEnd + 1;
33+
}
34+
35+
// pathname
36+
if (index !== source.length) {
37+
result.pathname = source.slice(index);
38+
}
39+
40+
return result;
41+
}

0 commit comments

Comments
 (0)