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 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":"AAAA,MAAM,UAAU,MAAM,CAAC,GAAW;IAChC,OAAO,SAAS,CAAC,GAAG,CAAC,CAAA;AACvB,CAAC"}
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
- return encodeURI(decodeURI(url));
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,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;AAClC,CAAC"}
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
@@ -1,5 +1,6 @@
1
1
  export function setHost(url, host) {
2
2
  const newURL = new URL(url);
3
+ newURL.port = '';
3
4
  newURL.host = host;
4
5
  return newURL;
5
6
  }
@@ -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,6 @@
1
+ export function setHostname(url, hostname) {
2
+ const newURL = new URL(url);
3
+ newURL.hostname = hostname;
4
+ return newURL;
5
+ }
6
+ //# sourceMappingURL=set-hostname.js.map
@@ -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"}
@@ -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(/^(\S+:)\/\//, protocol.endsWith(':')
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
@@ -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;IAG3B,MAAM,MAAM,GAAG,IAAI,GAAG,CACpB,MAAM,CAAC,IAAI,CAAC,OAAO,CACjB,aAAa,EACb,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;QACtB,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,GAAG,QAAQ,KAAK,CACnB,CACF,CAAA;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
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
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "url-operator",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "files": [
7
- "lib"
7
+ "lib",
8
+ "src"
8
9
  ],
9
10
  "type": "module",
10
11
  "main": "lib/index.js",
@@ -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
@@ -0,0 +1,4 @@
1
+ // 该函数仅仅是`decodeURI`的别名, 因为`decodeURI`通过了所有测试用例.
2
+ export function decode(url: string): string {
3
+ return decodeURI(url)
4
+ }
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'
@@ -0,0 +1,7 @@
1
+ export function setHash(url: URL, hash: string): URL {
2
+ const newURL = new URL(url)
3
+
4
+ newURL.hash = hash
5
+
6
+ return newURL
7
+ }
@@ -0,0 +1,8 @@
1
+ export function setHost(url: URL, host: string): URL {
2
+ const newURL = new URL(url)
3
+
4
+ newURL.port = ''
5
+ newURL.host = host
6
+
7
+ return newURL
8
+ }
@@ -0,0 +1,7 @@
1
+ export function setHostname(url: URL, hostname: string): URL {
2
+ const newURL = new URL(url)
3
+
4
+ newURL.hostname = hostname
5
+
6
+ return newURL
7
+ }
@@ -0,0 +1,7 @@
1
+ export function setPassword(url: URL, password: string): URL {
2
+ const newURL = new URL(url)
3
+
4
+ newURL.password = password
5
+
6
+ return newURL
7
+ }
@@ -0,0 +1,7 @@
1
+ export function setPathname(url: URL, pathname: string): URL {
2
+ const newURL = new URL(url)
3
+
4
+ newURL.pathname = pathname
5
+
6
+ return newURL
7
+ }
@@ -0,0 +1,7 @@
1
+ export function setPort(url: URL, port: number): URL {
2
+ const newURL = new URL(url)
3
+
4
+ newURL.port = port.toString()
5
+
6
+ return newURL
7
+ }
@@ -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
+ }
@@ -0,0 +1,7 @@
1
+ export function setSearch(url: URL, search: string): URL {
2
+ const newURL = new URL(url)
3
+
4
+ newURL.search = search
5
+
6
+ return newURL
7
+ }
@@ -0,0 +1,7 @@
1
+ export function setUsername(url: URL, username: string): URL {
2
+ const newURL = new URL(url)
3
+
4
+ newURL.username = username
5
+
6
+ return newURL
7
+ }