@hkdigital/lib-sveltekit 0.0.75 → 0.0.76
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/dist/components/index.d.ts +0 -1
- package/dist/components/tab-bar/HkTabBar.state.svelte.d.ts +1 -1
- package/dist/components/tab-bar/index.d.ts +0 -1
- package/dist/components/tab-bar/typedef.d.ts +1 -1
- package/dist/constants/mime/application.d.ts +1 -0
- package/dist/constants/mime/application.js +3 -0
- package/dist/constants/mime/audio.d.ts +10 -0
- package/dist/constants/mime/audio.js +13 -0
- package/dist/constants/mime/index.d.ts +1 -0
- package/dist/constants/mime/index.js +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/util/expect/index.d.ts +6 -0
- package/dist/util/expect/index.js +10 -1
- package/dist/util/http/headers.d.ts +2 -3
- package/dist/util/http/headers.js +18 -12
- package/dist/util/http/http-request.js +1 -1
- package/dist/util/http/json-request.d.ts +25 -14
- package/dist/util/http/json-request.js +17 -15
- package/dist/util/http/mocks.d.ts +8 -0
- package/dist/util/http/mocks.js +53 -0
- package/dist/util/http/response.d.ts +4 -4
- package/dist/util/http/response.js +22 -12
- package/dist/util/http/url.d.ts +2 -2
- package/dist/util/http/url.js +1 -1
- package/package.json +1 -1
@@ -1 +0,0 @@
|
|
1
|
-
export {};
|
@@ -51,4 +51,4 @@ export class HkTabBarState {
|
|
51
51
|
export const createOrGetState: (instanceKey?: string | Symbol) => HkTabBarState;
|
52
52
|
export const createState: (instanceKey?: string | Symbol) => HkTabBarState;
|
53
53
|
export const getState: (instanceKey?: string | Symbol) => HkTabBarState;
|
54
|
-
export type Tab =
|
54
|
+
export type Tab = any;
|
@@ -1,5 +1,4 @@
|
|
1
1
|
export { default as HkTabBar } from "./HkTabBar.svelte";
|
2
2
|
export { default as HkTabBarSelector } from "./HkTabBarSelector.svelte";
|
3
|
-
export * from "./typedef.js";
|
4
3
|
export { createOrGetState as createOrGetTabBarState, createState as createTabBarState, getState as getTabBarState } from "./HkTabBar.state.svelte.js";
|
5
4
|
export { createOrGetState as createOrGetTabBarSelectorState, createState as createTabBarSelectorState, getState as getTabBarSelectorState } from "./HkTabBarSelector.state.svelte.js";
|
@@ -0,0 +1,10 @@
|
|
1
|
+
export const AUDIO_BASIC: "audio/basic";
|
2
|
+
export const AUDIO_MIDI: "audio/mid";
|
3
|
+
export const AUDIO_WAV: "audio/vnd.wav";
|
4
|
+
export const AUDIO_MP3: "audio/mpeg";
|
5
|
+
export const AUDIO_MP4: "audio/mp4";
|
6
|
+
export const AUDIO_AIF: "audio/x-aiff";
|
7
|
+
export const AUDIO_AIFC: "audio/x-aiff";
|
8
|
+
export const AUDIO_AIFF: "audio/x-aiff";
|
9
|
+
export const AUDIO_M3U: "audio/x-mpegurl";
|
10
|
+
export const AUDIO_OGG: "audio/ogg";
|
@@ -0,0 +1,13 @@
|
|
1
|
+
export const AUDIO_BASIC = 'audio/basic';
|
2
|
+
export const AUDIO_MIDI = 'audio/mid';
|
3
|
+
export const AUDIO_WAV = 'audio/vnd.wav';
|
4
|
+
|
5
|
+
export const AUDIO_MP3 = 'audio/mpeg';
|
6
|
+
export const AUDIO_MP4 = 'audio/mp4';
|
7
|
+
|
8
|
+
export const AUDIO_AIF = 'audio/x-aiff';
|
9
|
+
export const AUDIO_AIFC = 'audio/x-aiff';
|
10
|
+
export const AUDIO_AIFF = 'audio/x-aiff';
|
11
|
+
|
12
|
+
export const AUDIO_M3U = 'audio/x-mpegurl';
|
13
|
+
export const AUDIO_OGG = 'audio/ogg';
|
package/dist/index.d.ts
CHANGED
@@ -1 +0,0 @@
|
|
1
|
-
export {};
|
@@ -16,6 +16,12 @@ export function notNull(value: any): void;
|
|
16
16
|
* @param {any} value
|
17
17
|
*/
|
18
18
|
export function _true(value: any): void;
|
19
|
+
/**
|
20
|
+
* Expect a positive number
|
21
|
+
*
|
22
|
+
* @param {any} value
|
23
|
+
*/
|
24
|
+
export function positiveNumber(value: any): void;
|
19
25
|
/**
|
20
26
|
* Throws a validation error if value is not a string
|
21
27
|
*
|
@@ -126,7 +126,16 @@ export { _true as true };
|
|
126
126
|
|
127
127
|
// > Compounds
|
128
128
|
|
129
|
-
|
129
|
+
/**
|
130
|
+
* Expect a positive number
|
131
|
+
*
|
132
|
+
* @param {any} value
|
133
|
+
*/
|
134
|
+
export function positiveNumber(value) {
|
135
|
+
const schema = v.pipe(v.number(), v.minValue(0));
|
136
|
+
v.parse(schema, value);
|
137
|
+
}
|
138
|
+
|
130
139
|
// notNegativeNumber
|
131
140
|
// positiveInteger
|
132
141
|
// notNegativeInteger
|
@@ -6,7 +6,6 @@
|
|
6
6
|
*
|
7
7
|
* @param {Headers} target - Headers object to set the extra headers in
|
8
8
|
*
|
9
|
-
* @param {object} [
|
10
|
-
* Object that contains custom headers. A header is a name, value pair.
|
9
|
+
* @param {null|object|[string, string][]} [pairs]
|
11
10
|
*/
|
12
|
-
export function setRequestHeaders(target: Headers,
|
11
|
+
export function setRequestHeaders(target: Headers, pairs?: null | object | [string, string][]): void;
|
@@ -8,30 +8,36 @@ import * as expect from '../expect/index.js';
|
|
8
8
|
*
|
9
9
|
* @param {Headers} target - Headers object to set the extra headers in
|
10
10
|
*
|
11
|
-
* @param {object} [
|
12
|
-
* Object that contains custom headers. A header is a name, value pair.
|
11
|
+
* @param {null|object|[string, string][]} [pairs]
|
13
12
|
*/
|
14
|
-
export function setRequestHeaders(target,
|
13
|
+
export function setRequestHeaders(target, pairs) {
|
15
14
|
if (!(target instanceof Headers)) {
|
16
15
|
throw new Error('Invalid parameter [target] (expected Headers object)');
|
17
16
|
}
|
18
17
|
|
19
|
-
expect.objectNoArray(
|
18
|
+
// expect.objectNoArray(pairs);
|
20
19
|
|
21
|
-
if (
|
22
|
-
throw new Error('Invalid parameter [
|
20
|
+
if (pairs instanceof Headers) {
|
21
|
+
throw new Error('Invalid parameter [pairs] (should not be a Headers object)');
|
23
22
|
}
|
24
23
|
|
25
|
-
|
26
|
-
|
24
|
+
if (!pairs) {
|
25
|
+
return;
|
26
|
+
}
|
27
|
+
|
28
|
+
if (typeof pairs !== 'object') {
|
29
|
+
throw new Error('Invalid value for parameter [pairs]');
|
30
|
+
}
|
27
31
|
|
28
|
-
|
32
|
+
if (!Array.isArray(pairs)) {
|
33
|
+
pairs = Object.entries(pairs);
|
34
|
+
}
|
29
35
|
|
36
|
+
for (const [name, value] of pairs) {
|
37
|
+
expect.notEmptyString(name);
|
30
38
|
expect.notEmptyString(value);
|
31
39
|
|
32
|
-
//
|
33
|
-
// Headers should be encoded lowercase in HTTP2
|
34
|
-
//
|
40
|
+
// @note Headers should be encoded lowercase in HTTP2
|
35
41
|
const nameLower = name.toLowerCase();
|
36
42
|
|
37
43
|
target.set(nameLower, value); /* overwrites existing value */
|
@@ -2,12 +2,13 @@
|
|
2
2
|
* Make a GET request to fetch JSON encoded data
|
3
3
|
* - Expect JSON response from server
|
4
4
|
*
|
5
|
-
* @param {
|
5
|
+
* @param {object} _
|
6
|
+
* @param {string|URL} _.url - Url string or URL object
|
6
7
|
*
|
7
|
-
* @param {object} [urlSearchParams]
|
8
|
+
* @param {object} [_.urlSearchParams]
|
8
9
|
* Parameters that should be added to the request url
|
9
10
|
*
|
10
|
-
* @param {
|
11
|
+
* @param {[string, string][]} [_.headers]
|
11
12
|
* List of custom headers. Each header is an array that contains
|
12
13
|
* the header name and the header value.
|
13
14
|
* E.g. [ "content-type", "application/json" ]
|
@@ -15,26 +16,31 @@
|
|
15
16
|
* @throws ResponseError
|
16
17
|
* If a network error occurred or the response was not ok
|
17
18
|
*
|
18
|
-
* @returns {any} parsed JSON data
|
19
|
+
* @returns {Promise<any>} parsed JSON data
|
19
20
|
*/
|
20
|
-
export function jsonGet({ url, urlSearchParams, headers }:
|
21
|
+
export function jsonGet({ url, urlSearchParams, headers }: {
|
22
|
+
url: string | URL;
|
23
|
+
urlSearchParams?: object;
|
24
|
+
headers?: [string, string][];
|
25
|
+
}): Promise<any>;
|
21
26
|
/**
|
22
27
|
* Make a POST request to fetch JSON encoded data
|
23
28
|
* - Expect JSON response from server
|
24
29
|
*
|
25
|
-
* @param {
|
30
|
+
* @param {object} _
|
31
|
+
* @param {string|URL} _.url - Url string or URL object
|
26
32
|
*
|
27
|
-
* @param {any} body
|
33
|
+
* @param {any} _.body
|
28
34
|
* Data that will be converted to a JSON encoded string and send to the server
|
29
35
|
*
|
30
|
-
* @param {object} [urlSearchParams]
|
36
|
+
* @param {object} [_.urlSearchParams]
|
31
37
|
* Parameters that should be added to the request url.
|
32
38
|
*
|
33
|
-
*
|
34
|
-
*
|
35
|
-
*
|
39
|
+
* - Be careful when using urlSearchParams in POST requests, it can be
|
40
|
+
* confusing since the parameters usually go in the body part of
|
41
|
+
* the request.
|
36
42
|
*
|
37
|
-
* @param {
|
43
|
+
* @param {[string, string][]} [_.headers]
|
38
44
|
* List of custom headers. Each header is an array that contains
|
39
45
|
* the header name and the header value.
|
40
46
|
* E.g. [ "content-type", "application/json" ]
|
@@ -42,6 +48,11 @@ export function jsonGet({ url, urlSearchParams, headers }: string | URL): any;
|
|
42
48
|
* @throws ResponseError
|
43
49
|
* If a network error occurred or the response was not ok
|
44
50
|
*
|
45
|
-
* @returns {any} parsed JSON data
|
51
|
+
* @returns {Promise<any>} parsed JSON data
|
46
52
|
*/
|
47
|
-
export function jsonPost({ url, body, urlSearchParams, headers }:
|
53
|
+
export function jsonPost({ url, body, urlSearchParams, headers }: {
|
54
|
+
url: string | URL;
|
55
|
+
body: any;
|
56
|
+
urlSearchParams?: object;
|
57
|
+
headers?: [string, string][];
|
58
|
+
}): Promise<any>;
|
@@ -16,12 +16,13 @@ const ACCEPT = 'accept';
|
|
16
16
|
* Make a GET request to fetch JSON encoded data
|
17
17
|
* - Expect JSON response from server
|
18
18
|
*
|
19
|
-
* @param {
|
19
|
+
* @param {object} _
|
20
|
+
* @param {string|URL} _.url - Url string or URL object
|
20
21
|
*
|
21
|
-
* @param {object} [urlSearchParams]
|
22
|
+
* @param {object} [_.urlSearchParams]
|
22
23
|
* Parameters that should be added to the request url
|
23
24
|
*
|
24
|
-
* @param {
|
25
|
+
* @param {[string, string][]} [_.headers]
|
25
26
|
* List of custom headers. Each header is an array that contains
|
26
27
|
* the header name and the header value.
|
27
28
|
* E.g. [ "content-type", "application/json" ]
|
@@ -29,13 +30,13 @@ const ACCEPT = 'accept';
|
|
29
30
|
* @throws ResponseError
|
30
31
|
* If a network error occurred or the response was not ok
|
31
32
|
*
|
32
|
-
* @returns {any} parsed JSON data
|
33
|
+
* @returns {Promise<any>} parsed JSON data
|
33
34
|
*/
|
34
35
|
export async function jsonGet({ url, urlSearchParams, headers }) {
|
35
36
|
url = toURL(url);
|
36
37
|
|
37
38
|
if (!headers) {
|
38
|
-
headers =
|
39
|
+
headers = [];
|
39
40
|
}
|
40
41
|
|
41
42
|
headers[ACCEPT] = APPLICATION_JSON;
|
@@ -75,19 +76,20 @@ export async function jsonGet({ url, urlSearchParams, headers }) {
|
|
75
76
|
* Make a POST request to fetch JSON encoded data
|
76
77
|
* - Expect JSON response from server
|
77
78
|
*
|
78
|
-
* @param {
|
79
|
+
* @param {object} _
|
80
|
+
* @param {string|URL} _.url - Url string or URL object
|
79
81
|
*
|
80
|
-
* @param {any} body
|
82
|
+
* @param {any} _.body
|
81
83
|
* Data that will be converted to a JSON encoded string and send to the server
|
82
84
|
*
|
83
|
-
* @param {object} [urlSearchParams]
|
85
|
+
* @param {object} [_.urlSearchParams]
|
84
86
|
* Parameters that should be added to the request url.
|
85
87
|
*
|
86
|
-
*
|
87
|
-
*
|
88
|
-
*
|
88
|
+
* - Be careful when using urlSearchParams in POST requests, it can be
|
89
|
+
* confusing since the parameters usually go in the body part of
|
90
|
+
* the request.
|
89
91
|
*
|
90
|
-
* @param {
|
92
|
+
* @param {[string, string][]} [_.headers]
|
91
93
|
* List of custom headers. Each header is an array that contains
|
92
94
|
* the header name and the header value.
|
93
95
|
* E.g. [ "content-type", "application/json" ]
|
@@ -95,13 +97,13 @@ export async function jsonGet({ url, urlSearchParams, headers }) {
|
|
95
97
|
* @throws ResponseError
|
96
98
|
* If a network error occurred or the response was not ok
|
97
99
|
*
|
98
|
-
* @returns {any} parsed JSON data
|
100
|
+
* @returns {Promise<any>} parsed JSON data
|
99
101
|
*/
|
100
102
|
export async function jsonPost({ url, body, urlSearchParams, headers }) {
|
101
103
|
url = toURL(url);
|
102
104
|
|
103
105
|
if (!headers) {
|
104
|
-
headers =
|
106
|
+
headers = [];
|
105
107
|
} else {
|
106
108
|
expect.object(headers);
|
107
109
|
}
|
@@ -111,7 +113,7 @@ export async function jsonPost({ url, body, urlSearchParams, headers }) {
|
|
111
113
|
headers[ACCEPT] = APPLICATION_JSON;
|
112
114
|
headers[CONTENT_TYPE] = APPLICATION_JSON;
|
113
115
|
|
114
|
-
const responsePromise = httpRequest({ METHOD_POST, url, body, urlSearchParams, headers });
|
116
|
+
const responsePromise = httpRequest({ method: METHOD_POST, url, body, urlSearchParams, headers });
|
115
117
|
|
116
118
|
const response = await waitForAndCheckResponse(responsePromise, url);
|
117
119
|
|
@@ -10,3 +10,11 @@
|
|
10
10
|
export function createJsonFetchResponse<T>(data: T): {
|
11
11
|
json: () => Promise<T>;
|
12
12
|
};
|
13
|
+
/**
|
14
|
+
* Create a response value that can be used by a mocked fetch function
|
15
|
+
*
|
16
|
+
* @param {ArrayBuffer} arrayBuffer
|
17
|
+
*
|
18
|
+
* @returns {Response}
|
19
|
+
*/
|
20
|
+
export function createStreamedResponse(arrayBuffer: ArrayBuffer): Response;
|
package/dist/util/http/mocks.js
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
import { CONTENT_TYPE, CONTENT_LENGTH } from '@hkdigital/lib-sveltekit/constants/http/index.js';
|
2
|
+
|
3
|
+
import { OCTET_STREAM } from '../../constants/mime/index.js';
|
4
|
+
|
1
5
|
/**
|
2
6
|
* Create a response value that can be used by a mocked fetch function
|
3
7
|
*
|
@@ -10,3 +14,52 @@
|
|
10
14
|
export function createJsonFetchResponse(data /* , options */) {
|
11
15
|
return { json: () => new Promise((resolve) => resolve(data)) };
|
12
16
|
}
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Create a response value that can be used by a mocked fetch function
|
20
|
+
*
|
21
|
+
* @param {ArrayBuffer} arrayBuffer
|
22
|
+
*
|
23
|
+
* @returns {Response}
|
24
|
+
*/
|
25
|
+
export function createStreamedResponse(arrayBuffer /*, options */) {
|
26
|
+
const byteLength = arrayBuffer.byteLength;
|
27
|
+
const chunkSize = Math.ceil(byteLength / 10);
|
28
|
+
|
29
|
+
const body = new ReadableStream({
|
30
|
+
start(controller) {
|
31
|
+
let offset = 0;
|
32
|
+
|
33
|
+
function pushChunk() {
|
34
|
+
if (offset >= byteLength) {
|
35
|
+
controller.close();
|
36
|
+
return;
|
37
|
+
}
|
38
|
+
|
39
|
+
// Calculate the size of the current chunk
|
40
|
+
const currentChunkSize = Math.min(chunkSize, byteLength - offset);
|
41
|
+
|
42
|
+
// Create a new ArrayBuffer for this chunk
|
43
|
+
const chunk = arrayBuffer.slice(offset, offset + currentChunkSize);
|
44
|
+
|
45
|
+
controller.enqueue(chunk);
|
46
|
+
offset += currentChunkSize;
|
47
|
+
|
48
|
+
// Schedule next chunk
|
49
|
+
setTimeout(pushChunk, 0);
|
50
|
+
}
|
51
|
+
|
52
|
+
// Start pushing chunks
|
53
|
+
pushChunk();
|
54
|
+
}
|
55
|
+
});
|
56
|
+
|
57
|
+
const response = new Response(body, {
|
58
|
+
headers: new Headers({
|
59
|
+
[CONTENT_TYPE]: OCTET_STREAM,
|
60
|
+
[CONTENT_LENGTH]: String(byteLength)
|
61
|
+
})
|
62
|
+
});
|
63
|
+
|
64
|
+
return response;
|
65
|
+
}
|
@@ -28,14 +28,14 @@ export function getResponseSize(response: Response): number;
|
|
28
28
|
* @example
|
29
29
|
* const response = await waitForAndCheckResponse( responsePromise );
|
30
30
|
*
|
31
|
-
* @param {Promise<
|
32
|
-
* @param {URL} url - An url that is used for error messages
|
31
|
+
* @param {Promise<Response>} responsePromise
|
32
|
+
* @param {string|URL} url - An url that is used for error messages
|
33
33
|
*
|
34
34
|
* @throws ResponseError - A response error if something went wrong
|
35
35
|
*
|
36
|
-
* @returns {
|
36
|
+
* @returns {Promise<Response>} response
|
37
37
|
*/
|
38
|
-
export function waitForAndCheckResponse(responsePromise: Promise<
|
38
|
+
export function waitForAndCheckResponse(responsePromise: Promise<Response>, url: string | URL): Promise<Response>;
|
39
39
|
/**
|
40
40
|
* Load response body as ArrayBuffer
|
41
41
|
* - Progress can be monitored by suppying an onProgress callback
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import { ResponseError } from '../../constants/errors/index.js';
|
2
2
|
import * as expect from '../expect/index.js';
|
3
|
+
import { toURL } from './url.js';
|
3
4
|
|
4
5
|
import { WWW_AUTHENTICATE, CONTENT_LENGTH } from '../../constants/http/headers.js';
|
5
6
|
|
@@ -96,16 +97,18 @@ export function getResponseSize(response) {
|
|
96
97
|
* @example
|
97
98
|
* const response = await waitForAndCheckResponse( responsePromise );
|
98
99
|
*
|
99
|
-
* @param {Promise<
|
100
|
-
* @param {URL} url - An url that is used for error messages
|
100
|
+
* @param {Promise<Response>} responsePromise
|
101
|
+
* @param {string|URL} url - An url that is used for error messages
|
101
102
|
*
|
102
103
|
* @throws ResponseError - A response error if something went wrong
|
103
104
|
*
|
104
|
-
* @returns {
|
105
|
+
* @returns {Promise<Response>} response
|
105
106
|
*/
|
106
107
|
export async function waitForAndCheckResponse(responsePromise, url) {
|
107
108
|
expect.promise(responsePromise);
|
108
109
|
|
110
|
+
url = toURL(url);
|
111
|
+
|
109
112
|
let response;
|
110
113
|
|
111
114
|
try {
|
@@ -157,23 +160,25 @@ export function loadResponseBuffer(response, onProgress) {
|
|
157
160
|
let aborted = false;
|
158
161
|
|
159
162
|
/**
|
163
|
+
* Read chunks from response body using reader
|
164
|
+
*
|
160
165
|
* @returns {Promise<ArrayBuffer>}
|
161
166
|
*/
|
162
167
|
async function read() {
|
163
|
-
let loading = true;
|
164
168
|
let chunks = [];
|
165
169
|
|
166
170
|
// - Use flag 'loading'
|
167
171
|
// - Check if #abortLoading still exists
|
168
|
-
|
172
|
+
for (;;) {
|
169
173
|
const { done, value } = await reader.read();
|
170
174
|
|
171
|
-
if (
|
172
|
-
//
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
175
|
+
if (value) {
|
176
|
+
// @note value is an ArrayBuffer
|
177
|
+
bytesLoaded += value.byteLength;
|
178
|
+
|
179
|
+
// console.log({ done, value, byteLength: value.byteLength, bytesLoaded });
|
180
|
+
|
181
|
+
// console.log({ size, bytesLoaded, value });
|
177
182
|
|
178
183
|
if (size && bytesLoaded > size) {
|
179
184
|
throw new Error(`Received more bytes that specified by header content-length`);
|
@@ -185,6 +190,11 @@ export function loadResponseBuffer(response, onProgress) {
|
|
185
190
|
onProgress({ bytesLoaded, size });
|
186
191
|
}
|
187
192
|
}
|
193
|
+
|
194
|
+
if (done || aborted) {
|
195
|
+
// Loading complete or aborted by user
|
196
|
+
break;
|
197
|
+
}
|
188
198
|
} // end while
|
189
199
|
|
190
200
|
if (size && bytesLoaded !== size) {
|
@@ -200,7 +210,7 @@ export function loadResponseBuffer(response, onProgress) {
|
|
200
210
|
// Place the chunks in the buffer
|
201
211
|
for (let chunk of chunks) {
|
202
212
|
body.set(chunk, offset);
|
203
|
-
offset += chunk.
|
213
|
+
offset += chunk.byteLength;
|
204
214
|
} // end for
|
205
215
|
|
206
216
|
return buffer;
|
package/dist/util/http/url.d.ts
CHANGED
@@ -20,6 +20,6 @@ export function hasProtocol(url: string): boolean;
|
|
20
20
|
* Convert an url to an absolute url and apply decodeURI to
|
21
21
|
* convert URI encoded characters to normal characters
|
22
22
|
*
|
23
|
-
* @param {string} url
|
23
|
+
* @param {string|URL} url
|
24
24
|
*/
|
25
|
-
export function href(url: string): string;
|
25
|
+
export function href(url: string | URL): string;
|
package/dist/util/http/url.js
CHANGED
@@ -44,7 +44,7 @@ export function hasProtocol(url) {
|
|
44
44
|
* Convert an url to an absolute url and apply decodeURI to
|
45
45
|
* convert URI encoded characters to normal characters
|
46
46
|
*
|
47
|
-
* @param {string} url
|
47
|
+
* @param {string|URL} url
|
48
48
|
*/
|
49
49
|
export function href(url) {
|
50
50
|
const urlObj = toURL(url);
|