You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
5.0 KiB
235 lines
5.0 KiB
1 year ago
|
[![npm version][npm-version-src]][npm-version-href]
|
||
|
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
||
|
[![Github Actions][github-actions-src]][github-actions-href]
|
||
|
[![Codecov][codecov-src]][codecov-href]
|
||
|
[![bundle][bundle-src]][bundle-href]
|
||
|
|
||
|
![👽 ufo](.github/banner.svg)
|
||
|
|
||
|
## Install
|
||
|
|
||
|
Install using npm or yarn:
|
||
|
|
||
|
```bash
|
||
|
npm i ufo
|
||
|
# or
|
||
|
yarn add ufo
|
||
|
```
|
||
|
|
||
|
Import:
|
||
|
|
||
|
```js
|
||
|
// CommonJS
|
||
|
const { normalizeURL, joinURL } = require('ufo')
|
||
|
|
||
|
// ESM
|
||
|
import { normalizeURL, joinURL } from 'ufo'
|
||
|
|
||
|
// Deno
|
||
|
import { parseURL } from 'https://unpkg.com/ufo/dist/index.mjs'
|
||
|
```
|
||
|
|
||
|
**Notice:** You may need to transpile package and add URL polyfill for legacy environments
|
||
|
|
||
|
## Usage
|
||
|
|
||
|
### `normalizeURL`
|
||
|
|
||
|
- Ensures URL is properly encoded
|
||
|
- Ensures pathname starts with slash
|
||
|
- Preserves protocol/host if provided
|
||
|
|
||
|
```ts
|
||
|
|
||
|
// Result: test?query=123%20123#hash,%20test
|
||
|
normalizeURL('test?query=123 123#hash, test')
|
||
|
|
||
|
// Result: http://localhost:3000/
|
||
|
normalizeURL('http://localhost:3000')
|
||
|
```
|
||
|
|
||
|
### `joinURL`
|
||
|
|
||
|
```ts
|
||
|
// Result: a/b/c
|
||
|
joinURL('a', '/b', '/c')
|
||
|
```
|
||
|
|
||
|
### `resolveURL`
|
||
|
|
||
|
```ts
|
||
|
// Result: http://foo.com/foo/bar/baz?test=123#token
|
||
|
resolveURL('http://foo.com/foo?test=123#token', 'bar', 'baz')
|
||
|
```
|
||
|
|
||
|
### `parseURL`
|
||
|
|
||
|
```ts
|
||
|
// Result: { protocol: 'http:', auth: '', host: 'foo.com', pathname: '/foo', search: '?test=123', hash: '#token' }
|
||
|
parseURL('http://foo.com/foo?test=123#token')
|
||
|
|
||
|
// Result: { pathname: 'foo.com/foo', search: '?test=123', hash: '#token' }
|
||
|
parseURL('foo.com/foo?test=123#token')
|
||
|
|
||
|
// Result: { protocol: 'https:', auth: '', host: 'foo.com', pathname: '/foo', search: '?test=123', hash: '#token' }
|
||
|
parseURL('foo.com/foo?test=123#token', 'https://')
|
||
|
```
|
||
|
|
||
|
### `withQuery`
|
||
|
|
||
|
```ts
|
||
|
// Result: /foo?page=a&token=secret
|
||
|
withQuery('/foo?page=a', { token: 'secret' })
|
||
|
```
|
||
|
|
||
|
### `getQuery`
|
||
|
|
||
|
```ts
|
||
|
// Result: { test: '123', unicode: '好' }
|
||
|
getQuery('http://foo.com/foo?test=123&unicode=%E5%A5%BD')
|
||
|
```
|
||
|
|
||
|
### `$URL`
|
||
|
|
||
|
Implementing URL interface with some improvements:
|
||
|
|
||
|
- Supporting schemeless and hostless URLs
|
||
|
- Supporting relative URLs
|
||
|
- Preserving trailing-slash status
|
||
|
- Decoded and mutable classs properties (`protocol`, `host`, `auth`, `pathname`, `query`, `hash`)
|
||
|
- Consistent URL parser independent of environment
|
||
|
- Consistent encoding independent of environment
|
||
|
- Punycode support for host encoding
|
||
|
|
||
|
### `withTrailingSlash`
|
||
|
|
||
|
Ensures url ends with a trailing slash
|
||
|
|
||
|
```ts
|
||
|
// Result: /foo/
|
||
|
withTrailingSlash('/foo')
|
||
|
```
|
||
|
|
||
|
```ts
|
||
|
// Result: /path/?query=true
|
||
|
withTrailingSlash('/path?query=true', true)
|
||
|
```
|
||
|
|
||
|
### `withoutTrailingSlash`
|
||
|
|
||
|
Ensures url does not ends with a trailing slash
|
||
|
|
||
|
```ts
|
||
|
// Result: /foo
|
||
|
withoutTrailingSlash('/foo/')
|
||
|
```
|
||
|
|
||
|
```ts
|
||
|
// Result: /path?query=true
|
||
|
withoutTrailingSlash('/path/?query=true', true)
|
||
|
```
|
||
|
|
||
|
### `cleanDoubleSlashes`
|
||
|
|
||
|
Ensures url does not have double slash (except for protocol)
|
||
|
|
||
|
```ts
|
||
|
// Result: /foo/bar/
|
||
|
cleanDoubleSlashes('//foo//bar//')
|
||
|
// Result: http://example.com/analyze/http://localhost:3000/
|
||
|
cleanDoubleSlashes('http://example.com/analyze//http://localhost:3000//')
|
||
|
```
|
||
|
|
||
|
### `isSamePath`
|
||
|
|
||
|
Check two paths are equal or not. Trailing slash and encoding are normalized before comparation.
|
||
|
|
||
|
```ts
|
||
|
// Result: true
|
||
|
isSamePath('/foo', '/foo/')
|
||
|
```
|
||
|
|
||
|
### `isRelative`
|
||
|
|
||
|
Check if a path starts with `./` or `../`.
|
||
|
|
||
|
```ts
|
||
|
// Result: true
|
||
|
isRelative('./foo')
|
||
|
```
|
||
|
|
||
|
### `withHttp`
|
||
|
|
||
|
Ensures url protocol is `http`
|
||
|
|
||
|
```ts
|
||
|
// Result: http://example.com
|
||
|
withHttp('https://example.com')
|
||
|
```
|
||
|
|
||
|
### `withHttps`
|
||
|
|
||
|
Ensures url protocol is `https`
|
||
|
|
||
|
```ts
|
||
|
// Result: https://example.com
|
||
|
withHttps('http://example.com')
|
||
|
```
|
||
|
|
||
|
### `withProtocol`
|
||
|
|
||
|
Changes url protocol passed as second argument
|
||
|
|
||
|
```ts
|
||
|
// Result: ftp://example.com
|
||
|
withProtocol('http://example.com', 'ftp://')
|
||
|
```
|
||
|
|
||
|
### `withoutProtocol`
|
||
|
|
||
|
Removes url protocol
|
||
|
|
||
|
```ts
|
||
|
// Result: example.com
|
||
|
withoutProtocol('http://example.com')
|
||
|
```
|
||
|
|
||
|
### `isEqual`
|
||
|
|
||
|
Compare two URLs regardless of their slash condition or encoding:
|
||
|
|
||
|
```ts
|
||
|
// Result: true
|
||
|
isEqual('/foo', 'foo')
|
||
|
isEqual('foo/', 'foo')
|
||
|
isEqual('/foo bar', '/foo%20bar')
|
||
|
|
||
|
// Strict compare
|
||
|
// Result: false
|
||
|
isEqual('/foo', 'foo', { leadingSlash: true })
|
||
|
isEqual('foo/', 'foo', { trailingSlash: true })
|
||
|
isEqual('/foo bar', '/foo%20bar', { encoding: true })
|
||
|
```
|
||
|
|
||
|
## License
|
||
|
|
||
|
[MIT](./LICENSE)
|
||
|
|
||
|
Special thanks to Eduardo San Martin Morote ([posva](https://github.com/posva)) for [encoding utlities](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-square
|
||
|
[npm-version-href]: https://npmjs.com/package/ufo
|
||
|
|
||
|
[npm-downloads-src]: https://img.shields.io/npm/dm/ufo?style=flat-square
|
||
|
[npm-downloads-href]: https://npmjs.com/package/ufo
|
||
|
|
||
|
[github-actions-src]: https://img.shields.io/github/workflow/status/unjs/ufo/ci/main?style=flat-square
|
||
|
[github-actions-href]: https://github.com/unjs/ufo/actions?query=workflow%3Aci
|
||
|
|
||
|
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/ufo/main?style=flat-square
|
||
|
[codecov-href]: https://codecov.io/gh/unjs/ufo
|
||
|
|
||
|
[bundle-src]: https://img.shields.io/bundlephobia/minzip/ufo?style=flat-square
|
||
|
[bundle-href]: https://bundlephobia.com/result?p=ufo
|