Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "vscode-uri",
"author": "Microsoft",
"version": "3.0.6",
"version": "3.0.7",
"description": "The URI implementation that is used by VS Code and its extensions",
"main": "./lib/umd/index.js",
"typings": "./lib/umd/index",
Expand Down
52 changes: 32 additions & 20 deletions src/uri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,29 +114,29 @@ export class URI implements UriComponents {
}

/**
* scheme is the 'http' part of 'http://www.msft.com/some/path?query#fragment'.
* scheme is the 'http' part of 'http://www.example.com/some/path?query#fragment'.
* The part before the first colon.
*/
readonly scheme: string;

/**
* authority is the 'www.msft.com' part of 'http://www.msft.com/some/path?query#fragment'.
* authority is the 'www.example.com' part of 'http://www.example.com/some/path?query#fragment'.
* The part between the first double slashes and the next slash.
*/
readonly authority: string;

/**
* path is the '/some/path' part of 'http://www.msft.com/some/path?query#fragment'.
* path is the '/some/path' part of 'http://www.example.com/some/path?query#fragment'.
*/
readonly path: string;

/**
* query is the 'query' part of 'http://www.msft.com/some/path?query#fragment'.
* query is the 'query' part of 'http://www.example.com/some/path?query#fragment'.
*/
readonly query: string;

/**
* fragment is the 'fragment' part of 'http://www.msft.com/some/path?query#fragment'.
* fragment is the 'fragment' part of 'http://www.example.com/some/path?query#fragment'.
*/
readonly fragment: string;

Expand Down Expand Up @@ -258,7 +258,7 @@ export class URI implements UriComponents {
// ---- parse & validate ------------------------

/**
* Creates a new URI from a string, e.g. `http://www.msft.com/some/path`,
* Creates a new URI from a string, e.g. `http://www.example.com/some/path`,
* `file:///usr/home`, or `scheme:with/path`.
*
* @param value A string which represents an URI (see `URI#toString`).
Expand Down Expand Up @@ -327,13 +327,15 @@ export class URI implements UriComponents {
}

static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI {
return new Uri(
const result = new Uri(
components.scheme,
components.authority,
components.path,
components.query,
components.fragment,
);
_validateUri(result, true);
return result;
}

// ---- printing/externalize ---------------------------
Expand Down Expand Up @@ -392,7 +394,7 @@ interface UriState extends UriComponents {

const _pathSepMarker = isWindows ? 1 : undefined;

// This class exists so that URI is compatibile with vscode.Uri (API).
// This class exists so that URI is compatible with vscode.Uri (API).
class Uri extends URI {

_formatted: string | null = null;
Expand Down Expand Up @@ -474,7 +476,7 @@ const encodeTable: { [ch: number]: string } = {
[CharCode.Space]: '%20',
};

function encodeURIComponentFast(uriComponent: string, allowSlash: boolean): string {
function encodeURIComponentFast(uriComponent: string, isPath: boolean, isAuthority: boolean): string {
let res: string | undefined = undefined;
let nativeEncodePos = -1;

Expand All @@ -490,7 +492,10 @@ function encodeURIComponentFast(uriComponent: string, allowSlash: boolean): stri
|| code === CharCode.Period
|| code === CharCode.Underline
|| code === CharCode.Tilde
|| (allowSlash && code === CharCode.Slash)
|| (isPath && code === CharCode.Slash)
|| (isAuthority && code === CharCode.OpenSquareBracket)
|| (isAuthority && code === CharCode.CloseSquareBracket)
|| (isAuthority && code === CharCode.Colon)
) {
// check if we are delaying native encode
if (nativeEncodePos !== -1) {
Expand Down Expand Up @@ -608,24 +613,24 @@ function _asFormatted(uri: URI, skipEncoding: boolean): string {
// <user>@<auth>
const userinfo = authority.substr(0, idx);
authority = authority.substr(idx + 1);
idx = userinfo.indexOf(':');
idx = userinfo.lastIndexOf(':');
if (idx === -1) {
res += encoder(userinfo, false);
res += encoder(userinfo, false, false);
} else {
// <user>:<pass>@<auth>
res += encoder(userinfo.substr(0, idx), false);
res += encoder(userinfo.substr(0, idx), false, false);
res += ':';
res += encoder(userinfo.substr(idx + 1), false);
res += encoder(userinfo.substr(idx + 1), false, true);
}
res += '@';
}
authority = authority.toLowerCase();
idx = authority.indexOf(':');
idx = authority.lastIndexOf(':');
if (idx === -1) {
res += encoder(authority, false);
res += encoder(authority, false, true);
} else {
// <auth>:<port>
res += encoder(authority.substr(0, idx), false);
res += encoder(authority.substr(0, idx), false, true);
res += authority.substr(idx);
}
}
Expand All @@ -643,15 +648,15 @@ function _asFormatted(uri: URI, skipEncoding: boolean): string {
}
}
// encode the rest of the path
res += encoder(path, true);
res += encoder(path, true, false);
}
if (query) {
res += '?';
res += encoder(query, false);
res += encoder(query, false, false);
}
if (fragment) {
res += '#';
res += !skipEncoding ? encodeURIComponentFast(fragment, false) : fragment;
res += !skipEncoding ? encodeURIComponentFast(fragment, false, false) : fragment;
}
return res;
}
Expand All @@ -678,3 +683,10 @@ function percentDecode(str: string): string {
}
return str.replace(_rEncodedAsHex, (match) => decodeURIComponentGraceful(match));
}

/**
* Mapped-type that replaces all occurrences of URI with UriComponents
*/
export type UriDto<T> = { [K in keyof T]: T[K] extends URI
? UriComponents
: UriDto<T[K]> };