url-operator 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/lib/decode.js.map +1 -1
- package/lib/encode.js +21 -1
- package/lib/encode.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/set-host.js +1 -0
- package/lib/set-host.js.map +1 -1
- package/lib/set-hostname.d.ts +1 -0
- package/lib/set-hostname.js +6 -0
- package/lib/set-hostname.js.map +1 -0
- package/lib/set-protocol.js +2 -2
- package/lib/set-protocol.js.map +1 -1
- package/package.json +3 -2
- package/src/append-pathname.ts +21 -0
- package/src/append-search-param.ts +13 -0
- package/src/decode.ts +4 -0
- package/src/encode.ts +32 -0
- package/src/index.ts +15 -0
- package/src/set-hash.ts +7 -0
- package/src/set-host.ts +8 -0
- package/src/set-hostname.ts +7 -0
- package/src/set-password.ts +7 -0
- package/src/set-pathname.ts +7 -0
- package/src/set-port.ts +7 -0
- package/src/set-protocol.ts +23 -0
- package/src/set-search-param.ts +13 -0
- package/src/set-search-params.ts +14 -0
- package/src/set-search.ts +7 -0
- package/src/set-username.ts +7 -0
package/README.md
CHANGED
|
@@ -31,6 +31,11 @@ function setPassword(url: URL, password: string): URL
|
|
|
31
31
|
function setHost(url: URL, host: string): URL
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
### setHostname
|
|
35
|
+
```ts
|
|
36
|
+
function setHostname(url: URL, hostname: string): URL
|
|
37
|
+
```
|
|
38
|
+
|
|
34
39
|
### setPort
|
|
35
40
|
```ts
|
|
36
41
|
function setPort(url: URL, port: number): URL
|
package/lib/decode.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decode.js","sourceRoot":"","sources":["../src/decode.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"decode.js","sourceRoot":"","sources":["../src/decode.ts"],"names":[],"mappings":"AACA,MAAM,UAAU,MAAM,CAAC,GAAW;IAChC,OAAO,SAAS,CAAC,GAAG,CAAC,CAAA;AACvB,CAAC"}
|
package/lib/encode.js
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
|
+
import { decode } from './decode.js';
|
|
1
2
|
export function encode(url) {
|
|
2
|
-
|
|
3
|
+
const decodedURL = decode(url);
|
|
4
|
+
const encodedURLParts = [];
|
|
5
|
+
const re = /%[A-F0-9]{2}/gi;
|
|
6
|
+
let result;
|
|
7
|
+
let lastMatchedEndIndex = 0;
|
|
8
|
+
while (result = re.exec(decodedURL), result) {
|
|
9
|
+
const matched = result[0];
|
|
10
|
+
const matchedStartIndex = result.index;
|
|
11
|
+
const matchedEndIndex = matchedStartIndex
|
|
12
|
+
+ matched.length;
|
|
13
|
+
const rawPart = decodedURL.slice(lastMatchedEndIndex, matchedStartIndex);
|
|
14
|
+
encodedURLParts.push(encodeURI(rawPart));
|
|
15
|
+
encodedURLParts.push(matched);
|
|
16
|
+
lastMatchedEndIndex = matchedEndIndex;
|
|
17
|
+
}
|
|
18
|
+
if (lastMatchedEndIndex < decodedURL.length) {
|
|
19
|
+
const rawPart = decodedURL.slice(lastMatchedEndIndex, decodedURL.length);
|
|
20
|
+
encodedURLParts.push(encodeURI(rawPart));
|
|
21
|
+
}
|
|
22
|
+
return encodedURLParts.join('');
|
|
3
23
|
}
|
|
4
24
|
//# sourceMappingURL=encode.js.map
|
package/lib/encode.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encode.js","sourceRoot":"","sources":["../src/encode.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,MAAM,CAAC,GAAW;IAChC,OAAO,
|
|
1
|
+
{"version":3,"file":"encode.js","sourceRoot":"","sources":["../src/encode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGpC,MAAM,UAAU,MAAM,CAAC,GAAW;IAChC,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;IAE9B,MAAM,eAAe,GAAa,EAAE,CAAA;IAEpC,MAAM,EAAE,GAAG,gBAAgB,CAAA;IAC3B,IAAI,MAA8B,CAAA;IAClC,IAAI,mBAAmB,GAAG,CAAC,CAAA;IAC3B,OAAO,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE;QAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;QACzB,MAAM,iBAAiB,GAAG,MAAM,CAAC,KAAK,CAAA;QACtC,MAAM,eAAe,GAAG,iBAAiB;cACjB,OAAO,CAAC,MAAM,CAAA;QAEtC,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAAA;QACxE,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;QAExC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAE7B,mBAAmB,GAAG,eAAe,CAAA;KACtC;IAED,IAAI,mBAAmB,GAAG,UAAU,CAAC,MAAM,EAAE;QAC3C,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,mBAAmB,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;QACxE,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;KACzC;IAED,OAAO,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AACjC,CAAC"}
|
package/lib/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './set-protocol.js';
|
|
|
2
2
|
export * from './set-username.js';
|
|
3
3
|
export * from './set-password.js';
|
|
4
4
|
export * from './set-host.js';
|
|
5
|
+
export * from './set-hostname.js';
|
|
5
6
|
export * from './set-port.js';
|
|
6
7
|
export * from './set-pathname.js';
|
|
7
8
|
export * from './append-pathname.js';
|
package/lib/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export * from './set-protocol.js';
|
|
|
2
2
|
export * from './set-username.js';
|
|
3
3
|
export * from './set-password.js';
|
|
4
4
|
export * from './set-host.js';
|
|
5
|
+
export * from './set-hostname.js';
|
|
5
6
|
export * from './set-port.js';
|
|
6
7
|
export * from './set-pathname.js';
|
|
7
8
|
export * from './append-pathname.js';
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA"}
|
package/lib/set-host.js
CHANGED
package/lib/set-host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set-host.js","sourceRoot":"","sources":["../src/set-host.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,OAAO,CAAC,GAAQ,EAAE,IAAY;IAC5C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IAE3B,MAAM,CAAC,IAAI,GAAG,IAAI,CAAA;IAElB,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
1
|
+
{"version":3,"file":"set-host.js","sourceRoot":"","sources":["../src/set-host.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,OAAO,CAAC,GAAQ,EAAE,IAAY;IAC5C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IAE3B,MAAM,CAAC,IAAI,GAAG,EAAE,CAAA;IAChB,MAAM,CAAC,IAAI,GAAG,IAAI,CAAA;IAElB,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function setHostname(url: URL, hostname: string): URL;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-hostname.js","sourceRoot":"","sources":["../src/set-hostname.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,GAAQ,EAAE,QAAgB;IACpD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IAE3B,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAE1B,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/lib/set-protocol.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export function setProtocol(url, protocol) {
|
|
2
2
|
const oldURL = new URL(url);
|
|
3
|
-
const newURL = new URL(oldURL.href.replace(
|
|
3
|
+
const newURL = new URL(oldURL.href.replace(/^\S+:/, protocol.endsWith(':')
|
|
4
4
|
? protocol
|
|
5
|
-
: `${protocol}
|
|
5
|
+
: `${protocol}:`));
|
|
6
6
|
return newURL;
|
|
7
7
|
}
|
|
8
8
|
//# sourceMappingURL=set-protocol.js.map
|
package/lib/set-protocol.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set-protocol.js","sourceRoot":"","sources":["../src/set-protocol.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,GAAQ,EAAE,QAAgB;IACpD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"set-protocol.js","sourceRoot":"","sources":["../src/set-protocol.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,WAAW,CAAC,GAAQ,EAAE,QAAgB;IACpD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IAW3B,MAAM,MAAM,GAAG,IAAI,GAAG,CACpB,MAAM,CAAC,IAAI,CAAC,OAAO,CACjB,OAAO,EACP,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QACtB,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,GAAG,QAAQ,GAAG,CACjB,CACF,CAAA;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { go } from '@blackglory/prelude'
|
|
2
|
+
|
|
3
|
+
export function appendPathname(url: URL, pathname: string): URL {
|
|
4
|
+
const baseURL = go(() => {
|
|
5
|
+
const baseURL = new URL(url)
|
|
6
|
+
if (!baseURL.pathname.endsWith('/')) {
|
|
7
|
+
baseURL.pathname = `${baseURL.pathname}/`
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return baseURL
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
const newURL = new URL(
|
|
14
|
+
pathname.replace(/^\/*/, '')
|
|
15
|
+
, baseURL
|
|
16
|
+
)
|
|
17
|
+
newURL.search = baseURL.search
|
|
18
|
+
newURL.hash = baseURL.hash
|
|
19
|
+
|
|
20
|
+
return newURL
|
|
21
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function appendSearchParam(
|
|
2
|
+
url: URL
|
|
3
|
+
, name: string
|
|
4
|
+
, value: string | number
|
|
5
|
+
): URL {
|
|
6
|
+
const newURL = new URL(url)
|
|
7
|
+
|
|
8
|
+
const newSearchParams = new URLSearchParams(newURL.searchParams)
|
|
9
|
+
newSearchParams.append(name, value.toString())
|
|
10
|
+
newURL.search = newSearchParams.toString()
|
|
11
|
+
|
|
12
|
+
return newURL
|
|
13
|
+
}
|
package/src/decode.ts
ADDED
package/src/encode.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { decode } from './decode.js'
|
|
2
|
+
|
|
3
|
+
// 与`encodeURI`不同, 该函数会首先尝试解码URL, 以防止二次编码.
|
|
4
|
+
export function encode(url: string): string {
|
|
5
|
+
const decodedURL = decode(url)
|
|
6
|
+
|
|
7
|
+
const encodedURLParts: string[] = []
|
|
8
|
+
|
|
9
|
+
const re = /%[A-F0-9]{2}/gi
|
|
10
|
+
let result: RegExpExecArray | null
|
|
11
|
+
let lastMatchedEndIndex = 0
|
|
12
|
+
while (result = re.exec(decodedURL), result) {
|
|
13
|
+
const matched = result[0]
|
|
14
|
+
const matchedStartIndex = result.index
|
|
15
|
+
const matchedEndIndex = matchedStartIndex
|
|
16
|
+
+ matched.length
|
|
17
|
+
|
|
18
|
+
const rawPart = decodedURL.slice(lastMatchedEndIndex, matchedStartIndex)
|
|
19
|
+
encodedURLParts.push(encodeURI(rawPart))
|
|
20
|
+
|
|
21
|
+
encodedURLParts.push(matched)
|
|
22
|
+
|
|
23
|
+
lastMatchedEndIndex = matchedEndIndex
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (lastMatchedEndIndex < decodedURL.length) {
|
|
27
|
+
const rawPart = decodedURL.slice(lastMatchedEndIndex, decodedURL.length)
|
|
28
|
+
encodedURLParts.push(encodeURI(rawPart))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return encodedURLParts.join('')
|
|
32
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from './set-protocol.js'
|
|
2
|
+
export * from './set-username.js'
|
|
3
|
+
export * from './set-password.js'
|
|
4
|
+
export * from './set-host.js'
|
|
5
|
+
export * from './set-hostname.js'
|
|
6
|
+
export * from './set-port.js'
|
|
7
|
+
export * from './set-pathname.js'
|
|
8
|
+
export * from './append-pathname.js'
|
|
9
|
+
export * from './set-search.js'
|
|
10
|
+
export * from './set-search-param.js'
|
|
11
|
+
export * from './set-search-params.js'
|
|
12
|
+
export * from './append-search-param.js'
|
|
13
|
+
export * from './set-hash.js'
|
|
14
|
+
export * from './encode.js'
|
|
15
|
+
export * from './decode.js'
|
package/src/set-hash.ts
ADDED
package/src/set-host.ts
ADDED
package/src/set-port.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function setProtocol(url: URL, protocol: string): URL {
|
|
2
|
+
const oldURL = new URL(url)
|
|
3
|
+
|
|
4
|
+
// WHATWG URL标准在更改协议时具有怪癖, 会阻止与[Special Scheme]协议相关的修改.
|
|
5
|
+
// 这意味着协议为`http:`的URL无法更改为`foo:`协议, 协议为`foo:`的URL也无法更改为`http:`协议.
|
|
6
|
+
// 为了绕过这项限制, 此处直接替换URL字符串.
|
|
7
|
+
// [Special Scheme]: https://url.spec.whatwg.org/#special-scheme
|
|
8
|
+
|
|
9
|
+
// 此外, 还存在一种URL的host为空的情况, 即`mailto:`、`javascript:`等协议,
|
|
10
|
+
// 这些URL在协议后直接跟pathname而不是host.
|
|
11
|
+
// 要正确处理相关URL的协议转换, 需要完成host与pathname之间的转换, 而这在URL对象上也无法实现(赋值会静默失败).
|
|
12
|
+
|
|
13
|
+
const newURL = new URL(
|
|
14
|
+
oldURL.href.replace(
|
|
15
|
+
/^\S+:/
|
|
16
|
+
, protocol.endsWith(':')
|
|
17
|
+
? protocol
|
|
18
|
+
: `${protocol}:`
|
|
19
|
+
)
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
return newURL
|
|
23
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function setSearchParam(
|
|
2
|
+
url: URL
|
|
3
|
+
, name: string
|
|
4
|
+
, value: string | number
|
|
5
|
+
): URL {
|
|
6
|
+
const newURL = new URL(url)
|
|
7
|
+
|
|
8
|
+
const newSearchParams = new URLSearchParams(newURL.searchParams)
|
|
9
|
+
newSearchParams.set(name, value.toString())
|
|
10
|
+
newURL.search = newSearchParams.toString()
|
|
11
|
+
|
|
12
|
+
return newURL
|
|
13
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function setSearchParams(
|
|
2
|
+
url: URL
|
|
3
|
+
, searchParams: Record<string, string | number>
|
|
4
|
+
): URL {
|
|
5
|
+
const newURL = new URL(url)
|
|
6
|
+
|
|
7
|
+
const newSearchParams = new URLSearchParams(newURL.searchParams)
|
|
8
|
+
for (const [name, value] of Object.entries(searchParams)) {
|
|
9
|
+
newSearchParams.set(name, value.toString())
|
|
10
|
+
}
|
|
11
|
+
newURL.search = newSearchParams.toString()
|
|
12
|
+
|
|
13
|
+
return newURL
|
|
14
|
+
}
|