@jridgewell/resolve-uri
Advanced tools
Comparing version 1.0.0 to 2.0.0
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global = global || self, global.resolveURI = factory()); | ||
}(this, function () { 'use strict'; | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.resolveURI = factory()); | ||
}(this, (function () { 'use strict'; | ||
/* istanbul ignore next */ | ||
const Url = (typeof URL !== 'undefined' ? URL : require('url').URL); | ||
// Matches "..", which must be preceeded by "/" or the start of the string, and | ||
// must be followed by a "/". We do not eat the following "/", so that the next | ||
// iteration can match on it. | ||
const parentRegex = /(^|\/)\.\.(?=\/|$)/g; | ||
function isAbsoluteUrl(url) { | ||
try { | ||
return !!new Url(url); | ||
} | ||
catch (e) { | ||
return false; | ||
} | ||
} | ||
/** | ||
* Creates a directory name that is guaranteed to not be in `str`. | ||
*/ | ||
function uniqInStr(str) { | ||
let uniq = String(Math.random()).slice(2); | ||
while (str.indexOf(uniq) > -1) { | ||
/* istanbul ignore next */ | ||
uniq += uniq; | ||
} | ||
return uniq; | ||
} | ||
/** | ||
* Removes the filename from the path (everything trailing the last "/"). This | ||
* is only safe to call on a path, never call with an absolute or protocol | ||
* relative URL. | ||
*/ | ||
function stripPathFilename(path) { | ||
path = normalizePath(path); | ||
const index = path.lastIndexOf('/'); | ||
return path.slice(0, index + 1); | ||
} | ||
/** | ||
* Normalizes a protocol-relative URL, but keeps it protocol relative by | ||
* stripping out the protocl before returning it. | ||
*/ | ||
function normalizeProtocolRelative(input, absoluteBase) { | ||
const { href, protocol } = new Url(input, absoluteBase); | ||
return href.slice(protocol.length); | ||
} | ||
/** | ||
* Normalizes a simple path (one that has no ".."s, or is absolute so ".."s can | ||
* be normalized absolutely). | ||
*/ | ||
function normalizeSimplePath(input) { | ||
const { href } = new Url(input, 'https://foo.com/'); | ||
return href.slice('https://foo.com/'.length); | ||
} | ||
/** | ||
* Normalizes a path, ensuring that excess ".."s are preserved for relative | ||
* paths in the output. | ||
* | ||
* If the input is absolute, this will return an absolutey normalized path, but | ||
* it will not have a leading "/". | ||
* | ||
* If the input has a leading "..", the output will have a leading "..". | ||
* | ||
* If the input has a leading ".", the output will not have a leading "." | ||
* unless there are too many ".."s, in which case there will be a leading "..". | ||
*/ | ||
function normalizePath(input) { | ||
// If there are no ".."s, we can treat this as if it were an absolute path. | ||
// The return won't be an absolute path, so it's easy. | ||
if (!parentRegex.test(input)) | ||
return normalizeSimplePath(input); | ||
// We already found one "..". Let's see how many there are. | ||
let total = 1; | ||
while (parentRegex.test(input)) | ||
total++; | ||
// If there are ".."s, we need to prefix the the path with the same number of | ||
// unique directories. This is to ensure that we "remember" how many parent | ||
// directories we are accessing. Eg, "../../.." must keep 3, and "foo/../.." | ||
// must keep 1. | ||
const uniqDirectory = `z${uniqInStr(input)}/`; | ||
// uniqDirectory is just a "z", followed by numbers, followed by a "/". So | ||
// generating a runtime regex from it is safe. We'll use this search regex to | ||
// strip out our uniq directory names and insert any needed ".."s. | ||
const search = new RegExp(`^(?:${uniqDirectory})*`); | ||
// Now we can resolve the total path. If there are excess ".."s, they will | ||
// eliminate one or more of the unique directories we prefix with. | ||
const relative = normalizeSimplePath(uniqDirectory.repeat(total) + input); | ||
// We can now count the number of unique directories that were eliminated. If | ||
// there were 3, and 1 was eliminated, we know we only need to add 1 "..". If | ||
// 2 were eliminated, we need to insert 2 ".."s. If all 3 were eliminated, | ||
// then we need 3, etc. This replace is guranteed to match (it may match 0 or | ||
// more times), and we can count the total match to see how many were eliminated. | ||
return relative.replace(search, (all) => { | ||
const leftover = all.length / uniqDirectory.length; | ||
return '../'.repeat(total - leftover); | ||
}); | ||
} | ||
/** | ||
* Attempts to resolve `input` URL relative to `base`. | ||
*/ | ||
function resolve(input, base) { | ||
if (!base) | ||
base = ''; | ||
// Absolute URLs are very easy to resolve right. | ||
if (isAbsoluteUrl(input)) | ||
return new Url(input).href; | ||
if (base) { | ||
// Absolute URLs are easy... | ||
if (isAbsoluteUrl(base)) | ||
return new Url(input, base).href; | ||
// If base is protocol relative, we'll resolve with it but keep the result | ||
// protocol relative. | ||
if (base.startsWith('//')) | ||
return normalizeProtocolRelative(input, `https:${base}`); | ||
} | ||
// Normalize input, but keep it protocol relative. We know base doesn't supply | ||
// a protocol, because that would have been handled above. | ||
if (input.startsWith('//')) | ||
return normalizeProtocolRelative(input, 'https://foo.com/'); | ||
// We now know that base (if there is one) and input are paths. We've handled | ||
// both absolute and protocol-relative variations above. | ||
// Absolute paths don't need any special handling, because they cannot have | ||
// extra "." or ".."s. That'll all be stripped away. Input takes priority here, | ||
// because if input is an absolute path, base path won't affect it in any way. | ||
if (input.startsWith('/')) | ||
return '/' + normalizeSimplePath(input); | ||
// Since input and base are paths, we need to join them to do any further | ||
// processing. Paths are joined at the directory level, so we need to remove | ||
// the base's filename before joining. We also know that input does not have a | ||
// leading slash, and that the stripped base will have a trailing slash if | ||
// there are any directories (or it'll be empty). | ||
const joined = stripPathFilename(base) + input; | ||
// If base is an absolute path, then input will be relative to it. | ||
if (base.startsWith('/')) | ||
return '/' + normalizeSimplePath(joined); | ||
// We now know both base (if there is one) and input are relative paths. | ||
const relative = normalizePath(joined); | ||
// 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. | ||
if ((base || input).startsWith('.') && !relative.startsWith('.')) { | ||
return './' + relative; | ||
} | ||
return relative; | ||
} | ||
// Matches "..", which must be preceeded by "/" or the start of the string, and | ||
// must be followed by a "/". We do not eat the following "/", so that the next | ||
// iteration can match on it. | ||
const parentRegex = /(^|\/)\.\.(?=\/|$)/g; | ||
// Matches the scheme of a URL, which is a strong indicator it is an valid | ||
// absolute URL. | ||
const schemeRegex = /^\s*[a-z][a-z0-9+\-.]*:/i; | ||
function absoluteUrl(url) { | ||
try { | ||
return schemeRegex.test(url) ? new URL(url) : null; | ||
} | ||
catch (_a) { | ||
/* istanbul ignore next */ | ||
return null; | ||
} | ||
} | ||
/** | ||
* Creates a directory name that is guaranteed to not be in `str`. | ||
*/ | ||
function uniqInStr(str) { | ||
let uniq = String(Math.random()).slice(2); | ||
let index = 0; | ||
while ((index = str.indexOf(uniq, index)) > -1) { | ||
uniq += uniq; | ||
} | ||
return uniq; | ||
} | ||
/** | ||
* Removes the filename from the path (everything trailing the last "/"). This | ||
* is only safe to call on a path, never call with an absolute or protocol | ||
* relative URL. | ||
*/ | ||
function stripPathFilename(path) { | ||
path = normalizePath(path); | ||
const index = path.lastIndexOf('/'); | ||
return path.slice(0, index + 1); | ||
} | ||
/** | ||
* Normalizes a protocol-relative URL, but keeps it protocol relative by | ||
* stripping out the protocl before returning it. | ||
*/ | ||
function normalizeProtocolRelative(input, absoluteBase) { | ||
const { href, protocol } = new URL(input, absoluteBase); | ||
return href.slice(protocol.length); | ||
} | ||
/** | ||
* Normalizes a simple path (one that has no ".."s, or is absolute so ".."s can | ||
* be normalized absolutely). | ||
*/ | ||
function normalizeSimplePath(input) { | ||
const { href } = new URL(input, 'https://foo.com/'); | ||
return href.slice('https://foo.com/'.length); | ||
} | ||
/** | ||
* Normalizes a path, ensuring that excess ".."s are preserved for relative | ||
* paths in the output. | ||
* | ||
* If the input is absolute, this will return an absolutey normalized path, but | ||
* it will not have a leading "/". | ||
* | ||
* If the input has a leading "..", the output will have a leading "..". | ||
* | ||
* If the input has a leading ".", the output will not have a leading "." | ||
* unless there are too many ".."s, in which case there will be a leading "..". | ||
*/ | ||
function normalizePath(input) { | ||
// If there are no ".."s, we can treat this as if it were an absolute path. | ||
// The return won't be an absolute path, so it's easy. | ||
if (!parentRegex.test(input)) | ||
return normalizeSimplePath(input); | ||
// We already found one "..". Let's see how many there are. | ||
let total = 1; | ||
while (parentRegex.test(input)) | ||
total++; | ||
// If there are ".."s, we need to prefix the the path with the same number of | ||
// unique directories. This is to ensure that we "remember" how many parent | ||
// directories we are accessing. Eg, "../../.." must keep 3, and "foo/../.." | ||
// must keep 1. | ||
const uniqDirectory = `z${uniqInStr(input)}/`; | ||
// Now we can resolve the total path. If there are excess ".."s, they will | ||
// eliminate one or more of the unique directories we prefix with. | ||
const relative = normalizeSimplePath(uniqDirectory.repeat(total) + input); | ||
// We can now count the number of unique directories that were eliminated. If | ||
// there were 3, and 1 was eliminated, we know we only need to add 1 "..". If | ||
// 2 were eliminated, we need to insert 2 ".."s. If all 3 were eliminated, | ||
// then we need 3, etc. | ||
let index = 0; | ||
while (relative.startsWith(uniqDirectory, index)) { | ||
total--; | ||
index += uniqDirectory.length; | ||
} | ||
return '../'.repeat(total) + relative.slice(index); | ||
} | ||
/** | ||
* Attempts to resolve `input` URL relative to `base`. | ||
*/ | ||
function resolve(input, base) { | ||
if (!base) | ||
base = ''; | ||
// Absolute URLs are very easy to resolve right. | ||
let url; | ||
if ((url = absoluteUrl(input))) | ||
return url.href; | ||
if (base) { | ||
// Absolute URLs are easy... | ||
if (absoluteUrl(base)) | ||
return new URL(input, base).href; | ||
// If base is protocol relative, we'll resolve with it but keep the result | ||
// protocol relative. | ||
if (base.startsWith('//')) | ||
return normalizeProtocolRelative(input, `https:${base}`); | ||
} | ||
// Normalize input, but keep it protocol relative. We know base doesn't supply | ||
// a protocol, because that would have been handled above. | ||
if (input.startsWith('//')) | ||
return normalizeProtocolRelative(input, 'https://foo.com/'); | ||
// We now know that base (if there is one) and input are paths. We've handled | ||
// both absolute and protocol-relative variations above. | ||
// Absolute paths don't need any special handling, because they cannot have | ||
// extra "." or ".."s. That'll all be stripped away. Input takes priority here, | ||
// because if input is an absolute path, base path won't affect it in any way. | ||
if (input.startsWith('/')) | ||
return '/' + normalizeSimplePath(input); | ||
// Since input and base are paths, we need to join them to do any further | ||
// processing. Paths are joined at the directory level, so we need to remove | ||
// the base's filename before joining. We also know that input does not have a | ||
// leading slash, and that the stripped base will have a trailing slash if | ||
// there are any directories (or it'll be empty). | ||
const joined = stripPathFilename(base) + input; | ||
// If base is an absolute path, then input will be relative to it. | ||
if (base.startsWith('/')) | ||
return '/' + normalizeSimplePath(joined); | ||
// We now know both base (if there is one) and input are relative paths. | ||
const relative = normalizePath(joined); | ||
// 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. | ||
if ((base || input).startsWith('.') && !relative.startsWith('.')) { | ||
return './' + relative; | ||
} | ||
return relative; | ||
} | ||
return resolve; | ||
return resolve; | ||
})); | ||
}))); | ||
//# sourceMappingURL=resolve-uri.umd.js.map |
{ | ||
"name": "@jridgewell/resolve-uri", | ||
"version": "1.0.0", | ||
"version": "2.0.0", | ||
"description": "Resolve a URI relative to an optional base URI", | ||
@@ -11,2 +11,5 @@ "keywords": [ | ||
], | ||
"author": "Justin Ridgewell <justin@ridgewell.name>", | ||
"license": "MIT", | ||
"repository": "https://github.com/jridgewell/resolve-uri", | ||
"main": "dist/resolve-uri.umd.js", | ||
@@ -18,51 +21,39 @@ "module": "dist/resolve-uri.mjs", | ||
], | ||
"author": "Justin Ridgewell <jridgewell@google.com>", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/jridgewell/resolve-uri.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/jridgewell/resolve-uri/issues" | ||
}, | ||
"license": "MIT", | ||
"engines": { | ||
"node": ">=6.0.0" | ||
"node": ">=10.0.0" | ||
}, | ||
"scripts": { | ||
"lint:ts": "npm run test:lint:ts -- --fix", | ||
"lint:prettier": "npm run test:lint:prettier -- --write", | ||
"lint": "run-s -n lint:*", | ||
"prebuild": "rm -rf dist", | ||
"build:ts": "tsc --module commonjs", | ||
"build:rollup": "rollup -c rollup.config.ts", | ||
"build": "run-s -n build:*", | ||
"test": "jest --coverage", | ||
"build:rollup": "rollup -c rollup.config.js", | ||
"build:ts": "tsc --project tsconfig.build.json", | ||
"lint": "run-s -n lint:*", | ||
"lint:prettier": "npm run test:lint:prettier -- --write", | ||
"lint:ts": "npm run test:lint:ts -- --fix", | ||
"test": "run-s -n test:lint 'test:only -- --no-cache'", | ||
"test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand", | ||
"test:lint": "run-s -n test:lint:*", | ||
"test:lint:prettier": "prettier --check '{src,test}/**/*.ts'", | ||
"test:lint:ts": "eslint '{src,test}/**/*.ts'", | ||
"test:only": "jest --coverage", | ||
"test:watch": "jest --coverage --watch", | ||
"test:lint:ts": "tslint --project tsconfig.json -t codeFrame '{src,test}/**/*.ts'", | ||
"test:lint:prettier": "prettier --check '{src,test}/**/*.ts'", | ||
"test:lint": "run-s -n test:lint:*", | ||
"test:prod": "run-s -n test:lint 'test --no-cache'", | ||
"preversion": "run-s test:prod build", | ||
"prepublishOnly": "npm run preversion" | ||
"prepublishOnly": "npm run preversion", | ||
"preversion": "run-s test build" | ||
}, | ||
"devDependencies": { | ||
"@types/jest": "24.0.15", | ||
"@types/node": "12.6.2", | ||
"jest": "24.8.0", | ||
"jest-config": "24.8.0", | ||
"@rollup/plugin-typescript": "8.1.0", | ||
"@types/jest": "26.0.19", | ||
"@typescript-eslint/eslint-plugin": "4.10.0", | ||
"@typescript-eslint/parser": "4.10.0", | ||
"eslint": "7.15.0", | ||
"eslint-config-prettier": "7.0.0", | ||
"jest": "26.6.3", | ||
"jest-config": "26.6.3", | ||
"npm-run-all": "4.1.5", | ||
"prettier": "1.18.2", | ||
"rollup": "1.16.7", | ||
"rollup-plugin-commonjs": "10.0.1", | ||
"rollup-plugin-node-resolve": "5.2.0", | ||
"rollup-plugin-sourcemaps": "0.4.2", | ||
"rollup-plugin-typescript": "1.0.1", | ||
"ts-jest": "24.0.2", | ||
"ts-node": "8.3.0", | ||
"tslint": "5.18.0", | ||
"tslint-config-prettier": "1.18.0", | ||
"tslint-config-standard": "8.0.1", | ||
"typescript": "3.5.3" | ||
"prettier": "2.2.1", | ||
"rollup": "2.35.1", | ||
"ts-jest": "26.4.4", | ||
"tslib": "2.0.3", | ||
"typescript": "4.1.3" | ||
} | ||
} |
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
14
36964
8
300
1
1