@jridgewell/resolve-uri
Advanced tools
Comparing version 3.0.8 to 3.1.0
@@ -16,4 +16,6 @@ (function (global, factory) { | ||
* 5. Path, including "/", optional. | ||
* 6. Query, including "?", optional. | ||
* 7. Hash, including "#", optional. | ||
*/ | ||
const urlRegex = /^([\w+.-]+:)\/\/([^@/#?]*@)?([^:/#?]*)(:\d+)?(\/[^#?]*)?/; | ||
const urlRegex = /^([\w+.-]+:)\/\/([^@/#?]*@)?([^:/#?]*)(:\d+)?(\/[^#?]*)?(\?[^#]*)?(#.*)?/; | ||
/** | ||
@@ -24,5 +26,17 @@ * File URLs are weird. They dont' need the regular `//` in the scheme, they may or may not start | ||
* 1. Host, optional. | ||
* 2. Path, which may inclue "/", guaranteed. | ||
* 2. Path, which may include "/", guaranteed. | ||
* 3. Query, including "?", optional. | ||
* 4. Hash, including "#", optional. | ||
*/ | ||
const fileRegex = /^file:(?:\/\/((?![a-z]:)[^/]*)?)?(\/?.*)/i; | ||
const fileRegex = /^file:(?:\/\/((?![a-z]:)[^/#?]*)?)?(\/?[^#?]*)(\?[^#]*)?(#.*)?/i; | ||
var UrlType; | ||
(function (UrlType) { | ||
UrlType[UrlType["Empty"] = 1] = "Empty"; | ||
UrlType[UrlType["Hash"] = 2] = "Hash"; | ||
UrlType[UrlType["Query"] = 3] = "Query"; | ||
UrlType[UrlType["RelativePath"] = 4] = "RelativePath"; | ||
UrlType[UrlType["AbsolutePath"] = 5] = "AbsolutePath"; | ||
UrlType[UrlType["SchemeRelative"] = 6] = "SchemeRelative"; | ||
UrlType[UrlType["Absolute"] = 7] = "Absolute"; | ||
})(UrlType || (UrlType = {})); | ||
function isAbsoluteUrl(input) { | ||
@@ -40,5 +54,8 @@ return schemeRegex.test(input); | ||
} | ||
function isRelative(input) { | ||
return /^[.?#]/.test(input); | ||
} | ||
function parseAbsoluteUrl(input) { | ||
const match = urlRegex.exec(input); | ||
return makeUrl(match[1], match[2] || '', match[3], match[4] || '', match[5] || '/'); | ||
return makeUrl(match[1], match[2] || '', match[3], match[4] || '', match[5] || '/', match[6] || '', match[7] || ''); | ||
} | ||
@@ -48,5 +65,5 @@ function parseFileUrl(input) { | ||
const path = match[2]; | ||
return makeUrl('file:', '', match[1] || '', '', isAbsolutePath(path) ? path : '/' + path); | ||
return makeUrl('file:', '', match[1] || '', '', isAbsolutePath(path) ? path : '/' + path, match[3] || '', match[4] || ''); | ||
} | ||
function makeUrl(scheme, user, host, port, path) { | ||
function makeUrl(scheme, user, host, port, path, query, hash) { | ||
return { | ||
@@ -58,3 +75,5 @@ scheme, | ||
path, | ||
relativePath: false, | ||
query, | ||
hash, | ||
type: UrlType.Absolute, | ||
}; | ||
@@ -66,2 +85,3 @@ } | ||
url.scheme = ''; | ||
url.type = UrlType.SchemeRelative; | ||
return url; | ||
@@ -73,2 +93,3 @@ } | ||
url.host = ''; | ||
url.type = UrlType.AbsolutePath; | ||
return url; | ||
@@ -83,3 +104,9 @@ } | ||
url.host = ''; | ||
url.relativePath = true; | ||
url.type = input | ||
? input.startsWith('?') | ||
? UrlType.Query | ||
: input.startsWith('#') | ||
? UrlType.Hash | ||
: UrlType.RelativePath | ||
: UrlType.Empty; | ||
return url; | ||
@@ -96,6 +123,3 @@ } | ||
function mergePaths(url, base) { | ||
// If we're not a relative path, then we're an absolute path, and it doesn't matter what base is. | ||
if (!url.relativePath) | ||
return; | ||
normalizePath(base); | ||
normalizePath(base, base.type); | ||
// If the path is just a "/", then it was an empty path to begin with (remember, we're a relative | ||
@@ -110,4 +134,2 @@ // path). | ||
} | ||
// If the base path is absolute, then our path is now absolute too. | ||
url.relativePath = base.relativePath; | ||
} | ||
@@ -118,4 +140,4 @@ /** | ||
*/ | ||
function normalizePath(url) { | ||
const { relativePath } = url; | ||
function normalizePath(url, type) { | ||
const rel = type <= UrlType.RelativePath; | ||
const pieces = url.path.split('/'); | ||
@@ -152,3 +174,3 @@ // We need to preserve the first piece always, so that we output a leading slash. The item at | ||
} | ||
else if (relativePath) { | ||
else if (rel) { | ||
// If we're in a relativePath, then we need to keep the excess parents. Else, in an absolute | ||
@@ -181,33 +203,56 @@ // URL, protocol relative URL, or an absolute path, we don't need to keep excess. | ||
const url = parseUrl(input); | ||
// If we have a base, and the input isn't already an absolute URL, then we need to merge. | ||
if (base && !url.scheme) { | ||
let inputType = url.type; | ||
if (base && inputType !== UrlType.Absolute) { | ||
const baseUrl = parseUrl(base); | ||
url.scheme = baseUrl.scheme; | ||
// If there's no host, then we were just a path. | ||
if (!url.host) { | ||
// The host, user, and port are joined, you can't copy one without the others. | ||
url.user = baseUrl.user; | ||
url.host = baseUrl.host; | ||
url.port = baseUrl.port; | ||
const baseType = baseUrl.type; | ||
switch (inputType) { | ||
case UrlType.Empty: | ||
url.hash = baseUrl.hash; | ||
// fall through | ||
case UrlType.Hash: | ||
url.query = baseUrl.query; | ||
// fall through | ||
case UrlType.Query: | ||
case UrlType.RelativePath: | ||
mergePaths(url, baseUrl); | ||
// fall through | ||
case UrlType.AbsolutePath: | ||
// The host, user, and port are joined, you can't copy one without the others. | ||
url.user = baseUrl.user; | ||
url.host = baseUrl.host; | ||
url.port = baseUrl.port; | ||
// fall through | ||
case UrlType.SchemeRelative: | ||
// The input doesn't have a schema at least, so we need to copy at least that over. | ||
url.scheme = baseUrl.scheme; | ||
} | ||
mergePaths(url, baseUrl); | ||
if (baseType > inputType) | ||
inputType = baseType; | ||
} | ||
normalizePath(url); | ||
// If the input (and base, if there was one) are both relative, then we need to output a relative. | ||
if (url.relativePath) { | ||
// The first char is always a "/". | ||
const path = url.path.slice(1); | ||
if (!path) | ||
return '.'; | ||
// If base started with a leading ".", or there is no base and input started with a ".", then we | ||
// need to ensure that the relative path starts with a ".". We don't know if relative starts | ||
// with a "..", though, so check before prepending. | ||
const keepRelative = (base || input).startsWith('.'); | ||
return !keepRelative || path.startsWith('.') ? path : './' + path; | ||
normalizePath(url, inputType); | ||
const queryHash = url.query + url.hash; | ||
switch (inputType) { | ||
// This is impossible, because of the empty checks at the start of the function. | ||
// case UrlType.Empty: | ||
case UrlType.Hash: | ||
case UrlType.Query: | ||
return queryHash; | ||
case UrlType.RelativePath: { | ||
// The first char is always a "/", and we need it to be relative. | ||
const path = url.path.slice(1); | ||
if (!path) | ||
return queryHash || '.'; | ||
if (isRelative(base || input) && !isRelative(path)) { | ||
// If base started with a leading ".", or there is no base and input started with a ".", | ||
// then we need to ensure that the relative path starts with a ".". We don't know if | ||
// relative starts with a "..", though, so check before prepending. | ||
return './' + path + queryHash; | ||
} | ||
return path + queryHash; | ||
} | ||
case UrlType.AbsolutePath: | ||
return url.path + queryHash; | ||
default: | ||
return url.scheme + '//' + url.user + url.host + url.port + url.path + queryHash; | ||
} | ||
// If there's no host (and no scheme/user/port), then we need to output an absolute path. | ||
if (!url.scheme && !url.host) | ||
return url.path; | ||
// We're outputting either an absolute URL, or a protocol relative one. | ||
return `${url.scheme}//${url.user}${url.host}${url.port}${url.path}`; | ||
} | ||
@@ -214,0 +259,0 @@ |
{ | ||
"name": "@jridgewell/resolve-uri", | ||
"version": "3.0.8", | ||
"version": "3.1.0", | ||
"description": "Resolve a URI relative to an optional base URI", | ||
@@ -30,3 +30,2 @@ "keywords": [ | ||
"files": [ | ||
"src", | ||
"dist" | ||
@@ -58,2 +57,3 @@ ], | ||
"devDependencies": { | ||
"@jridgewell/resolve-uri-latest": "npm:@jridgewell/resolve-uri@*", | ||
"@rollup/plugin-typescript": "8.3.0", | ||
@@ -60,0 +60,0 @@ "@typescript-eslint/eslint-plugin": "5.10.0", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
55156
12
8
492