File size: 10,387 Bytes
bc20498
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
# ufo

[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![bundle][bundle-src]][bundle-href]
[![Codecov][codecov-src]][codecov-href]

URL utils for humans.

## Install

Install using npm or your favourite package manager:

Install package:

```sh
# npm
npm install ufo

# yarn
yarn add ufo

# pnpm
pnpm install ufo

# bun
bun install ufo
```

Import utils:

```js
// ESM
import { normalizeURL, joinURL } from "ufo";

// CommonJS
const { normalizeURL, joinURL } = require("ufo");

// Deno
import { parseURL } from "https://unpkg.com/ufo/dist/index.mjs";
```

<!-- AUTOMD_START generator="jsdocs" defaultGroup="utils" -->

## Encoding Utils

### `decode(text)`

Decode text using `decodeURIComponent`. Returns the original text if it fails.

### `decodePath(text)`

Decode path section of URL (consistent with encodePath for slash encoding).

### `decodeQueryKey(text)`

Decodes query key (consistent with `encodeQueryKey` for plus encoding).

### `decodeQueryValue(text)`

Decode query value (consistent with encodeQueryValue for plus encoding).

### `encode(text)`

Encode characters that need to be encoded on the path, search and hash sections of the URL.

### `encodeHash(text)`

Encode characters that need to be encoded on the hash section of the URL.

### `encodeHost(name)`

Encodes hostname with punycode encoding.

### `encodeParam(text)`

Encode characters that need to be encoded on the path section of the URL as a param. This function encodes everything `encodePath` does plus the slash (`/`) character.

### `encodePath(text)`

Encode characters that need to be encoded on the path section of the URL.

### `encodeQueryKey(text)`

Encode characters that need to be encoded query values on the query section of the URL and also encodes the `=` character.

### `encodeQueryValue(input)`

Encode characters that need to be encoded query values on the query section of the URL.

## Parsing Utils

### `parseAuth(input)`

Takes a string of the form `username:password` and returns an object with the username and password decoded.

### `parseFilename(input)`

Parses a url and returns last segment in path as filename.

If `{ strict: true }` is passed as the second argument, it will only return the last segment only if ending with an extension.

**Example:**

```js
// Result: filename.ext
parseFilename("http://example.com/path/to/filename.ext");

// Result: undefined
parseFilename("/path/to/.hidden-file", { strict: true });
```

### `parseHost(input)`

Takes a string, and returns an object with two properties: `hostname` and `port`.

### `parsePath(input)`

Splits the input string into three parts, and returns an object with those three parts.

### `parseURL(input, defaultProto?)`

Takes a URL string and returns an object with the URL's `protocol`, `auth`, `host`, `pathname`, `search`, and `hash`.

**Example:**

```js
parseURL("http://foo.com/foo?test=123#token");
// { protocol: 'http:', auth: '', host: 'foo.com', pathname: '/foo', search: '?test=123', hash: '#token' }

parseURL("foo.com/foo?test=123#token");
// { pathname: 'foo.com/foo', search: '?test=123', hash: '#token' }

parseURL("foo.com/foo?test=123#token", "https://");
// { protocol: 'https:', auth: '', host: 'foo.com', pathname: '/foo', search: '?test=123', hash: '#token' }
```

### `stringifyParsedURL(parsed)`

Takes a `ParsedURL` object and returns the stringified URL.

**Example:**

```js
const obj = parseURL("http://foo.com/foo?test=123#token");
obj.host = "bar.com";

stringifyParsedURL(obj); // "http://bar.com/foo?test=123#token"
```

## Query Utils

### `encodeQueryItem(key, value)`

Encodes a pair of key and value into a url query string value.

If the value is an array, it will be encoded as multiple key-value pairs with the same key.

### `parseQuery(parametersString)`

Parses and decodes a query string into an object.

input can be a query string with or without the leading `?`

### `stringifyQuery(query)`

Stringfies and encodes a query object into a query string.

## Utils

### `cleanDoubleSlashes(input)`

Removes double slashes from the URL.

**Example:**

```js
cleanDoubleSlashes("//foo//bar//"); // "/foo/bar/"

cleanDoubleSlashes("http://example.com/analyze//http://localhost:3000//");
// Returns "http://example.com/analyze/http://localhost:3000/"
```

### `getQuery(input)`

Parses and decods the query object of an input URL into an object.

**Example:**

```js
getQuery("http://foo.com/foo?test=123&unicode=%E5%A5%BD");
// { test: "123", unicode: "好" }
```

### `hasLeadingSlash(input)`

Checks if the input has a leading slash. (e.g. `/foo`)

### `hasProtocol(inputString, opts)`


### `hasTrailingSlash(input, respectQueryAndFragment?)`

Checks if the input has a trailing slash.

### `isEmptyURL(url)`

Checks if the input url is empty or `/`.

### `isEqual(a, b, options)`

Checks if two paths are equal regardless of encoding, trailing slash, and leading slash differences.

You can make slash check strict by setting `{ trailingSlash: true, leadingSlash: true }` as options.
You can make encoding check strict by setting `{ encoding: true }` as options.

**Example:**

```js
isEqual("/foo", "foo"); // true
isEqual("foo/", "foo"); // true
isEqual("/foo bar", "/foo%20bar"); // true

// Strict compare
isEqual("/foo", "foo", { leadingSlash: true }); // false
isEqual("foo/", "foo", { trailingSlash: true }); // false
isEqual("/foo bar", "/foo%20bar", { encoding: true }); // false
```

