bare-url 0.0.0 → 0.1.1
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 +3 -3
- package/index.js +218 -4
- package/lib/constants.js +25 -0
- package/lib/errors.js +47 -0
- package/lib/infra.js +39 -0
- package/lib/parse.js +602 -0
- package/lib/serialize.js +49 -0
- package/package.json +13 -9
- package/.github/workflows/ci.yml +0 -23
- package/NOTICE +0 -13
- package/test.js +0 -6
package/README.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# bare-url
|
|
2
2
|
|
|
3
|
-
URL parser for
|
|
3
|
+
URL parser for JavaScript.
|
|
4
4
|
|
|
5
5
|
```
|
|
6
|
-
npm
|
|
6
|
+
npm i bare-url
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
11
|
-
```
|
|
11
|
+
```js
|
|
12
12
|
const url = require('bare-url')
|
|
13
13
|
|
|
14
14
|
const p = url.fileURLToPath('file:///foo') // --> /foo
|
package/index.js
CHANGED
|
@@ -1,8 +1,222 @@
|
|
|
1
1
|
const path = require('path')
|
|
2
|
+
const constants = require('./lib/constants')
|
|
3
|
+
const errors = require('./lib/errors')
|
|
4
|
+
const parse = require('./lib/parse')
|
|
5
|
+
const serialize = require('./lib/serialize')
|
|
2
6
|
|
|
3
|
-
exports.
|
|
7
|
+
const URL = exports.URL = class URL {
|
|
8
|
+
constructor (href, base) {
|
|
9
|
+
if (typeof base === 'string') {
|
|
10
|
+
try {
|
|
11
|
+
base = new URL(base)
|
|
12
|
+
} catch (err) {
|
|
13
|
+
err.message = 'Invalid base URL'
|
|
14
|
+
throw err
|
|
15
|
+
}
|
|
16
|
+
}
|
|
4
17
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
18
|
+
this._url = parse(href, base ? base._url : null)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// https://url.spec.whatwg.org/#dom-url-href
|
|
22
|
+
|
|
23
|
+
get href () {
|
|
24
|
+
return serialize(this._url)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
set href (value) {
|
|
28
|
+
this._url = parse(value)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// https://url.spec.whatwg.org/#dom-url-protocol
|
|
32
|
+
|
|
33
|
+
get protocol () {
|
|
34
|
+
return `${this._url.scheme}:`
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
set protocol (value) {
|
|
38
|
+
parse(`${value}:`, null, this._url, constants.STATE_SCHEME_START)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// https://url.spec.whatwg.org/#dom-url-username
|
|
42
|
+
|
|
43
|
+
get username () {
|
|
44
|
+
return this._url.username
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
set username (value) {
|
|
48
|
+
if (this._url.host === null || this._url.host === '' || this._url.scheme === 'file') {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this._url.username = encodeURIComponent(value)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// https://url.spec.whatwg.org/#dom-url-password
|
|
56
|
+
|
|
57
|
+
get password () {
|
|
58
|
+
return this._url.password
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
set password (value) {
|
|
62
|
+
if (this._url.host === null || this._url.host === '' || this._url.scheme === 'file') {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this._url.password = encodeURIComponent(value)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// https://url.spec.whatwg.org/#dom-url-host
|
|
70
|
+
|
|
71
|
+
get host () {
|
|
72
|
+
if (this._url.host === null) return ''
|
|
73
|
+
if (this._url.port === null) return this._url.host
|
|
74
|
+
|
|
75
|
+
return `${this._url.host}:${this._url.port}`
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
set host (value) {
|
|
79
|
+
if (typeof this._url.path === 'string') return
|
|
80
|
+
|
|
81
|
+
parse(value, null, this._url, constants.STATE_HOST)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// https://url.spec.whatwg.org/#dom-url-hostname
|
|
85
|
+
|
|
86
|
+
get hostname () {
|
|
87
|
+
if (this._url.host === null) return ''
|
|
88
|
+
|
|
89
|
+
return this._url.host
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
set hostname (value) {
|
|
93
|
+
if (typeof this._url.path === 'string') return
|
|
94
|
+
|
|
95
|
+
parse(value, null, this._url, constants.STATE_HOSTNAME)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// https://url.spec.whatwg.org/#dom-url-port
|
|
99
|
+
|
|
100
|
+
get port () {
|
|
101
|
+
if (this._url.port === null) return ''
|
|
102
|
+
|
|
103
|
+
return `${this._url.port}`
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
set port (value) {
|
|
107
|
+
if (this._url.host === null || this._url.host === '' || this._url.scheme === 'file') {
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (value === '') {
|
|
112
|
+
this._url.port = null
|
|
113
|
+
} else {
|
|
114
|
+
parse(value, null, this._url, constants.STATE_PORT)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// https://url.spec.whatwg.org/#dom-url-pathname
|
|
119
|
+
|
|
120
|
+
get pathname () {
|
|
121
|
+
if (typeof this._url.path === 'string') return this._url.path
|
|
122
|
+
|
|
123
|
+
let output = ''
|
|
124
|
+
|
|
125
|
+
for (const segment of this._url.path) output += `/${segment}`
|
|
126
|
+
|
|
127
|
+
return output
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
set pathname (value) {
|
|
131
|
+
if (typeof this._url.path === 'string') return
|
|
132
|
+
|
|
133
|
+
this._url.path = []
|
|
134
|
+
|
|
135
|
+
parse(value, null, this._url, constants.STATE_PATH_START)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// https://url.spec.whatwg.org/#dom-url-search
|
|
139
|
+
|
|
140
|
+
get search () {
|
|
141
|
+
if (this._url.query === null || this._url.query === '') return ''
|
|
142
|
+
|
|
143
|
+
return `?${this._url.query}`
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
set search (value) {
|
|
147
|
+
if (value === '') {
|
|
148
|
+
this._url.query = null
|
|
149
|
+
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (value.charCodeAt(0) === 0x3f) {
|
|
154
|
+
value = value.substring(1)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
this._url.query = ''
|
|
158
|
+
|
|
159
|
+
parse(value, null, this._url, constants.STATE_QUERY)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// https://url.spec.whatwg.org/#dom-url-hash
|
|
163
|
+
|
|
164
|
+
get hash () {
|
|
165
|
+
if (this._url.fragment === null || this._url.fragment === '') return ''
|
|
166
|
+
|
|
167
|
+
return `#${this._url.fragment}`
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
set hash (value) {
|
|
171
|
+
if (value === '') {
|
|
172
|
+
this._url.fragment = null
|
|
173
|
+
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (value.charCodeAt(0) === 0x23) {
|
|
178
|
+
value = value.substring(1)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
this._url.fragment = ''
|
|
182
|
+
|
|
183
|
+
parse(value, null, this._url, constants.STATE_FRAGMENT)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
[Symbol.for('bare.inspect')] () {
|
|
187
|
+
return {
|
|
188
|
+
__proto__: { constructor: URL },
|
|
189
|
+
|
|
190
|
+
href: this.href,
|
|
191
|
+
protocol: this.protocol,
|
|
192
|
+
username: this.username,
|
|
193
|
+
password: this.password,
|
|
194
|
+
host: this.host,
|
|
195
|
+
hostname: this.hostname,
|
|
196
|
+
port: this.port,
|
|
197
|
+
pathname: this.pathname,
|
|
198
|
+
search: this.search,
|
|
199
|
+
hash: this.hash
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
exports.fileURLToPath = function fileURLToPath (url) {
|
|
205
|
+
if (typeof url === 'string') {
|
|
206
|
+
url = new URL(url)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (url.protocol !== 'file:') {
|
|
210
|
+
throw errors.INVALID_URL_SCHEME('The URL must use the file: protocol')
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const pathname = path.normalize(decodeURIComponent(url.pathname))
|
|
214
|
+
|
|
215
|
+
if (process.platform === 'win32') {
|
|
216
|
+
if (url.hostname) return `\\\\${url.hostname}${pathname}`
|
|
217
|
+
|
|
218
|
+
return pathname.slice(1)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return pathname
|
|
8
222
|
}
|
package/lib/constants.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
// Parser states
|
|
3
|
+
// https://url.spec.whatwg.org/#url-parsing
|
|
4
|
+
STATE_SCHEME_START: 1,
|
|
5
|
+
STATE_SCHEME: 2,
|
|
6
|
+
STATE_NO_SCHEME: 3,
|
|
7
|
+
STATE_SPECIAL_RELATIVE_OR_AUTHORITY: 4,
|
|
8
|
+
STATE_PATH_OR_AUTHORITY: 5,
|
|
9
|
+
STATE_RELATIVE: 6,
|
|
10
|
+
STATE_RELATIVE_SLASH: 7,
|
|
11
|
+
STATE_SPECIAL_AUTHORITY_SLASHES: 8,
|
|
12
|
+
STATE_SPECIAL_AUTHORITY_IGNORE_SLASHES: 9,
|
|
13
|
+
STATE_AUTHORITY: 10,
|
|
14
|
+
STATE_HOST: 11,
|
|
15
|
+
STATE_HOSTNAME: 12,
|
|
16
|
+
STATE_PORT: 13,
|
|
17
|
+
STATE_FILE: 14,
|
|
18
|
+
STATE_FILE_SLASH: 15,
|
|
19
|
+
STATE_FILE_HOST: 16,
|
|
20
|
+
STATE_PATH_START: 17,
|
|
21
|
+
STATE_PATH: 18,
|
|
22
|
+
STATE_OPAQUE_PATH: 19,
|
|
23
|
+
STATE_QUERY: 20,
|
|
24
|
+
STATE_FRAGMENT: 21
|
|
25
|
+
}
|
package/lib/errors.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module.exports = class URLError extends Error {
|
|
2
|
+
constructor (msg, code, fn = URLError) {
|
|
3
|
+
super(`${code}: ${msg}`)
|
|
4
|
+
this.code = code
|
|
5
|
+
|
|
6
|
+
if (Error.captureStackTrace) {
|
|
7
|
+
Error.captureStackTrace(this, fn)
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get name () {
|
|
12
|
+
return 'URLError'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static INVALID_URL (msg = 'Invalid URL') {
|
|
16
|
+
return new URLError(msg, 'INVALID_URL', URLError.INVALID_URL)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static INVALID_URL_SCHEME (msg = 'Invalid URL') {
|
|
20
|
+
return new URLError(msg, 'INVALID_URL_SCHEME', URLError.INVALID_URL_SCHEME)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// https://url.spec.whatwg.org/#missing-scheme-non-relative-url
|
|
24
|
+
static MISSING_SCHEME_NON_RELATIVE_URL (msg = 'Invalid URL') {
|
|
25
|
+
return new URLError(msg, 'MISSING_SCHEME_NON_RELATIVE_URL', URLError.MISSING_SCHEME_NON_RELATIVE_URL)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// https://url.spec.whatwg.org/#invalid-credentials
|
|
29
|
+
static INVALID_CREDENTIALS (msg = 'Invalid URL') {
|
|
30
|
+
return new URLError(msg, 'INVALID_CREDENTIALS', URLError.INVALID_CREDENTIALS)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// https://url.spec.whatwg.org/#host-missing
|
|
34
|
+
static HOST_MISSING (msg = 'Invalid URL') {
|
|
35
|
+
return new URLError(msg, 'HOST_MISSING', URLError.HOST_MISSING)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// https://url.spec.whatwg.org/#port-out-of-range
|
|
39
|
+
static PORT_OUT_OF_RANGE (msg = 'Invalid URL') {
|
|
40
|
+
return new URLError(msg, 'PORT_OUT_OF_RANGE', URLError.PORT_OUT_OF_RANGE)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// https://url.spec.whatwg.org/#port-invalid
|
|
44
|
+
static PORT_INVALID (msg = 'Invalid URL') {
|
|
45
|
+
return new URLError(msg, 'PORT_INVALID', URLError.PORT_INVALID)
|
|
46
|
+
}
|
|
47
|
+
}
|
package/lib/infra.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// https://infra.spec.whatwg.org/#ascii-digit
|
|
2
|
+
exports.isASCIIDigit = function isASCIIDigit (c) {
|
|
3
|
+
return c >= 0x30 && c <= 0x39
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// https://infra.spec.whatwg.org/#ascii-upper-hex-digit
|
|
7
|
+
exports.isASCIIUpperHexDigit = function isASCIIUpperHexDigit (c) {
|
|
8
|
+
return exports.isASCIIDigit(c) || (c >= 0x41 && c <= 0x46)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// https://infra.spec.whatwg.org/#ascii-lower-hex-digit
|
|
12
|
+
exports.isASCIILowerHexDigit = function isASCIILowerHexDigit (c) {
|
|
13
|
+
return exports.isASCIIDigit(c) || (c >= 0x61 && c <= 0x66)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// https://infra.spec.whatwg.org/#ascii-hex-digit
|
|
17
|
+
exports.isASCIIHexDigit = function isASCIIHexDigit (c) {
|
|
18
|
+
return exports.isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// https://infra.spec.whatwg.org/#ascii-upper-alpha
|
|
22
|
+
exports.isASCIIUpperAlpha = function isASCIIUpperAlpha (c) {
|
|
23
|
+
return c >= 0x41 && c <= 0x5a
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// https://infra.spec.whatwg.org/#ascii-lower-alpha
|
|
27
|
+
exports.isASCIILowerAlpha = function isASCIILowerAlpha (c) {
|
|
28
|
+
return c >= 0x61 && c <= 0x7a
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// https://infra.spec.whatwg.org/#ascii-alpha
|
|
32
|
+
exports.isASCIIAlpha = function isASCIIAlpha (c) {
|
|
33
|
+
return exports.isASCIIUpperAlpha(c) || exports.isASCIILowerAlpha(c)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// https://infra.spec.whatwg.org/#ascii-alphanumeric
|
|
37
|
+
exports.isASCIIAlphanumeric = function isASCIIAlphanumeric (c) {
|
|
38
|
+
return exports.isASCIIDigit(c) || exports.isASCIIAlpha(c)
|
|
39
|
+
}
|
package/lib/parse.js
ADDED
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
const constants = require('./constants')
|
|
2
|
+
const errors = require('./errors')
|
|
3
|
+
const infra = require('./infra')
|
|
4
|
+
|
|
5
|
+
// https://url.spec.whatwg.org/#url-parsing
|
|
6
|
+
module.exports = function parse (
|
|
7
|
+
input,
|
|
8
|
+
base = null,
|
|
9
|
+
// https://url.spec.whatwg.org/#url-representation
|
|
10
|
+
url = {
|
|
11
|
+
scheme: '',
|
|
12
|
+
username: '',
|
|
13
|
+
password: '',
|
|
14
|
+
host: null,
|
|
15
|
+
port: null,
|
|
16
|
+
path: [],
|
|
17
|
+
query: null,
|
|
18
|
+
fragment: null
|
|
19
|
+
},
|
|
20
|
+
stateOverride = 0
|
|
21
|
+
) {
|
|
22
|
+
let state = stateOverride || constants.STATE_SCHEME_START
|
|
23
|
+
let buffer = ''
|
|
24
|
+
let atSignSeen = false
|
|
25
|
+
let insideBrackets = false
|
|
26
|
+
let passwordTokenSeen = false
|
|
27
|
+
|
|
28
|
+
for (let pointer = 0; pointer <= input.length; pointer++) {
|
|
29
|
+
const c = pointer < input.length ? input.charCodeAt(pointer) : -1
|
|
30
|
+
|
|
31
|
+
switch (state) {
|
|
32
|
+
// https://url.spec.whatwg.org/#scheme-start-state
|
|
33
|
+
case constants.STATE_SCHEME_START:
|
|
34
|
+
if (infra.isASCIIAlpha(c)) {
|
|
35
|
+
buffer += String.fromCharCode(c).toLowerCase()
|
|
36
|
+
state = constants.STATE_SCHEME
|
|
37
|
+
} else if (!stateOverride) {
|
|
38
|
+
state = constants.STATE_NO_SCHEME
|
|
39
|
+
pointer--
|
|
40
|
+
} else {
|
|
41
|
+
throw errors.INVALID_URL()
|
|
42
|
+
}
|
|
43
|
+
break
|
|
44
|
+
|
|
45
|
+
// https://url.spec.whatwg.org/#scheme-state
|
|
46
|
+
case constants.STATE_SCHEME:
|
|
47
|
+
if (infra.isASCIIAlphanumeric(c) || c === 0x2b || c === 0x2d || c === 0x2e) {
|
|
48
|
+
buffer += String.fromCharCode(c).toLowerCase()
|
|
49
|
+
} else if (c === 0x3a) {
|
|
50
|
+
if (stateOverride) {
|
|
51
|
+
if (isSpecialScheme(url.scheme) && !isSpecialScheme(buffer)) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!isSpecialScheme(url.scheme) && isSpecialScheme(buffer)) {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if ((includesCredentials(url) || url.port !== null) && buffer === 'file') {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (url.scheme === 'file' && url.host === '') {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
url.scheme = buffer
|
|
69
|
+
|
|
70
|
+
if (stateOverride) {
|
|
71
|
+
if (url.port === defaultPort(url.scheme)) {
|
|
72
|
+
url.port = null
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
buffer = ''
|
|
79
|
+
|
|
80
|
+
if (url.scheme === 'file') {
|
|
81
|
+
state = constants.STATE_FILE
|
|
82
|
+
} else if (isSpecial(url)) {
|
|
83
|
+
if (base && base.scheme === url.scheme) {
|
|
84
|
+
state = constants.STATE_SPECIAL_RELATIVE_OR_AUTHORITY
|
|
85
|
+
} else {
|
|
86
|
+
state = constants.STATE_SPECIAL_AUTHORITY_SLASHES
|
|
87
|
+
}
|
|
88
|
+
} else if (input.charCodeAt(pointer + 1) === 0x2f) {
|
|
89
|
+
state = constants.STATE_PATH_OR_AUTHORITY
|
|
90
|
+
pointer++
|
|
91
|
+
} else {
|
|
92
|
+
url.path = ''
|
|
93
|
+
state = constants.STATE_OPAQUE_PATH
|
|
94
|
+
}
|
|
95
|
+
} else if (!stateOverride) {
|
|
96
|
+
buffer = ''
|
|
97
|
+
state = constants.STATE_NO_SCHEME
|
|
98
|
+
pointer = 0
|
|
99
|
+
} else {
|
|
100
|
+
throw errors.INVALID_URL()
|
|
101
|
+
}
|
|
102
|
+
break
|
|
103
|
+
|
|
104
|
+
// https://url.spec.whatwg.org/#no-scheme-state
|
|
105
|
+
case constants.STATE_NO_SCHEME:
|
|
106
|
+
if (base === null || (hasOpaquePath(base) && c !== 0x23)) {
|
|
107
|
+
throw errors.MISSING_SCHEME_NON_RELATIVE_URL()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (hasOpaquePath(base) && c === 0x23) {
|
|
111
|
+
url.scheme = base.scheme
|
|
112
|
+
url.path = base.path
|
|
113
|
+
url.query = base.query
|
|
114
|
+
url.fragment = ''
|
|
115
|
+
state = constants.STATE_FRAGMENT
|
|
116
|
+
} else if (base.sceheme !== 'file') {
|
|
117
|
+
state = constants.STATE_RELATIVE
|
|
118
|
+
pointer--
|
|
119
|
+
} else {
|
|
120
|
+
state = constants.STATE_FILE
|
|
121
|
+
pointer++
|
|
122
|
+
}
|
|
123
|
+
break
|
|
124
|
+
|
|
125
|
+
// https://url.spec.whatwg.org/#special-relative-or-authority-state
|
|
126
|
+
case constants.STATE_SPECIAL_RELATIVE_OR_AUTHORITY:
|
|
127
|
+
if (c === 0x2f && input.charCodeAt(pointer + 1) === 0x2f) {
|
|
128
|
+
state = constants.STATE_SPECIAL_AUTHORITY_IGNORE_SLASHES
|
|
129
|
+
pointer++
|
|
130
|
+
} else {
|
|
131
|
+
state = constants.STATE_RELATIVE
|
|
132
|
+
pointer--
|
|
133
|
+
}
|
|
134
|
+
break
|
|
135
|
+
|
|
136
|
+
// https://url.spec.whatwg.org/#path-or-authority-state
|
|
137
|
+
case constants.STATE_PATH_OR_AUTHORITY:
|
|
138
|
+
if (c === 0x2f) {
|
|
139
|
+
state = constants.STATE_AUTHORITY
|
|
140
|
+
} else {
|
|
141
|
+
state = constants.STATE_PATH
|
|
142
|
+
pointer--
|
|
143
|
+
}
|
|
144
|
+
break
|
|
145
|
+
|
|
146
|
+
// https://url.spec.whatwg.org/#relative-state
|
|
147
|
+
case constants.STATE_RELATIVE:
|
|
148
|
+
url.scheme = base.scheme
|
|
149
|
+
|
|
150
|
+
if (c === 0x2f) {
|
|
151
|
+
state = constants.STATE_RELATIVE_SLASH
|
|
152
|
+
} else if (isSpecial(url) && c === 0x5c) {
|
|
153
|
+
state = constants.STATE_RELATIVE_SLASH
|
|
154
|
+
} else {
|
|
155
|
+
url.username = base.username
|
|
156
|
+
url.password = base.password
|
|
157
|
+
url.host = base.host
|
|
158
|
+
url.port = base.port
|
|
159
|
+
url.path = [...base.path]
|
|
160
|
+
url.query = base.query
|
|
161
|
+
|
|
162
|
+
if (c === 0x3f) {
|
|
163
|
+
url.query = ''
|
|
164
|
+
state = constants.STATE_QUERY
|
|
165
|
+
} else if (c === 0x23) {
|
|
166
|
+
url.fragment = ''
|
|
167
|
+
state = constants.STATE_FRAGMENT
|
|
168
|
+
} else if (c !== -1) {
|
|
169
|
+
url.query = null
|
|
170
|
+
shortenPath(url)
|
|
171
|
+
state = constants.STATE_PATH
|
|
172
|
+
pointer--
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
break
|
|
176
|
+
|
|
177
|
+
// https://url.spec.whatwg.org/#relative-slash-state
|
|
178
|
+
case constants.STATE_RELATIVE_SLASH:
|
|
179
|
+
if (isSpecial(url) && (c === 0x2f || c === 0x5c)) {
|
|
180
|
+
state = constants.STATE_SPECIAL_AUTHORITY_IGNORE_SLASHES
|
|
181
|
+
} else if (c === 0x2f) {
|
|
182
|
+
state = constants.STATE_AUTHORITY
|
|
183
|
+
} else {
|
|
184
|
+
url.username = base.username
|
|
185
|
+
url.password = base.password
|
|
186
|
+
url.host = base.url
|
|
187
|
+
url.port = base.port
|
|
188
|
+
state = constants.STATE_PATH
|
|
189
|
+
pointer--
|
|
190
|
+
}
|
|
191
|
+
break
|
|
192
|
+
|
|
193
|
+
// https://url.spec.whatwg.org/#special-authority-slashes-state
|
|
194
|
+
case constants.STATE_SPECIAL_AUTHORITY_SLASHES:
|
|
195
|
+
if (c === 0x2f && input.charCodeAt(pointer + 1) === 0x2f) {
|
|
196
|
+
state = constants.STATE_SPECIAL_AUTHORITY_IGNORE_SLASHES
|
|
197
|
+
pointer++
|
|
198
|
+
} else {
|
|
199
|
+
state = constants.STATE_SPECIAL_AUTHORITY_IGNORE_SLASHES
|
|
200
|
+
pointer--
|
|
201
|
+
}
|
|
202
|
+
break
|
|
203
|
+
|
|
204
|
+
// https://url.spec.whatwg.org/#special-authority-ignore-slashes-state
|
|
205
|
+
case constants.STATE_SPECIAL_AUTHORITY_IGNORE_SLASHES:
|
|
206
|
+
if (c !== 0x2f || c !== 0x5c) {
|
|
207
|
+
state = constants.STATE_AUTHORITY
|
|
208
|
+
pointer--
|
|
209
|
+
}
|
|
210
|
+
break
|
|
211
|
+
|
|
212
|
+
// https://url.spec.whatwg.org/#authority-state
|
|
213
|
+
case constants.STATE_AUTHORITY:
|
|
214
|
+
if (c === 0x40) {
|
|
215
|
+
if (atSignSeen) buffer = '%40' + buffer
|
|
216
|
+
|
|
217
|
+
atSignSeen = true
|
|
218
|
+
|
|
219
|
+
for (let i = 0, n = buffer.length; i < n; i++) {
|
|
220
|
+
const c = buffer.charCodeAt(i)
|
|
221
|
+
|
|
222
|
+
if (c === 0x3a && !passwordTokenSeen) {
|
|
223
|
+
passwordTokenSeen = true
|
|
224
|
+
continue
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (passwordTokenSeen) {
|
|
228
|
+
url.password += encodeURIComponent(buffer[i])
|
|
229
|
+
} else {
|
|
230
|
+
url.username += encodeURIComponent(buffer[i])
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
buffer = ''
|
|
235
|
+
} else if (
|
|
236
|
+
(c === -1 || c === 0x2f || c === 0x3f || c === 0x23) ||
|
|
237
|
+
(isSpecial(url) && c === 0x5c)
|
|
238
|
+
) {
|
|
239
|
+
if (atSignSeen && buffer === '') {
|
|
240
|
+
throw errors.INVALID_CREDENTIALS()
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
pointer -= buffer.length + 1
|
|
244
|
+
buffer = ''
|
|
245
|
+
state = constants.STATE_HOST
|
|
246
|
+
} else {
|
|
247
|
+
buffer += String.fromCharCode(c)
|
|
248
|
+
}
|
|
249
|
+
break
|
|
250
|
+
|
|
251
|
+
// https://url.spec.whatwg.org/#host-state
|
|
252
|
+
// https://url.spec.whatwg.org/#hostname-state
|
|
253
|
+
case constants.STATE_HOST:
|
|
254
|
+
case constants.STATE_HOSTNAME:
|
|
255
|
+
if (stateOverride && url.scheme === 'file') {
|
|
256
|
+
pointer--
|
|
257
|
+
state = constants.STATE_FILE_HOST
|
|
258
|
+
} else if (c === 0x3a && !insideBrackets) {
|
|
259
|
+
if (buffer === '') {
|
|
260
|
+
throw errors.HOST_MISSING()
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (stateOverride === constants.STATE_HOSTNAME) return
|
|
264
|
+
|
|
265
|
+
url.host = parseHost(buffer, !isSpecial(url))
|
|
266
|
+
|
|
267
|
+
buffer = ''
|
|
268
|
+
state = constants.STATE_PORT
|
|
269
|
+
} else if (
|
|
270
|
+
(c === -1 || c === 0x2f || c === 0x3f || c === 0x23) ||
|
|
271
|
+
(isSpecial(url) && c === 0x5c)
|
|
272
|
+
) {
|
|
273
|
+
pointer--
|
|
274
|
+
|
|
275
|
+
if (isSpecial(url) && buffer === '') {
|
|
276
|
+
throw errors.HOST_MISSING()
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (stateOverride && buffer === '' && (includesCredentials(url) || url.port !== null)) {
|
|
280
|
+
return
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
url.host = parseHost(buffer, !isSpecial(url))
|
|
284
|
+
|
|
285
|
+
buffer = ''
|
|
286
|
+
state = constants.STATE_PATH_START
|
|
287
|
+
|
|
288
|
+
if (stateOverride) return
|
|
289
|
+
} else {
|
|
290
|
+
if (c === 0x5b) insideBrackets = true
|
|
291
|
+
else if (c === 0x5d) insideBrackets = false
|
|
292
|
+
|
|
293
|
+
buffer += String.fromCharCode(c)
|
|
294
|
+
}
|
|
295
|
+
break
|
|
296
|
+
|
|
297
|
+
// https://url.spec.whatwg.org/#port-state
|
|
298
|
+
case constants.STATE_PORT:
|
|
299
|
+
if (infra.isASCIIDigit(c)) {
|
|
300
|
+
buffer += String.fromCharCode(c)
|
|
301
|
+
} else if (
|
|
302
|
+
(c === -1 || c === 0x2f || c === 0x3f || c === 0x23) ||
|
|
303
|
+
(isSpecial(url) && c === 0x5c) ||
|
|
304
|
+
stateOverride
|
|
305
|
+
) {
|
|
306
|
+
if (buffer) {
|
|
307
|
+
const port = parseInt(buffer, 10)
|
|
308
|
+
|
|
309
|
+
if (port > 2 ** 16 - 1) {
|
|
310
|
+
throw errors.PORT_OUT_OF_RANGE()
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
url.port = port === defaultPort(url.scheme) ? null : port
|
|
314
|
+
|
|
315
|
+
buffer = ''
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (stateOverride) return
|
|
319
|
+
|
|
320
|
+
state = constants.STATE_PATH_START
|
|
321
|
+
pointer--
|
|
322
|
+
} else {
|
|
323
|
+
throw errors.PORT_INVALID()
|
|
324
|
+
}
|
|
325
|
+
break
|
|
326
|
+
|
|
327
|
+
// https://url.spec.whatwg.org/#file-state
|
|
328
|
+
case constants.STATE_FILE:
|
|
329
|
+
url.scheme = 'file'
|
|
330
|
+
url.host = ''
|
|
331
|
+
|
|
332
|
+
if (c === 0x2f || c === 0x5c) {
|
|
333
|
+
state = constants.STATE_FILE_SLASH
|
|
334
|
+
} else if (base && base.scheme === 'file') {
|
|
335
|
+
url.host = base.host
|
|
336
|
+
url.path = [...base.path]
|
|
337
|
+
url.query = base.query
|
|
338
|
+
|
|
339
|
+
if (c === 0x3f) {
|
|
340
|
+
url.query = ''
|
|
341
|
+
state = constants.STATE_QUERY
|
|
342
|
+
} else if (c === 0x23) {
|
|
343
|
+
url.fragment = ''
|
|
344
|
+
state = constants.STATE_FRAGMENT
|
|
345
|
+
} else if (c !== -1) {
|
|
346
|
+
url.query = null
|
|
347
|
+
|
|
348
|
+
if (!startsWithWindowsDriveLetter(input.substring(pointer))) {
|
|
349
|
+
shortenPath(url)
|
|
350
|
+
} else {
|
|
351
|
+
url.path = []
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
state = constants.STATE_PATH
|
|
355
|
+
pointer--
|
|
356
|
+
}
|
|
357
|
+
} else {
|
|
358
|
+
state = constants.STATE_PATH
|
|
359
|
+
pointer--
|
|
360
|
+
}
|
|
361
|
+
break
|
|
362
|
+
|
|
363
|
+
// https://url.spec.whatwg.org/#file-slash-state
|
|
364
|
+
case constants.STATE_FILE_SLASH:
|
|
365
|
+
if (c === 0x2f || c === 0x5c) {
|
|
366
|
+
state = constants.STATE_FILE_HOST
|
|
367
|
+
} else {
|
|
368
|
+
if (base && base.scheme === 'file') {
|
|
369
|
+
url.host = base.host
|
|
370
|
+
|
|
371
|
+
if (!startsWithWindowsDriveLetter(input.substring(pointer)) && isNormalizedWindowsDriveLetter(base.path[0])) {
|
|
372
|
+
url.path.push(base.path[0])
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
state = constants.STATE_PATH
|
|
377
|
+
pointer--
|
|
378
|
+
}
|
|
379
|
+
break
|
|
380
|
+
|
|
381
|
+
// https://url.spec.whatwg.org/#file-host-state
|
|
382
|
+
case constants.STATE_FILE_HOST:
|
|
383
|
+
if (c === -1 || c === 0x2f || c === 0x5c || c === 0x3f || c === 0x23) {
|
|
384
|
+
pointer--
|
|
385
|
+
|
|
386
|
+
if (!stateOverride && isWindowsDriveLetter(buffer)) {
|
|
387
|
+
state = constants.STATE_PATH
|
|
388
|
+
} else if (buffer === '') {
|
|
389
|
+
url.host = ''
|
|
390
|
+
|
|
391
|
+
if (stateOverride) return
|
|
392
|
+
|
|
393
|
+
state = constants.STATE_PATH_START
|
|
394
|
+
} else {
|
|
395
|
+
let host = parseHost(buffer, !isSpecial(url))
|
|
396
|
+
if (host === 'localhost') host = ''
|
|
397
|
+
|
|
398
|
+
url.host = host
|
|
399
|
+
|
|
400
|
+
if (stateOverride) return
|
|
401
|
+
|
|
402
|
+
buffer = ''
|
|
403
|
+
state = constants.STATE_PATH_START
|
|
404
|
+
}
|
|
405
|
+
} else {
|
|
406
|
+
buffer += String.fromCharCode(c)
|
|
407
|
+
}
|
|
408
|
+
break
|
|
409
|
+
|
|
410
|
+
// https://url.spec.whatwg.org/#path-start-state
|
|
411
|
+
case constants.STATE_PATH_START:
|
|
412
|
+
if (isSpecial(url)) {
|
|
413
|
+
state = constants.STATE_PATH
|
|
414
|
+
|
|
415
|
+
if (c !== 0x2f || c !== 0x5c) pointer--
|
|
416
|
+
} else if (!stateOverride && c === 0x3f) {
|
|
417
|
+
url.query = ''
|
|
418
|
+
state = constants.STATE_QUERY
|
|
419
|
+
} else if (!stateOverride && c === 0x23) {
|
|
420
|
+
url.fragment = ''
|
|
421
|
+
state = constants.STATE_FRAGMENT
|
|
422
|
+
} else if (c !== -1) {
|
|
423
|
+
state = constants.STATE_PATH
|
|
424
|
+
|
|
425
|
+
if (c !== 0x2f) pointer--
|
|
426
|
+
} else if (stateOverride && url.host === null) {
|
|
427
|
+
url.path.push('')
|
|
428
|
+
}
|
|
429
|
+
break
|
|
430
|
+
|
|
431
|
+
// https://url.spec.whatwg.org/#path-state
|
|
432
|
+
case constants.STATE_PATH:
|
|
433
|
+
if (
|
|
434
|
+
(c === -1 || c === 0x2f) ||
|
|
435
|
+
(isSpecial(url) && c === 0x5c) ||
|
|
436
|
+
(!stateOverride && (c === 0x3f || c === 0x23))
|
|
437
|
+
) {
|
|
438
|
+
if (isDoubleDotPathSegment(buffer)) {
|
|
439
|
+
shortenPath(url)
|
|
440
|
+
|
|
441
|
+
if (c !== 0x2f || !(isSpecial(url) && c === 0x5c)) {
|
|
442
|
+
url.path.push('')
|
|
443
|
+
}
|
|
444
|
+
} else if (isSingleDotPathSegment(buffer)) {
|
|
445
|
+
if (c !== 0x2f || !(isSpecial(url) && c === 0x5c)) {
|
|
446
|
+
url.path.push('')
|
|
447
|
+
}
|
|
448
|
+
} else {
|
|
449
|
+
if (url.scheme === 'file' && url.path.length === 0 && isWindowsDriveLetter(buffer)) {
|
|
450
|
+
buffer[1] = ':'
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
url.path.push(buffer)
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
buffer = ''
|
|
457
|
+
|
|
458
|
+
if (c === 0x3f) {
|
|
459
|
+
url.query = ''
|
|
460
|
+
state = constants.STATE_QUERY
|
|
461
|
+
} else if (c === 0x23) {
|
|
462
|
+
url.fragment = ''
|
|
463
|
+
state = constants.STATE_FRAGMENT
|
|
464
|
+
}
|
|
465
|
+
} else {
|
|
466
|
+
buffer += encodeURIComponent(String.fromCharCode(c))
|
|
467
|
+
}
|
|
468
|
+
break
|
|
469
|
+
|
|
470
|
+
// https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state
|
|
471
|
+
case constants.STATE_OPAQUE_PATH:
|
|
472
|
+
if (c === 0x3f) {
|
|
473
|
+
url.query = ''
|
|
474
|
+
state = constants.STATE_QUERY
|
|
475
|
+
} else if (c === 0x23) {
|
|
476
|
+
url.fragment = ''
|
|
477
|
+
state = constants.STATE_FRAGMENT
|
|
478
|
+
} else {
|
|
479
|
+
if (c !== -1) {
|
|
480
|
+
url.path += encodeURIComponent(String.fromCharCode(c))
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
break
|
|
484
|
+
|
|
485
|
+
// https://url.spec.whatwg.org/#query-state
|
|
486
|
+
case constants.STATE_QUERY:
|
|
487
|
+
if ((!stateOverride && c === 0x23) || c === -1) {
|
|
488
|
+
url.query += encodeURI(buffer)
|
|
489
|
+
buffer = ''
|
|
490
|
+
|
|
491
|
+
if (c === 0x23) {
|
|
492
|
+
url.fragment = ''
|
|
493
|
+
state = constants.STATE_FRAGMENT
|
|
494
|
+
}
|
|
495
|
+
} else if (c !== -1) {
|
|
496
|
+
buffer += String.fromCharCode(c)
|
|
497
|
+
}
|
|
498
|
+
break
|
|
499
|
+
|
|
500
|
+
// https://url.spec.whatwg.org/#fragment-state
|
|
501
|
+
case constants.STATE_FRAGMENT:
|
|
502
|
+
if (c !== -1) {
|
|
503
|
+
url.fragment += encodeURI(String.fromCharCode(c))
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
return url
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// https://url.spec.whatwg.org/#host-parsing
|
|
512
|
+
function parseHost (host, isNotSpecial) {
|
|
513
|
+
return host
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// https://url.spec.whatwg.org/#special-scheme
|
|
517
|
+
function isSpecialScheme (scheme) {
|
|
518
|
+
switch (scheme) {
|
|
519
|
+
case 'ftp':
|
|
520
|
+
case 'file':
|
|
521
|
+
case 'http':
|
|
522
|
+
case 'https':
|
|
523
|
+
case 'ws':
|
|
524
|
+
case 'wss':
|
|
525
|
+
return true
|
|
526
|
+
default:
|
|
527
|
+
return false
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// https://url.spec.whatwg.org/#default-port
|
|
532
|
+
function defaultPort (scheme) {
|
|
533
|
+
switch (scheme) {
|
|
534
|
+
case 'ftp': return 21
|
|
535
|
+
case 'file': return null
|
|
536
|
+
case 'http': return 80
|
|
537
|
+
case 'https': return 443
|
|
538
|
+
case 'ws': return 80
|
|
539
|
+
case 'wss': return 443
|
|
540
|
+
default: return null
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// https://url.spec.whatwg.org/#is-special
|
|
545
|
+
function isSpecial (url) {
|
|
546
|
+
return isSpecialScheme(url)
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// https://url.spec.whatwg.org/#include-credentials
|
|
550
|
+
function includesCredentials (url) {
|
|
551
|
+
return url.username !== '' && url.password !== ''
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// https://url.spec.whatwg.org/#url-opaque-path
|
|
555
|
+
function hasOpaquePath (url) {
|
|
556
|
+
return typeof url.path === 'string'
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// https://url.spec.whatwg.org/#windows-drive-letter
|
|
560
|
+
function isWindowsDriveLetter (input) {
|
|
561
|
+
return input.length >= 2 && infra.isASCIIAlpha(input.charCodeAt(0)) && (
|
|
562
|
+
input.charCodeAt(1) === 0x3a ||
|
|
563
|
+
input.charCodeAt(1) === 0x7c
|
|
564
|
+
)
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// https://url.spec.whatwg.org/#normalized-windows-drive-letter
|
|
568
|
+
function isNormalizedWindowsDriveLetter (input) {
|
|
569
|
+
return input.length >= 2 && infra.isASCIIAlpha(input.charCodeAt(0)) && input.charCodeAt(1) === 0x3a
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
|
|
573
|
+
function startsWithWindowsDriveLetter (input) {
|
|
574
|
+
return input.length >= 2 && isWindowsDriveLetter(input) && (
|
|
575
|
+
input.length === 2 ||
|
|
576
|
+
input.charCodeAt(2) === 0x2f ||
|
|
577
|
+
input.charCodeAt(2) === 0x5c ||
|
|
578
|
+
input.charCodeAt(2) === 0x3f ||
|
|
579
|
+
input.charCodeAt(2) === 0x23
|
|
580
|
+
)
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// https://url.spec.whatwg.org/#shorten-a-urls-path
|
|
584
|
+
function shortenPath (url) {
|
|
585
|
+
const path = url.path
|
|
586
|
+
|
|
587
|
+
if (url.scheme === 'file' && path.length === 1 && isNormalizedWindowsDriveLetter(path[0])) {
|
|
588
|
+
return
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
path.pop()
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// https://url.spec.whatwg.org/#single-dot-path-segment
|
|
595
|
+
function isSingleDotPathSegment (segment) {
|
|
596
|
+
return segment === '.' || decodeURIComponent(segment) === '.'
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// https://url.spec.whatwg.org/#double-dot-path-segment
|
|
600
|
+
function isDoubleDotPathSegment (segment) {
|
|
601
|
+
return segment === '..' || decodeURIComponent(segment) === '..'
|
|
602
|
+
}
|
package/lib/serialize.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// https://url.spec.whatwg.org/#url-serializing
|
|
2
|
+
module.exports = function serialize (url, excludeFragment = false) {
|
|
3
|
+
let output = url.scheme + ':'
|
|
4
|
+
|
|
5
|
+
if (url.host) {
|
|
6
|
+
output += '//'
|
|
7
|
+
|
|
8
|
+
if (url.username !== '' || url.password !== '') {
|
|
9
|
+
output += url.username
|
|
10
|
+
|
|
11
|
+
if (url.password !== '') {
|
|
12
|
+
output += ':' + url.password
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
output += '@'
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
output += url.host
|
|
19
|
+
|
|
20
|
+
if (url.port !== null) {
|
|
21
|
+
output += ':' + url.port.toString(10)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (
|
|
26
|
+
url.host === null &&
|
|
27
|
+
typeof url.path !== 'string' &&
|
|
28
|
+
url.path.length > 1 &&
|
|
29
|
+
url.path[0] === ''
|
|
30
|
+
) {
|
|
31
|
+
output += '/.'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (typeof url.path === 'string') {
|
|
35
|
+
output += url.path
|
|
36
|
+
} else {
|
|
37
|
+
output += '/' + url.path.join('/')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (url.query !== null) {
|
|
41
|
+
output += '?' + url.query
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (url.fragment !== null && !excludeFragment) {
|
|
45
|
+
output += '#' + url.fragment
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return output
|
|
49
|
+
}
|
package/package.json
CHANGED
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bare-url",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "URL parser for
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "URL parser for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"index.js",
|
|
8
|
+
"lib"
|
|
9
|
+
],
|
|
6
10
|
"scripts": {
|
|
7
|
-
"test": "standard &&
|
|
8
|
-
},
|
|
9
|
-
"devDependencies": {
|
|
10
|
-
"standard": "^17.1.0",
|
|
11
|
-
"brittle": "^3.3.2"
|
|
11
|
+
"test": "standard && bare test.js"
|
|
12
12
|
},
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
|
-
"url": "https://github.com/holepunchto/bare-url.git"
|
|
15
|
+
"url": "git+https://github.com/holepunchto/bare-url.git"
|
|
16
16
|
},
|
|
17
17
|
"author": "Holepunch",
|
|
18
18
|
"license": "Apache-2.0",
|
|
19
19
|
"bugs": {
|
|
20
20
|
"url": "https://github.com/holepunchto/bare-url/issues"
|
|
21
21
|
},
|
|
22
|
-
"homepage": "https://github.com/holepunchto/bare-url"
|
|
22
|
+
"homepage": "https://github.com/holepunchto/bare-url",
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"brittle": "^3.3.2",
|
|
25
|
+
"standard": "^17.1.0"
|
|
26
|
+
}
|
|
23
27
|
}
|
package/.github/workflows/ci.yml
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
name: Build Status
|
|
2
|
-
on:
|
|
3
|
-
push:
|
|
4
|
-
branches:
|
|
5
|
-
- main
|
|
6
|
-
pull_request:
|
|
7
|
-
branches:
|
|
8
|
-
- main
|
|
9
|
-
jobs:
|
|
10
|
-
build:
|
|
11
|
-
strategy:
|
|
12
|
-
matrix:
|
|
13
|
-
node-version: [lts/*]
|
|
14
|
-
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
15
|
-
runs-on: ${{ matrix.os }}
|
|
16
|
-
steps:
|
|
17
|
-
- uses: actions/checkout@v2
|
|
18
|
-
- name: Use Node.js ${{ matrix.node-version }}
|
|
19
|
-
uses: actions/setup-node@v2
|
|
20
|
-
with:
|
|
21
|
-
node-version: ${{ matrix.node-version }}
|
|
22
|
-
- run: npm install
|
|
23
|
-
- run: npm test
|
package/NOTICE
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
Copyright 2023 Holepunch Inc
|
|
2
|
-
|
|
3
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
you may not use this file except in compliance with the License.
|
|
5
|
-
You may obtain a copy of the License at
|
|
6
|
-
|
|
7
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
|
|
9
|
-
Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
See the License for the specific language governing permissions and
|
|
13
|
-
limitations under the License.
|