vscode-uri
Advanced tools
Comparing version 2.1.0 to 2.1.1
@@ -42,3 +42,3 @@ /** | ||
*/ | ||
protected constructor(scheme: string, authority?: string, path?: string, query?: string, fragment?: string); | ||
protected constructor(scheme: string, authority?: string, path?: string, query?: string, fragment?: string, _strict?: boolean); | ||
/** | ||
@@ -84,7 +84,5 @@ * @internal | ||
* | ||
* *Note:* When the input lacks a scheme then `file` is used. | ||
* | ||
* @param value A string which represents an URI (see `URI#toString`). | ||
*/ | ||
static parse(value: string, strict?: boolean): URI; | ||
static parse(value: string, _strict?: boolean): URI; | ||
/** | ||
@@ -91,0 +89,0 @@ * Creates a new URI from a file system path, e.g. `c:\my\files`, |
@@ -19,2 +19,3 @@ /*--------------------------------------------------------------------------------------------- | ||
})(); | ||
var _a; | ||
var isWindows; | ||
@@ -47,6 +48,8 @@ if (typeof process === 'object') { | ||
//#endregion | ||
var _schemeRegExp = /^\w[\w\d+.-]*$/; | ||
function _validateUri(ret) { | ||
var _schemePattern = /^\w[\w\d+.-]*$/; | ||
var _singleSlashStart = /^\//; | ||
var _doubleSlashStart = /^\/\//; | ||
function _validateUri(ret, _strict) { | ||
// scheme, must be set | ||
if (!ret.scheme) { | ||
if (!ret.scheme && _strict) { | ||
throw new Error("[UriError]: Scheme is missing: {scheme: \"\", authority: \"" + ret.authority + "\", path: \"" + ret.path + "\", query: \"" + ret.query + "\", fragment: \"" + ret.fragment + "\"}"); | ||
@@ -56,3 +59,3 @@ } | ||
// ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) | ||
if (ret.scheme && !_schemeRegExp.test(ret.scheme)) { | ||
if (ret.scheme && !_schemePattern.test(ret.scheme)) { | ||
throw new Error('[UriError]: Scheme contains illegal characters.'); | ||
@@ -67,3 +70,3 @@ } | ||
if (ret.authority) { | ||
if (ret.path.charCodeAt(0) !== 47 /* Slash */) { | ||
if (!_singleSlashStart.test(ret.path)) { | ||
throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character'); | ||
@@ -73,3 +76,3 @@ } | ||
else { | ||
if (ret.path.charCodeAt(0) === 47 /* Slash */ && ret.path.charCodeAt(1) === 47 /* Slash */) { | ||
if (_doubleSlashStart.test(ret.path)) { | ||
throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//")'); | ||
@@ -80,12 +83,9 @@ } | ||
} | ||
// graceful behaviour when scheme is missing: fallback to using 'file'-scheme | ||
function _schemeFix(scheme, strict) { | ||
if (!scheme) { | ||
if (strict) { | ||
throw new Error('[UriError]: A scheme must be provided'); | ||
} | ||
else { | ||
// console.trace('BAD uri lacks scheme, falling back to file-scheme.'); | ||
scheme = 'file'; | ||
} | ||
// for a while we allowed uris *without* schemes and this is the migration | ||
// for them, e.g. an uri without scheme and without strict-mode warns and falls | ||
// back to the file-scheme. that should cause the least carnage and still be a | ||
// clear warning | ||
function _schemeFix(scheme, _strict) { | ||
if (!scheme && !_strict) { | ||
return 'file'; | ||
} | ||
@@ -105,6 +105,6 @@ return scheme; | ||
if (!path) { | ||
path = '/'; | ||
path = _slash; | ||
} | ||
else if (path[0].charCodeAt(0) !== 47 /* Slash */) { | ||
path = '/' + path; | ||
else if (path[0] !== _slash) { | ||
path = _slash + path; | ||
} | ||
@@ -115,7 +115,5 @@ break; | ||
} | ||
var _uriRegExp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/; | ||
var _percentRegExp = /%/g; | ||
var _hashRegExp = /#/g; | ||
var _backslashRegExp = /\\/g; | ||
var _slashRegExp = /\//g; | ||
var _empty = ''; | ||
var _slash = '/'; | ||
var _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/; | ||
/** | ||
@@ -139,9 +137,10 @@ * Uniform Resource Identifier (URI) http://tools.ietf.org/html/rfc3986. | ||
*/ | ||
function URI(schemeOrData, authority, path, query, fragment) { | ||
function URI(schemeOrData, authority, path, query, fragment, _strict) { | ||
if (_strict === void 0) { _strict = false; } | ||
if (typeof schemeOrData === 'object') { | ||
this.scheme = schemeOrData.scheme || ''; | ||
this.authority = schemeOrData.authority || ''; | ||
this.path = schemeOrData.path || ''; | ||
this.query = schemeOrData.query || ''; | ||
this.fragment = schemeOrData.fragment || ''; | ||
this.scheme = schemeOrData.scheme || _empty; | ||
this.authority = schemeOrData.authority || _empty; | ||
this.path = schemeOrData.path || _empty; | ||
this.query = schemeOrData.query || _empty; | ||
this.fragment = schemeOrData.fragment || _empty; | ||
// no validation because it's this URI | ||
@@ -152,8 +151,8 @@ // that creates uri components. | ||
else { | ||
this.scheme = _schemeFix(schemeOrData); | ||
this.authority = authority || ''; | ||
this.path = _referenceResolution(this.scheme, path || ''); | ||
this.query = query || ''; | ||
this.fragment = fragment || ''; | ||
_validateUri(this); | ||
this.scheme = _schemeFix(schemeOrData, _strict); | ||
this.authority = authority || _empty; | ||
this.path = _referenceResolution(this.scheme, path || _empty); | ||
this.query = query || _empty; | ||
this.fragment = fragment || _empty; | ||
_validateUri(this, _strict); | ||
} | ||
@@ -204,3 +203,6 @@ } | ||
get: function () { | ||
return _toFsPath(this.scheme, this.authority, this.path); | ||
// if (this.scheme !== 'file') { | ||
// console.warn(`[UriError] calling fsPath with scheme ${this.scheme}`); | ||
// } | ||
return _makeFsPath(this); | ||
}, | ||
@@ -220,3 +222,3 @@ enumerable: true, | ||
else if (scheme === null) { | ||
scheme = ''; | ||
scheme = _empty; | ||
} | ||
@@ -227,3 +229,3 @@ if (authority === undefined) { | ||
else if (authority === null) { | ||
authority = ''; | ||
authority = _empty; | ||
} | ||
@@ -234,3 +236,3 @@ if (path === undefined) { | ||
else if (path === null) { | ||
path = ''; | ||
path = _empty; | ||
} | ||
@@ -241,3 +243,3 @@ if (query === undefined) { | ||
else if (query === null) { | ||
query = ''; | ||
query = _empty; | ||
} | ||
@@ -248,3 +250,3 @@ if (fragment === undefined) { | ||
else if (fragment === null) { | ||
fragment = ''; | ||
fragment = _empty; | ||
} | ||
@@ -265,19 +267,11 @@ if (scheme === this.scheme | ||
* | ||
* *Note:* When the input lacks a scheme then `file` is used. | ||
* | ||
* @param value A string which represents an URI (see `URI#toString`). | ||
*/ | ||
URI.parse = function (value, strict) { | ||
var match = _uriRegExp.exec(value); | ||
URI.parse = function (value, _strict) { | ||
if (_strict === void 0) { _strict = false; } | ||
var match = _regexp.exec(value); | ||
if (!match) { | ||
throw new Error("[UriError]: Invalid input: " + value); | ||
return new _URI(_empty, _empty, _empty, _empty, _empty); | ||
} | ||
var scheme = _schemeFix(match[2 /* scheme */], strict) || ''; | ||
var authority = match[4 /* authority */] || ''; | ||
var path = _referenceResolution(scheme, match[5 /* path */] || ''); | ||
var query = match[7 /* query */] || ''; | ||
var fragment = match[9 /* fragment */] || ''; | ||
var result = new _URI(scheme, percentDecode(authority), percentDecode(path), percentDecode(query), percentDecode(fragment)); | ||
result._external = _toExternal(_normalEncoder, scheme, authority, path, query, fragment); | ||
return result; | ||
return new _URI(match[2] || _empty, decodeURIComponent(match[4] || _empty), decodeURIComponent(match[5] || _empty), decodeURIComponent(match[7] || _empty), decodeURIComponent(match[9] || _empty), _strict); | ||
}; | ||
@@ -306,3 +300,3 @@ /** | ||
URI.file = function (path) { | ||
var authority = ''; | ||
var authority = _empty; | ||
// normalize to fwd-slashes on windows, | ||
@@ -312,27 +306,18 @@ // on other systems bwd-slashes are valid | ||
if (isWindows) { | ||
path = path.replace(_backslashRegExp, '/'); | ||
path = path.replace(/\\/g, _slash); | ||
} | ||
// check for authority as used in UNC shares | ||
// or use the path as given | ||
if (path.charCodeAt(0) === 47 /* Slash */ && path.charCodeAt(1) === 47 /* Slash */) { | ||
var idx = path.indexOf('/', 2); | ||
if (path[0] === _slash && path[1] === _slash) { | ||
var idx = path.indexOf(_slash, 2); | ||
if (idx === -1) { | ||
authority = path.substring(2); | ||
path = '/'; | ||
path = _slash; | ||
} | ||
else { | ||
authority = path.substring(2, idx); | ||
path = path.substring(idx) || '/'; | ||
path = path.substring(idx) || _slash; | ||
} | ||
} | ||
// ensures that path starts with / | ||
path = _referenceResolution('file', path); | ||
// escape some vital characters | ||
authority = authority.replace(_percentRegExp, '%25'); | ||
path = path.replace(_percentRegExp, '%25'); | ||
path = path.replace(_hashRegExp, '%23'); | ||
if (!isWindows) { | ||
path = path.replace(_backslashRegExp, '%5C'); | ||
} | ||
return URI.parse('file://' + authority + path); | ||
return new _URI('file', authority, path, _empty, _empty); | ||
}; | ||
@@ -356,3 +341,3 @@ URI.from = function (components) { | ||
if (skipEncoding === void 0) { skipEncoding = false; } | ||
return _toExternal(skipEncoding ? _minimalEncoder : _normalEncoder, this.scheme, this.authority, this.path, this.query, this.fragment); | ||
return _asFormatted(this, skipEncoding); | ||
}; | ||
@@ -371,3 +356,3 @@ URI.prototype.toJSON = function () { | ||
var result = new _URI(data); | ||
result._external = data.external; | ||
result._formatted = data.external; | ||
result._fsPath = data._sep === _pathSepMarker ? data.fsPath : null; | ||
@@ -386,3 +371,3 @@ return result; | ||
var _this = _super !== null && _super.apply(this, arguments) || this; | ||
_this._external = null; | ||
_this._formatted = null; | ||
_this._fsPath = null; | ||
@@ -394,3 +379,3 @@ return _this; | ||
if (!this._fsPath) { | ||
this._fsPath = _toFsPath(this.scheme, this.authority, this.path); | ||
this._fsPath = _makeFsPath(this); | ||
} | ||
@@ -404,10 +389,12 @@ return this._fsPath; | ||
if (skipEncoding === void 0) { skipEncoding = false; } | ||
if (skipEncoding) { | ||
if (!skipEncoding) { | ||
if (!this._formatted) { | ||
this._formatted = _asFormatted(this, false); | ||
} | ||
return this._formatted; | ||
} | ||
else { | ||
// we don't cache that | ||
return _toExternal(_minimalEncoder, this.scheme, this.authority, this.path, this.query, this.fragment); | ||
return _asFormatted(this, true); | ||
} | ||
if (!this._external) { | ||
this._external = _toExternal(_normalEncoder, this.scheme, this.authority, this.path, this.query, this.fragment); | ||
} | ||
return this._external; | ||
}; | ||
@@ -423,4 +410,4 @@ _URI.prototype.toJSON = function () { | ||
} | ||
if (this._external) { | ||
res.external = this._external; | ||
if (this._formatted) { | ||
res.external = this._formatted; | ||
} | ||
@@ -447,146 +434,126 @@ // uri components | ||
}(URI)); | ||
// reserved characters: https://tools.ietf.org/html/rfc3986#section-2.2 | ||
var encodeTable = (_a = {}, | ||
_a[58 /* Colon */] = '%3A', | ||
_a[47 /* Slash */] = '%2F', | ||
_a[63 /* QuestionMark */] = '%3F', | ||
_a[35 /* Hash */] = '%23', | ||
_a[91 /* OpenSquareBracket */] = '%5B', | ||
_a[93 /* CloseSquareBracket */] = '%5D', | ||
_a[64 /* AtSign */] = '%40', | ||
_a[33 /* ExclamationMark */] = '%21', | ||
_a[36 /* DollarSign */] = '%24', | ||
_a[38 /* Ampersand */] = '%26', | ||
_a[39 /* SingleQuote */] = '%27', | ||
_a[40 /* OpenParen */] = '%28', | ||
_a[41 /* CloseParen */] = '%29', | ||
_a[42 /* Asterisk */] = '%2A', | ||
_a[43 /* Plus */] = '%2B', | ||
_a[44 /* Comma */] = '%2C', | ||
_a[59 /* Semicolon */] = '%3B', | ||
_a[61 /* Equals */] = '%3D', | ||
_a[32 /* Space */] = '%20', | ||
_a); | ||
function encodeURIComponentFast(uriComponent, allowSlash) { | ||
var res = undefined; | ||
var nativeEncodePos = -1; | ||
for (var pos = 0; pos < uriComponent.length; pos++) { | ||
var code = uriComponent.charCodeAt(pos); | ||
// unreserved characters: https://tools.ietf.org/html/rfc3986#section-2.3 | ||
if ((code >= 97 /* a */ && code <= 122 /* z */) | ||
|| (code >= 65 /* A */ && code <= 90 /* Z */) | ||
|| (code >= 48 /* Digit0 */ && code <= 57 /* Digit9 */) | ||
|| code === 45 /* Dash */ | ||
|| code === 46 /* Period */ | ||
|| code === 95 /* Underline */ | ||
|| code === 126 /* Tilde */ | ||
|| (allowSlash && code === 47 /* Slash */)) { | ||
// check if we are delaying native encode | ||
if (nativeEncodePos !== -1) { | ||
res += encodeURIComponent(uriComponent.substring(nativeEncodePos, pos)); | ||
nativeEncodePos = -1; | ||
} | ||
// check if we write into a new string (by default we try to return the param) | ||
if (res !== undefined) { | ||
res += uriComponent.charAt(pos); | ||
} | ||
} | ||
else { | ||
// encoding needed, we need to allocate a new string | ||
if (res === undefined) { | ||
res = uriComponent.substr(0, pos); | ||
} | ||
// check with default table first | ||
var escaped = encodeTable[code]; | ||
if (escaped !== undefined) { | ||
// check if we are delaying native encode | ||
if (nativeEncodePos !== -1) { | ||
res += encodeURIComponent(uriComponent.substring(nativeEncodePos, pos)); | ||
nativeEncodePos = -1; | ||
} | ||
// append escaped variant to result | ||
res += escaped; | ||
} | ||
else if (nativeEncodePos === -1) { | ||
// use native encode only when needed | ||
nativeEncodePos = pos; | ||
} | ||
} | ||
} | ||
if (nativeEncodePos !== -1) { | ||
res += encodeURIComponent(uriComponent.substring(nativeEncodePos)); | ||
} | ||
return res !== undefined ? res : uriComponent; | ||
} | ||
function encodeURIComponentMinimal(path) { | ||
var res = undefined; | ||
for (var pos = 0; pos < path.length; pos++) { | ||
var code = path.charCodeAt(pos); | ||
if (code === 35 /* Hash */ || code === 63 /* QuestionMark */) { | ||
if (res === undefined) { | ||
res = path.substr(0, pos); | ||
} | ||
res += encodeTable[code]; | ||
} | ||
else { | ||
if (res !== undefined) { | ||
res += path[pos]; | ||
} | ||
} | ||
} | ||
return res !== undefined ? res : path; | ||
} | ||
/** | ||
* Compute `fsPath` for the given uri | ||
*/ | ||
function _toFsPath(scheme, authority, path) { | ||
function _makeFsPath(uri) { | ||
var value; | ||
if (authority && path.length > 1 && scheme === 'file') { | ||
if (uri.authority && uri.path.length > 1 && uri.scheme === 'file') { | ||
// unc path: file://shares/c$/far/boo | ||
value = "//" + authority + path; | ||
value = "//" + uri.authority + uri.path; | ||
} | ||
else if (path.charCodeAt(0) === 47 /* Slash */ | ||
&& isAsciiLetter(path.charCodeAt(1)) | ||
&& path.charCodeAt(2) === 58 /* Colon */) { | ||
else if (uri.path.charCodeAt(0) === 47 /* Slash */ | ||
&& (uri.path.charCodeAt(1) >= 65 /* A */ && uri.path.charCodeAt(1) <= 90 /* Z */ || uri.path.charCodeAt(1) >= 97 /* a */ && uri.path.charCodeAt(1) <= 122 /* z */) | ||
&& uri.path.charCodeAt(2) === 58 /* Colon */) { | ||
// windows drive letter: file:///c:/far/boo | ||
value = path[1].toLowerCase() + path.substr(2); | ||
value = uri.path[1].toLowerCase() + uri.path.substr(2); | ||
} | ||
else { | ||
// other path | ||
value = path; | ||
value = uri.path; | ||
} | ||
if (isWindows) { | ||
value = value.replace(_slashRegExp, '\\'); | ||
value = value.replace(/\//g, '\\'); | ||
} | ||
return value; | ||
} | ||
//#region ---- decode | ||
function decodeURIComponentGraceful(str) { | ||
try { | ||
return decodeURIComponent(str); | ||
} | ||
catch (_a) { | ||
if (str.length > 3) { | ||
return str.substr(0, 3) + decodeURIComponentGraceful(str.substr(3)); | ||
} | ||
else { | ||
return str; | ||
} | ||
} | ||
} | ||
var _encodedAsHexRegExp = /(%[0-9A-Za-z][0-9A-Za-z])+/g; | ||
function percentDecode(str) { | ||
if (!str.match(_encodedAsHexRegExp)) { | ||
return str; | ||
} | ||
return str.replace(_encodedAsHexRegExp, function (match) { return decodeURIComponentGraceful(match); }); | ||
} | ||
//#endregion | ||
//#region ---- encode | ||
// https://url.spec.whatwg.org/#percent-encoded-bytes | ||
// "The C0 control percent-encode set are the C0 controls and all code points greater than U+007E (~)." | ||
function isC0ControlPercentEncodeSet(code) { | ||
return code <= 0x1F || code > 0x7E; | ||
} | ||
// "The fragment percent-encode set is the C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+003C (<), U+003E (>), and U+0060 (`)." | ||
function isFragmentPercentEncodeSet(code) { | ||
return isC0ControlPercentEncodeSet(code) | ||
|| code === 0x20 || code === 0x22 || code === 0x3C || code === 0x3E || code === 0x60; | ||
} | ||
// "The path percent-encode set is the fragment percent-encode set and U+0023 (#), U+003F (?), U+007B ({), and U+007D (})." | ||
function isPathPercentEncodeSet(code) { | ||
return isFragmentPercentEncodeSet(code) | ||
|| code === 0x23 || code === 0x3F || code === 0x7B || code === 0x7D; | ||
} | ||
// "The userinfo percent-encode set is the path percent-encode set and U+002F (/), U+003A (:), U+003B (;), U+003D (=), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), and U+007C (|)." | ||
function isUserInfoPercentEncodeSet(code) { | ||
return isPathPercentEncodeSet(code) | ||
|| code === 0x2F || code === 0x3A || code === 0x3B || code === 0x3D || code === 0x40 | ||
|| code === 0x5B || code === 0x5C || code === 0x5D || code === 0x5E || code === 0x7C; | ||
} | ||
// https://url.spec.whatwg.org/#query-state | ||
function isQueryPrecentEncodeSet(code) { | ||
return code < 0x21 || code > 0x7E | ||
|| code === 0x22 || code === 0x23 || code === 0x3C || code === 0x3E | ||
|| code === 0x27; // <- todo@joh https://url.spec.whatwg.org/#is-special | ||
} | ||
// this is non-standard and uses for `URI.toString(true)` | ||
function isHashOrQuestionMark(code) { | ||
return code === 35 /* Hash */ || code === 63 /* QuestionMark */; | ||
} | ||
var _encodeTable = (function () { | ||
var table = []; | ||
for (var code = 0; code < 128; code++) { | ||
table[code] = "%" + code.toString(16); | ||
} | ||
return table; | ||
})(); | ||
function percentEncode(str, mustEncode) { | ||
var lazyOutStr; | ||
for (var pos = 0; pos < str.length; pos++) { | ||
var code = str.charCodeAt(pos); | ||
// invoke encodeURIComponent when needed | ||
if (mustEncode(code)) { | ||
if (!lazyOutStr) { | ||
lazyOutStr = str.substr(0, pos); | ||
} | ||
if (isHighSurrogate(code)) { | ||
// Append encoded version of this surrogate pair (2 characters) | ||
if (pos + 1 < str.length && isLowSurrogate(str.charCodeAt(pos + 1))) { | ||
lazyOutStr += encodeURIComponent(str.substr(pos, 2)); | ||
pos += 1; | ||
} | ||
else { | ||
// broken surrogate pair | ||
lazyOutStr += str.charAt(pos); | ||
} | ||
} | ||
else { | ||
// Append encoded version of the current character, use lookup table | ||
// to speed up repeated encoding of the same characters. | ||
if (code < _encodeTable.length) { | ||
lazyOutStr += _encodeTable[code]; | ||
} | ||
else { | ||
lazyOutStr += encodeURIComponent(str.charAt(pos)); | ||
} | ||
} | ||
continue; | ||
} | ||
// normalize percent encoded sequences to upper case | ||
// todo@joh also changes invalid sequences | ||
if (code === 37 /* PercentSign */ | ||
&& pos + 2 < str.length | ||
&& (isLowerAsciiHex(str.charCodeAt(pos + 1)) || isLowerAsciiHex(str.charCodeAt(pos + 2)))) { | ||
if (!lazyOutStr) { | ||
lazyOutStr = str.substr(0, pos); | ||
} | ||
lazyOutStr += '%' + str.substr(pos + 1, 2).toUpperCase(); | ||
pos += 2; | ||
continue; | ||
} | ||
// once started, continue to build up lazy output | ||
if (lazyOutStr) { | ||
lazyOutStr += str.charAt(pos); | ||
} | ||
} | ||
return lazyOutStr || str; | ||
} | ||
var _normalEncoder = [isUserInfoPercentEncodeSet, isC0ControlPercentEncodeSet, isPathPercentEncodeSet, isQueryPrecentEncodeSet, isFragmentPercentEncodeSet]; | ||
var _minimalEncoder = [isHashOrQuestionMark, isHashOrQuestionMark, isHashOrQuestionMark, isHashOrQuestionMark, function () { return false; }]; | ||
var _driveLetterRegExp = /^(\/?[a-z])(:|%3a)/i; | ||
/** | ||
* Create the external version of a uri | ||
*/ | ||
function _toExternal(encoder, scheme, authority, path, query, fragment) { | ||
function _asFormatted(uri, skipEncoding) { | ||
var encoder = !skipEncoding | ||
? encodeURIComponentFast | ||
: encodeURIComponentMinimal; | ||
var res = ''; | ||
var scheme = uri.scheme, authority = uri.authority, path = uri.path, query = uri.query, fragment = uri.fragment; | ||
if (scheme) { | ||
@@ -597,48 +564,60 @@ res += scheme; | ||
if (authority || scheme === 'file') { | ||
res += '//'; | ||
res += _slash; | ||
res += _slash; | ||
} | ||
if (authority) { | ||
var idxUserInfo = authority.indexOf('@'); | ||
if (idxUserInfo !== -1) { | ||
// <user:token> | ||
var userInfo = authority.substr(0, idxUserInfo); | ||
var idxPasswordOrToken = userInfo.indexOf(':'); | ||
if (idxPasswordOrToken !== -1) { | ||
res += percentEncode(userInfo.substr(0, idxPasswordOrToken), encoder[0 /* user */]); | ||
res += ':'; | ||
res += percentEncode(userInfo.substr(idxPasswordOrToken + 1), encoder[0 /* user */]); | ||
var idx = authority.indexOf('@'); | ||
if (idx !== -1) { | ||
// <user>@<auth> | ||
var userinfo = authority.substr(0, idx); | ||
authority = authority.substr(idx + 1); | ||
idx = userinfo.indexOf(':'); | ||
if (idx === -1) { | ||
res += encoder(userinfo, false); | ||
} | ||
else { | ||
res += percentEncode(userInfo, encoder[0 /* user */]); | ||
// <user>:<pass>@<auth> | ||
res += encoder(userinfo.substr(0, idx), false); | ||
res += ':'; | ||
res += encoder(userinfo.substr(idx + 1), false); | ||
} | ||
res += '@'; | ||
} | ||
authority = authority.substr(idxUserInfo + 1).toLowerCase(); | ||
var idxPort = authority.indexOf(':'); | ||
if (idxPort !== -1) { | ||
// <authority>:<port> | ||
res += percentEncode(authority.substr(0, idxPort), encoder[1 /* authority */]); | ||
res += ':'; | ||
authority = authority.toLowerCase(); | ||
idx = authority.indexOf(':'); | ||
if (idx === -1) { | ||
res += encoder(authority, false); | ||
} | ||
res += percentEncode(authority.substr(idxPort + 1), encoder[1 /* authority */]); | ||
else { | ||
// <auth>:<port> | ||
res += encoder(authority.substr(0, idx), false); | ||
res += authority.substr(idx); | ||
} | ||
} | ||
if (path) { | ||
// encode the path | ||
var pathEncoded = percentEncode(path, encoder[2 /* path */]); | ||
// lower-case windows drive letters in /C:/fff or C:/fff and escape `:` | ||
var match = _driveLetterRegExp.exec(pathEncoded); | ||
if (match) { | ||
pathEncoded = match[1].toLowerCase() + '%3A' + pathEncoded.substr(match[0].length); | ||
// lower-case windows drive letters in /C:/fff or C:/fff | ||
if (path.length >= 3 && path.charCodeAt(0) === 47 /* Slash */ && path.charCodeAt(2) === 58 /* Colon */) { | ||
var code = path.charCodeAt(1); | ||
if (code >= 65 /* A */ && code <= 90 /* Z */) { | ||
path = "/" + String.fromCharCode(code + 32) + ":" + path.substr(3); // "/c:".length === 3 | ||
} | ||
} | ||
res += pathEncoded; | ||
else if (path.length >= 2 && path.charCodeAt(1) === 58 /* Colon */) { | ||
var code = path.charCodeAt(0); | ||
if (code >= 65 /* A */ && code <= 90 /* Z */) { | ||
path = String.fromCharCode(code + 32) + ":" + path.substr(2); // "/c:".length === 3 | ||
} | ||
} | ||
// encode the rest of the path | ||
res += encoder(path, true); | ||
} | ||
if (query) { | ||
res += '?'; | ||
res += percentEncode(query, encoder[3 /* query */]); | ||
res += encoder(query, false); | ||
} | ||
if (fragment) { | ||
res += '#'; | ||
res += percentEncode(fragment, encoder[4 /* fragment */]); | ||
res += !skipEncoding ? encodeURIComponentFast(fragment, false) : fragment; | ||
} | ||
return res; | ||
} |
@@ -42,3 +42,3 @@ /** | ||
*/ | ||
protected constructor(scheme: string, authority?: string, path?: string, query?: string, fragment?: string); | ||
protected constructor(scheme: string, authority?: string, path?: string, query?: string, fragment?: string, _strict?: boolean); | ||
/** | ||
@@ -84,7 +84,5 @@ * @internal | ||
* | ||
* *Note:* When the input lacks a scheme then `file` is used. | ||
* | ||
* @param value A string which represents an URI (see `URI#toString`). | ||
*/ | ||
static parse(value: string, strict?: boolean): URI; | ||
static parse(value: string, _strict?: boolean): URI; | ||
/** | ||
@@ -91,0 +89,0 @@ * Creates a new URI from a file system path, e.g. `c:\my\files`, |
@@ -28,2 +28,3 @@ var __extends = (this && this.__extends) || (function () { | ||
'use strict'; | ||
var _a; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -57,6 +58,8 @@ var isWindows; | ||
//#endregion | ||
var _schemeRegExp = /^\w[\w\d+.-]*$/; | ||
function _validateUri(ret) { | ||
var _schemePattern = /^\w[\w\d+.-]*$/; | ||
var _singleSlashStart = /^\//; | ||
var _doubleSlashStart = /^\/\//; | ||
function _validateUri(ret, _strict) { | ||
// scheme, must be set | ||
if (!ret.scheme) { | ||
if (!ret.scheme && _strict) { | ||
throw new Error("[UriError]: Scheme is missing: {scheme: \"\", authority: \"" + ret.authority + "\", path: \"" + ret.path + "\", query: \"" + ret.query + "\", fragment: \"" + ret.fragment + "\"}"); | ||
@@ -66,3 +69,3 @@ } | ||
// ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) | ||
if (ret.scheme && !_schemeRegExp.test(ret.scheme)) { | ||
if (ret.scheme && !_schemePattern.test(ret.scheme)) { | ||
throw new Error('[UriError]: Scheme contains illegal characters.'); | ||
@@ -77,3 +80,3 @@ } | ||
if (ret.authority) { | ||
if (ret.path.charCodeAt(0) !== 47 /* Slash */) { | ||
if (!_singleSlashStart.test(ret.path)) { | ||
throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character'); | ||
@@ -83,3 +86,3 @@ } | ||
else { | ||
if (ret.path.charCodeAt(0) === 47 /* Slash */ && ret.path.charCodeAt(1) === 47 /* Slash */) { | ||
if (_doubleSlashStart.test(ret.path)) { | ||
throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//")'); | ||
@@ -90,12 +93,9 @@ } | ||
} | ||
// graceful behaviour when scheme is missing: fallback to using 'file'-scheme | ||
function _schemeFix(scheme, strict) { | ||
if (!scheme) { | ||
if (strict) { | ||
throw new Error('[UriError]: A scheme must be provided'); | ||
} | ||
else { | ||
// console.trace('BAD uri lacks scheme, falling back to file-scheme.'); | ||
scheme = 'file'; | ||
} | ||
// for a while we allowed uris *without* schemes and this is the migration | ||
// for them, e.g. an uri without scheme and without strict-mode warns and falls | ||
// back to the file-scheme. that should cause the least carnage and still be a | ||
// clear warning | ||
function _schemeFix(scheme, _strict) { | ||
if (!scheme && !_strict) { | ||
return 'file'; | ||
} | ||
@@ -115,6 +115,6 @@ return scheme; | ||
if (!path) { | ||
path = '/'; | ||
path = _slash; | ||
} | ||
else if (path[0].charCodeAt(0) !== 47 /* Slash */) { | ||
path = '/' + path; | ||
else if (path[0] !== _slash) { | ||
path = _slash + path; | ||
} | ||
@@ -125,7 +125,5 @@ break; | ||
} | ||
var _uriRegExp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/; | ||
var _percentRegExp = /%/g; | ||
var _hashRegExp = /#/g; | ||
var _backslashRegExp = /\\/g; | ||
var _slashRegExp = /\//g; | ||
var _empty = ''; | ||
var _slash = '/'; | ||
var _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/; | ||
/** | ||
@@ -149,9 +147,10 @@ * Uniform Resource Identifier (URI) http://tools.ietf.org/html/rfc3986. | ||
*/ | ||
function URI(schemeOrData, authority, path, query, fragment) { | ||
function URI(schemeOrData, authority, path, query, fragment, _strict) { | ||
if (_strict === void 0) { _strict = false; } | ||
if (typeof schemeOrData === 'object') { | ||
this.scheme = schemeOrData.scheme || ''; | ||
this.authority = schemeOrData.authority || ''; | ||
this.path = schemeOrData.path || ''; | ||
this.query = schemeOrData.query || ''; | ||
this.fragment = schemeOrData.fragment || ''; | ||
this.scheme = schemeOrData.scheme || _empty; | ||
this.authority = schemeOrData.authority || _empty; | ||
this.path = schemeOrData.path || _empty; | ||
this.query = schemeOrData.query || _empty; | ||
this.fragment = schemeOrData.fragment || _empty; | ||
// no validation because it's this URI | ||
@@ -162,8 +161,8 @@ // that creates uri components. | ||
else { | ||
this.scheme = _schemeFix(schemeOrData); | ||
this.authority = authority || ''; | ||
this.path = _referenceResolution(this.scheme, path || ''); | ||
this.query = query || ''; | ||
this.fragment = fragment || ''; | ||
_validateUri(this); | ||
this.scheme = _schemeFix(schemeOrData, _strict); | ||
this.authority = authority || _empty; | ||
this.path = _referenceResolution(this.scheme, path || _empty); | ||
this.query = query || _empty; | ||
this.fragment = fragment || _empty; | ||
_validateUri(this, _strict); | ||
} | ||
@@ -214,3 +213,6 @@ } | ||
get: function () { | ||
return _toFsPath(this.scheme, this.authority, this.path); | ||
// if (this.scheme !== 'file') { | ||
// console.warn(`[UriError] calling fsPath with scheme ${this.scheme}`); | ||
// } | ||
return _makeFsPath(this); | ||
}, | ||
@@ -230,3 +232,3 @@ enumerable: true, | ||
else if (scheme === null) { | ||
scheme = ''; | ||
scheme = _empty; | ||
} | ||
@@ -237,3 +239,3 @@ if (authority === undefined) { | ||
else if (authority === null) { | ||
authority = ''; | ||
authority = _empty; | ||
} | ||
@@ -244,3 +246,3 @@ if (path === undefined) { | ||
else if (path === null) { | ||
path = ''; | ||
path = _empty; | ||
} | ||
@@ -251,3 +253,3 @@ if (query === undefined) { | ||
else if (query === null) { | ||
query = ''; | ||
query = _empty; | ||
} | ||
@@ -258,3 +260,3 @@ if (fragment === undefined) { | ||
else if (fragment === null) { | ||
fragment = ''; | ||
fragment = _empty; | ||
} | ||
@@ -275,19 +277,11 @@ if (scheme === this.scheme | ||
* | ||
* *Note:* When the input lacks a scheme then `file` is used. | ||
* | ||
* @param value A string which represents an URI (see `URI#toString`). | ||
*/ | ||
URI.parse = function (value, strict) { | ||
var match = _uriRegExp.exec(value); | ||
URI.parse = function (value, _strict) { | ||
if (_strict === void 0) { _strict = false; } | ||
var match = _regexp.exec(value); | ||
if (!match) { | ||
throw new Error("[UriError]: Invalid input: " + value); | ||
return new _URI(_empty, _empty, _empty, _empty, _empty); | ||
} | ||
var scheme = _schemeFix(match[2 /* scheme */], strict) || ''; | ||
var authority = match[4 /* authority */] || ''; | ||
var path = _referenceResolution(scheme, match[5 /* path */] || ''); | ||
var query = match[7 /* query */] || ''; | ||
var fragment = match[9 /* fragment */] || ''; | ||
var result = new _URI(scheme, percentDecode(authority), percentDecode(path), percentDecode(query), percentDecode(fragment)); | ||
result._external = _toExternal(_normalEncoder, scheme, authority, path, query, fragment); | ||
return result; | ||
return new _URI(match[2] || _empty, decodeURIComponent(match[4] || _empty), decodeURIComponent(match[5] || _empty), decodeURIComponent(match[7] || _empty), decodeURIComponent(match[9] || _empty), _strict); | ||
}; | ||
@@ -316,3 +310,3 @@ /** | ||
URI.file = function (path) { | ||
var authority = ''; | ||
var authority = _empty; | ||
// normalize to fwd-slashes on windows, | ||
@@ -322,27 +316,18 @@ // on other systems bwd-slashes are valid | ||
if (isWindows) { | ||
path = path.replace(_backslashRegExp, '/'); | ||
path = path.replace(/\\/g, _slash); | ||
} | ||
// check for authority as used in UNC shares | ||
// or use the path as given | ||
if (path.charCodeAt(0) === 47 /* Slash */ && path.charCodeAt(1) === 47 /* Slash */) { | ||
var idx = path.indexOf('/', 2); | ||
if (path[0] === _slash && path[1] === _slash) { | ||
var idx = path.indexOf(_slash, 2); | ||
if (idx === -1) { | ||
authority = path.substring(2); | ||
path = '/'; | ||
path = _slash; | ||
} | ||
else { | ||
authority = path.substring(2, idx); | ||
path = path.substring(idx) || '/'; | ||
path = path.substring(idx) || _slash; | ||
} | ||
} | ||
// ensures that path starts with / | ||
path = _referenceResolution('file', path); | ||
// escape some vital characters | ||
authority = authority.replace(_percentRegExp, '%25'); | ||
path = path.replace(_percentRegExp, '%25'); | ||
path = path.replace(_hashRegExp, '%23'); | ||
if (!isWindows) { | ||
path = path.replace(_backslashRegExp, '%5C'); | ||
} | ||
return URI.parse('file://' + authority + path); | ||
return new _URI('file', authority, path, _empty, _empty); | ||
}; | ||
@@ -366,3 +351,3 @@ URI.from = function (components) { | ||
if (skipEncoding === void 0) { skipEncoding = false; } | ||
return _toExternal(skipEncoding ? _minimalEncoder : _normalEncoder, this.scheme, this.authority, this.path, this.query, this.fragment); | ||
return _asFormatted(this, skipEncoding); | ||
}; | ||
@@ -381,3 +366,3 @@ URI.prototype.toJSON = function () { | ||
var result = new _URI(data); | ||
result._external = data.external; | ||
result._formatted = data.external; | ||
result._fsPath = data._sep === _pathSepMarker ? data.fsPath : null; | ||
@@ -396,3 +381,3 @@ return result; | ||
var _this = _super !== null && _super.apply(this, arguments) || this; | ||
_this._external = null; | ||
_this._formatted = null; | ||
_this._fsPath = null; | ||
@@ -404,3 +389,3 @@ return _this; | ||
if (!this._fsPath) { | ||
this._fsPath = _toFsPath(this.scheme, this.authority, this.path); | ||
this._fsPath = _makeFsPath(this); | ||
} | ||
@@ -414,10 +399,12 @@ return this._fsPath; | ||
if (skipEncoding === void 0) { skipEncoding = false; } | ||
if (skipEncoding) { | ||
if (!skipEncoding) { | ||
if (!this._formatted) { | ||
this._formatted = _asFormatted(this, false); | ||
} | ||
return this._formatted; | ||
} | ||
else { | ||
// we don't cache that | ||
return _toExternal(_minimalEncoder, this.scheme, this.authority, this.path, this.query, this.fragment); | ||
return _asFormatted(this, true); | ||
} | ||
if (!this._external) { | ||
this._external = _toExternal(_normalEncoder, this.scheme, this.authority, this.path, this.query, this.fragment); | ||
} | ||
return this._external; | ||
}; | ||
@@ -433,4 +420,4 @@ _URI.prototype.toJSON = function () { | ||
} | ||
if (this._external) { | ||
res.external = this._external; | ||
if (this._formatted) { | ||
res.external = this._formatted; | ||
} | ||
@@ -457,146 +444,126 @@ // uri components | ||
}(URI)); | ||
// reserved characters: https://tools.ietf.org/html/rfc3986#section-2.2 | ||
var encodeTable = (_a = {}, | ||
_a[58 /* Colon */] = '%3A', | ||
_a[47 /* Slash */] = '%2F', | ||
_a[63 /* QuestionMark */] = '%3F', | ||
_a[35 /* Hash */] = '%23', | ||
_a[91 /* OpenSquareBracket */] = '%5B', | ||
_a[93 /* CloseSquareBracket */] = '%5D', | ||
_a[64 /* AtSign */] = '%40', | ||
_a[33 /* ExclamationMark */] = '%21', | ||
_a[36 /* DollarSign */] = '%24', | ||
_a[38 /* Ampersand */] = '%26', | ||
_a[39 /* SingleQuote */] = '%27', | ||
_a[40 /* OpenParen */] = '%28', | ||
_a[41 /* CloseParen */] = '%29', | ||
_a[42 /* Asterisk */] = '%2A', | ||
_a[43 /* Plus */] = '%2B', | ||
_a[44 /* Comma */] = '%2C', | ||
_a[59 /* Semicolon */] = '%3B', | ||
_a[61 /* Equals */] = '%3D', | ||
_a[32 /* Space */] = '%20', | ||
_a); | ||
function encodeURIComponentFast(uriComponent, allowSlash) { | ||
var res = undefined; | ||
var nativeEncodePos = -1; | ||
for (var pos = 0; pos < uriComponent.length; pos++) { | ||
var code = uriComponent.charCodeAt(pos); | ||
// unreserved characters: https://tools.ietf.org/html/rfc3986#section-2.3 | ||
if ((code >= 97 /* a */ && code <= 122 /* z */) | ||
|| (code >= 65 /* A */ && code <= 90 /* Z */) | ||
|| (code >= 48 /* Digit0 */ && code <= 57 /* Digit9 */) | ||
|| code === 45 /* Dash */ | ||
|| code === 46 /* Period */ | ||
|| code === 95 /* Underline */ | ||
|| code === 126 /* Tilde */ | ||
|| (allowSlash && code === 47 /* Slash */)) { | ||
// check if we are delaying native encode | ||
if (nativeEncodePos !== -1) { | ||
res += encodeURIComponent(uriComponent.substring(nativeEncodePos, pos)); | ||
nativeEncodePos = -1; | ||
} | ||
// check if we write into a new string (by default we try to return the param) | ||
if (res !== undefined) { | ||
res += uriComponent.charAt(pos); | ||
} | ||
} | ||
else { | ||
// encoding needed, we need to allocate a new string | ||
if (res === undefined) { | ||
res = uriComponent.substr(0, pos); | ||
} | ||
// check with default table first | ||
var escaped = encodeTable[code]; | ||
if (escaped !== undefined) { | ||
// check if we are delaying native encode | ||
if (nativeEncodePos !== -1) { | ||
res += encodeURIComponent(uriComponent.substring(nativeEncodePos, pos)); | ||
nativeEncodePos = -1; | ||
} | ||
// append escaped variant to result | ||
res += escaped; | ||
} | ||
else if (nativeEncodePos === -1) { | ||
// use native encode only when needed | ||
nativeEncodePos = pos; | ||
} | ||
} | ||
} | ||
if (nativeEncodePos !== -1) { | ||
res += encodeURIComponent(uriComponent.substring(nativeEncodePos)); | ||
} | ||
return res !== undefined ? res : uriComponent; | ||
} | ||
function encodeURIComponentMinimal(path) { | ||
var res = undefined; | ||
for (var pos = 0; pos < path.length; pos++) { | ||
var code = path.charCodeAt(pos); | ||
if (code === 35 /* Hash */ || code === 63 /* QuestionMark */) { | ||
if (res === undefined) { | ||
res = path.substr(0, pos); | ||
} | ||
res += encodeTable[code]; | ||
} | ||
else { | ||
if (res !== undefined) { | ||
res += path[pos]; | ||
} | ||
} | ||
} | ||
return res !== undefined ? res : path; | ||
} | ||
/** | ||
* Compute `fsPath` for the given uri | ||
*/ | ||
function _toFsPath(scheme, authority, path) { | ||
function _makeFsPath(uri) { | ||
var value; | ||
if (authority && path.length > 1 && scheme === 'file') { | ||
if (uri.authority && uri.path.length > 1 && uri.scheme === 'file') { | ||
// unc path: file://shares/c$/far/boo | ||
value = "//" + authority + path; | ||
value = "//" + uri.authority + uri.path; | ||
} | ||
else if (path.charCodeAt(0) === 47 /* Slash */ | ||
&& isAsciiLetter(path.charCodeAt(1)) | ||
&& path.charCodeAt(2) === 58 /* Colon */) { | ||
else if (uri.path.charCodeAt(0) === 47 /* Slash */ | ||
&& (uri.path.charCodeAt(1) >= 65 /* A */ && uri.path.charCodeAt(1) <= 90 /* Z */ || uri.path.charCodeAt(1) >= 97 /* a */ && uri.path.charCodeAt(1) <= 122 /* z */) | ||
&& uri.path.charCodeAt(2) === 58 /* Colon */) { | ||
// windows drive letter: file:///c:/far/boo | ||
value = path[1].toLowerCase() + path.substr(2); | ||
value = uri.path[1].toLowerCase() + uri.path.substr(2); | ||
} | ||
else { | ||
// other path | ||
value = path; | ||
value = uri.path; | ||
} | ||
if (isWindows) { | ||
value = value.replace(_slashRegExp, '\\'); | ||
value = value.replace(/\//g, '\\'); | ||
} | ||
return value; | ||
} | ||
//#region ---- decode | ||
function decodeURIComponentGraceful(str) { | ||
try { | ||
return decodeURIComponent(str); | ||
} | ||
catch (_a) { | ||
if (str.length > 3) { | ||
return str.substr(0, 3) + decodeURIComponentGraceful(str.substr(3)); | ||
} | ||
else { | ||
return str; | ||
} | ||
} | ||
} | ||
var _encodedAsHexRegExp = /(%[0-9A-Za-z][0-9A-Za-z])+/g; | ||
function percentDecode(str) { | ||
if (!str.match(_encodedAsHexRegExp)) { | ||
return str; | ||
} | ||
return str.replace(_encodedAsHexRegExp, function (match) { return decodeURIComponentGraceful(match); }); | ||
} | ||
//#endregion | ||
//#region ---- encode | ||
// https://url.spec.whatwg.org/#percent-encoded-bytes | ||
// "The C0 control percent-encode set are the C0 controls and all code points greater than U+007E (~)." | ||
function isC0ControlPercentEncodeSet(code) { | ||
return code <= 0x1F || code > 0x7E; | ||
} | ||
// "The fragment percent-encode set is the C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+003C (<), U+003E (>), and U+0060 (`)." | ||
function isFragmentPercentEncodeSet(code) { | ||
return isC0ControlPercentEncodeSet(code) | ||
|| code === 0x20 || code === 0x22 || code === 0x3C || code === 0x3E || code === 0x60; | ||
} | ||
// "The path percent-encode set is the fragment percent-encode set and U+0023 (#), U+003F (?), U+007B ({), and U+007D (})." | ||
function isPathPercentEncodeSet(code) { | ||
return isFragmentPercentEncodeSet(code) | ||
|| code === 0x23 || code === 0x3F || code === 0x7B || code === 0x7D; | ||
} | ||
// "The userinfo percent-encode set is the path percent-encode set and U+002F (/), U+003A (:), U+003B (;), U+003D (=), U+0040 (@), U+005B ([), U+005C (\), U+005D (]), U+005E (^), and U+007C (|)." | ||
function isUserInfoPercentEncodeSet(code) { | ||
return isPathPercentEncodeSet(code) | ||
|| code === 0x2F || code === 0x3A || code === 0x3B || code === 0x3D || code === 0x40 | ||
|| code === 0x5B || code === 0x5C || code === 0x5D || code === 0x5E || code === 0x7C; | ||
} | ||
// https://url.spec.whatwg.org/#query-state | ||
function isQueryPrecentEncodeSet(code) { | ||
return code < 0x21 || code > 0x7E | ||
|| code === 0x22 || code === 0x23 || code === 0x3C || code === 0x3E | ||
|| code === 0x27; // <- todo@joh https://url.spec.whatwg.org/#is-special | ||
} | ||
// this is non-standard and uses for `URI.toString(true)` | ||
function isHashOrQuestionMark(code) { | ||
return code === 35 /* Hash */ || code === 63 /* QuestionMark */; | ||
} | ||
var _encodeTable = (function () { | ||
var table = []; | ||
for (var code = 0; code < 128; code++) { | ||
table[code] = "%" + code.toString(16); | ||
} | ||
return table; | ||
})(); | ||
function percentEncode(str, mustEncode) { | ||
var lazyOutStr; | ||
for (var pos = 0; pos < str.length; pos++) { | ||
var code = str.charCodeAt(pos); | ||
// invoke encodeURIComponent when needed | ||
if (mustEncode(code)) { | ||
if (!lazyOutStr) { | ||
lazyOutStr = str.substr(0, pos); | ||
} | ||
if (isHighSurrogate(code)) { | ||
// Append encoded version of this surrogate pair (2 characters) | ||
if (pos + 1 < str.length && isLowSurrogate(str.charCodeAt(pos + 1))) { | ||
lazyOutStr += encodeURIComponent(str.substr(pos, 2)); | ||
pos += 1; | ||
} | ||
else { | ||
// broken surrogate pair | ||
lazyOutStr += str.charAt(pos); | ||
} | ||
} | ||
else { | ||
// Append encoded version of the current character, use lookup table | ||
// to speed up repeated encoding of the same characters. | ||
if (code < _encodeTable.length) { | ||
lazyOutStr += _encodeTable[code]; | ||
} | ||
else { | ||
lazyOutStr += encodeURIComponent(str.charAt(pos)); | ||
} | ||
} | ||
continue; | ||
} | ||
// normalize percent encoded sequences to upper case | ||
// todo@joh also changes invalid sequences | ||
if (code === 37 /* PercentSign */ | ||
&& pos + 2 < str.length | ||
&& (isLowerAsciiHex(str.charCodeAt(pos + 1)) || isLowerAsciiHex(str.charCodeAt(pos + 2)))) { | ||
if (!lazyOutStr) { | ||
lazyOutStr = str.substr(0, pos); | ||
} | ||
lazyOutStr += '%' + str.substr(pos + 1, 2).toUpperCase(); | ||
pos += 2; | ||
continue; | ||
} | ||
// once started, continue to build up lazy output | ||
if (lazyOutStr) { | ||
lazyOutStr += str.charAt(pos); | ||
} | ||
} | ||
return lazyOutStr || str; | ||
} | ||
var _normalEncoder = [isUserInfoPercentEncodeSet, isC0ControlPercentEncodeSet, isPathPercentEncodeSet, isQueryPrecentEncodeSet, isFragmentPercentEncodeSet]; | ||
var _minimalEncoder = [isHashOrQuestionMark, isHashOrQuestionMark, isHashOrQuestionMark, isHashOrQuestionMark, function () { return false; }]; | ||
var _driveLetterRegExp = /^(\/?[a-z])(:|%3a)/i; | ||
/** | ||
* Create the external version of a uri | ||
*/ | ||
function _toExternal(encoder, scheme, authority, path, query, fragment) { | ||
function _asFormatted(uri, skipEncoding) { | ||
var encoder = !skipEncoding | ||
? encodeURIComponentFast | ||
: encodeURIComponentMinimal; | ||
var res = ''; | ||
var scheme = uri.scheme, authority = uri.authority, path = uri.path, query = uri.query, fragment = uri.fragment; | ||
if (scheme) { | ||
@@ -607,46 +574,58 @@ res += scheme; | ||
if (authority || scheme === 'file') { | ||
res += '//'; | ||
res += _slash; | ||
res += _slash; | ||
} | ||
if (authority) { | ||
var idxUserInfo = authority.indexOf('@'); | ||
if (idxUserInfo !== -1) { | ||
// <user:token> | ||
var userInfo = authority.substr(0, idxUserInfo); | ||
var idxPasswordOrToken = userInfo.indexOf(':'); | ||
if (idxPasswordOrToken !== -1) { | ||
res += percentEncode(userInfo.substr(0, idxPasswordOrToken), encoder[0 /* user */]); | ||
res += ':'; | ||
res += percentEncode(userInfo.substr(idxPasswordOrToken + 1), encoder[0 /* user */]); | ||
var idx = authority.indexOf('@'); | ||
if (idx !== -1) { | ||
// <user>@<auth> | ||
var userinfo = authority.substr(0, idx); | ||
authority = authority.substr(idx + 1); | ||
idx = userinfo.indexOf(':'); | ||
if (idx === -1) { | ||
res += encoder(userinfo, false); | ||
} | ||
else { | ||
res += percentEncode(userInfo, encoder[0 /* user */]); | ||
// <user>:<pass>@<auth> | ||
res += encoder(userinfo.substr(0, idx), false); | ||
res += ':'; | ||
res += encoder(userinfo.substr(idx + 1), false); | ||
} | ||
res += '@'; | ||
} | ||
authority = authority.substr(idxUserInfo + 1).toLowerCase(); | ||
var idxPort = authority.indexOf(':'); | ||
if (idxPort !== -1) { | ||
// <authority>:<port> | ||
res += percentEncode(authority.substr(0, idxPort), encoder[1 /* authority */]); | ||
res += ':'; | ||
authority = authority.toLowerCase(); | ||
idx = authority.indexOf(':'); | ||
if (idx === -1) { | ||
res += encoder(authority, false); | ||
} | ||
res += percentEncode(authority.substr(idxPort + 1), encoder[1 /* authority */]); | ||
else { | ||
// <auth>:<port> | ||
res += encoder(authority.substr(0, idx), false); | ||
res += authority.substr(idx); | ||
} | ||
} | ||
if (path) { | ||
// encode the path | ||
var pathEncoded = percentEncode(path, encoder[2 /* path */]); | ||
// lower-case windows drive letters in /C:/fff or C:/fff and escape `:` | ||
var match = _driveLetterRegExp.exec(pathEncoded); | ||
if (match) { | ||
pathEncoded = match[1].toLowerCase() + '%3A' + pathEncoded.substr(match[0].length); | ||
// lower-case windows drive letters in /C:/fff or C:/fff | ||
if (path.length >= 3 && path.charCodeAt(0) === 47 /* Slash */ && path.charCodeAt(2) === 58 /* Colon */) { | ||
var code = path.charCodeAt(1); | ||
if (code >= 65 /* A */ && code <= 90 /* Z */) { | ||
path = "/" + String.fromCharCode(code + 32) + ":" + path.substr(3); // "/c:".length === 3 | ||
} | ||
} | ||
res += pathEncoded; | ||
else if (path.length >= 2 && path.charCodeAt(1) === 58 /* Colon */) { | ||
var code = path.charCodeAt(0); | ||
if (code >= 65 /* A */ && code <= 90 /* Z */) { | ||
path = String.fromCharCode(code + 32) + ":" + path.substr(2); // "/c:".length === 3 | ||
} | ||
} | ||
// encode the rest of the path | ||
res += encoder(path, true); | ||
} | ||
if (query) { | ||
res += '?'; | ||
res += percentEncode(query, encoder[3 /* query */]); | ||
res += encoder(query, false); | ||
} | ||
if (fragment) { | ||
res += '#'; | ||
res += percentEncode(fragment, encoder[4 /* fragment */]); | ||
res += !skipEncoding ? encodeURIComponentFast(fragment, false) : fragment; | ||
} | ||
@@ -656,2 +635,1 @@ return res; | ||
}); | ||
//#endregion |
{ | ||
"name": "vscode-uri", | ||
"author": "Microsoft", | ||
"version": "2.1.0", | ||
"version": "2.1.1", | ||
"description": "The URI implementation that is used by VS Code and its extensions", | ||
@@ -6,0 +6,0 @@ "main": "./lib/umd/index.js", |
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
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
62089
1483