### `isNonEmptyURL(url)`

Checks if the input url is not empty nor `/`.

### `isRelative(inputString)`

Check if a path starts with `./` or `../`.

**Example:**

```js
isRelative("./foo"); // true
```

### `isSamePath(p1, p2)`

Check two paths are equal or not. Trailing slash and encoding are normalized before comparison.

**Example:**

```js
isSamePath("/foo", "/foo/"); // true
```

### `isScriptProtocol(protocol?)`

Checks if the input protocol is any of the dangerous `blob:`, `data:`, `javascript`: or `vbscript:` protocols.

### `joinRelativeURL()`

Joins multiple URL segments into a single URL and also handles relative paths with `./` and `../`.

**Example:**

```js
joinRelativeURL("/a", "../b", "./c"); // "/b/c"
```

### `joinURL(base)`

Joins multiple URL segments into a single URL.

**Example:**

```js
joinURL("a", "/b", "/c"); // "a/b/c"
```

### `normalizeURL(input)`

Normlizes inputed url:

- Ensures url is properly encoded - Ensures pathname starts with slash - Preserves protocol/host if provided

**Example:**

```js
normalizeURL("test?query=123 123#hash, test");
// Returns "test?query=123%20123#hash,%20test"

normalizeURL("http://localhost:3000");
// Returns "http://localhost:3000"
```

### `resolveURL(base)`

Resolves multiple URL segments into a single URL.

**Example:**

```js
resolveURL("http://foo.com/foo?test=123#token", "bar", "baz");
// Returns "http://foo.com/foo/bar/baz?test=123#token"
```

### `withBase(input, base)`

Ensures the URL or pathname has a trailing slash.

If input aleady start with base, it will not be added again.

### `withFragment(input, hash)`

Add/Replace the fragment section of the URL.

**Example:**

```js
withFragment("/foo", "bar"); // "/foo#bar"
withFragment("/foo#bar", "baz"); // "/foo#baz"
withFragment("/foo#bar", ""); // "/foo"
```

### `withHttp(input)`

Adds or replaces url protocol to `http://`.

**Example:**

```js
withHttp("https://example.com"); // http://example.com
```

### `withHttps(input)`

Adds or replaces url protocol to `https://`.

**Example:**

```js
withHttps("http://example.com"); // https://example.com
```

### `withLeadingSlash(input)`

Ensures the URL or pathname has a leading slash.

### `withoutBase(input, base)`

Removes the base from the URL or pathname.

If input does not start with base, it will not be removed.

### `withoutFragment(input)`

Removes the fragment section from the URL.

**Example:**

```js
withoutFragment("http://example.com/foo?q=123#bar")
// Returns "http://example.com/foo?q=123"
```

### `withoutHost(input)`

Removes the host from the URL preserving everything else.

**Example:**

```js
withoutHost("http://example.com/foo?q=123#bar")
// Returns "/foo?q=123#bar"
```

### `withoutLeadingSlash(input)`

Removes leading slash from the URL or pathname.

### `withoutProtocol(input)`

Removes the protocol from the input.

**Example:**

```js
withoutProtocol("http://example.com"); // "example.com"
```

### `withoutTrailingSlash(input, respectQueryAndFragment?)`

Removes trailing slash from the URL or pathname.

If second argument is true, it will only remove the trailing slash if it's not part of the query or fragment with cost of more expensive operations.

**Example:**

```js
withoutTrailingSlash("/foo/"); // "/foo"

withoutTrailingSlash("/path/?query=true", true); // "/path?query=true"
```

### `withProtocol(input, protocol)`

Adds or Replaces protocol of the input URL.

**Example:**

```js
withProtocol("http://example.com", "ftp://"); // "ftp://example.com"
```

### `withQuery(input, query)`

Add/Replace the query section of the URL.

**Example:**

```js
withQuery("/foo?page=a", { token: "secret" }); // "/foo?page=a&token=secret"
```

### `withTrailingSlash(input, respectQueryAndFragment?)`

Ensures url ends with a trailing slash.

If seccond argument is `true`, it will only add the trailing slash if it's not part of the query or fragment with cost of more expensive operation.

**Example:**

```js
withTrailingSlash("/foo"); // "/foo/"

withTrailingSlash("/path?query=true", true); // "/path/?query=true"
```


<!-- AUTOMD_END -->

## License

[MIT](./LICENSE)

Special thanks to Eduardo San Martin Morote ([posva](https://github.com/posva)) for [encoding utilities](https://github.com/vuejs/vue-router-next/blob/v4.0.1/src/encoding.ts)

<!-- Badges -->

[npm-version-src]: https://img.shields.io/npm/v/ufo?style=flat&colorA=18181B&colorB=F0DB4F
[npm-version-href]: https://npmjs.com/package/ufo
[npm-downloads-src]: https://img.shields.io/npm/dm/ufo?style=flat&colorA=18181B&colorB=F0DB4F
[npm-downloads-href]: https://npmjs.com/package/ufo
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/ufo/main?style=flat&colorA=18181B&colorB=F0DB4F
[codecov-href]: https://codecov.io/gh/unjs/ufo
[bundle-src]: https://img.shields.io/bundlephobia/minzip/ufo?style=flat&colorA=18181B&colorB=F0DB4F
[bundle-href]: https://bundlephobia.com/result?p=ufo