UNPKG

@theia/core

Version:

Theia is a cloud & desktop IDE framework implemented in TypeScript.

278 lines (241 loc) • 7.45 kB
// ***************************************************************************** // Copyright (C) 2017 TypeFox and others. // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License v. 2.0 which is available at // http://www.eclipse.org/legal/epl-2.0. // // This Source Code may also be made available under the following Secondary // Licenses when the conditions for such availability set forth in the Eclipse // Public License v. 2.0 are satisfied: GNU General Public License, version 2 // with the GNU Classpath Exception which is available at // https://www.gnu.org/software/classpath/license.html. // // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** import { URI as Uri } from 'vscode-uri'; import { Path } from './path'; export class URI { public static fromComponents(components: UriComponents): URI { return new URI(Uri.revive(components)); } public static fromFilePath(path: string): URI { return new URI(Uri.file(path)); } private readonly codeUri: Uri; private _path: Path | undefined; constructor(uri: string | Uri = '') { if (uri instanceof Uri) { this.codeUri = uri; } else { this.codeUri = Uri.parse(uri); } } /** * TODO move implementation to `DefaultUriLabelProviderContribution.getName` * * @deprecated use `LabelProvider.getName` instead */ get displayName(): string { const base = this.path.base; if (base) { return base; } if (this.path.isRoot) { return this.path.fsPath(); } return ''; } /** * Return all uri from the current to the top most. */ get allLocations(): URI[] { const locations = []; let location: URI = this; while (!location.path.isRoot && location.path.hasDir) { locations.push(location); location = location.parent; } locations.push(location); return locations; } get parent(): URI { if (this.path.isRoot) { return this; } return this.withPath(this.path.dir); } relative(uri: URI): Path | undefined { if (this.authority !== uri.authority || this.scheme !== uri.scheme) { return undefined; } return this.path.relative(uri.path); } resolve(path: string | Path): URI { return this.withPath(this.path.join(path.toString())); } /** * @returns a new, absolute URI if one can be computed from the path segments passed in. */ resolveToAbsolute(...pathSegments: Array<string | Path>): URI | undefined { const absolutePath = this.path.resolve(...pathSegments.map(path => path.toString())); if (absolutePath) { return this.withPath(absolutePath); } } /** * return a new URI replacing the current with the given scheme */ withScheme(scheme: string): URI { const newCodeUri = Uri.from({ ...this.codeUri.toJSON(), scheme }); return new URI(newCodeUri); } /** * return a new URI replacing the current with the given authority */ withAuthority(authority: string): URI { const newCodeUri = Uri.from({ ...this.codeUri.toJSON(), scheme: this.codeUri.scheme, authority }); return new URI(newCodeUri); } /** * return this URI without a authority */ withoutAuthority(): URI { return this.withAuthority(''); } /** * return a new URI replacing the current with the given path */ withPath(path: string | Path): URI { const newCodeUri = Uri.from({ ...this.codeUri.toJSON(), scheme: this.codeUri.scheme, path: path.toString() }); return new URI(newCodeUri); } /** * return this URI without a path */ withoutPath(): URI { return this.withPath(''); } /** * return a new URI replacing the current with the given query */ withQuery(query: string): URI { const newCodeUri = Uri.from({ ...this.codeUri.toJSON(), scheme: this.codeUri.scheme, query }); return new URI(newCodeUri); } /** * return this URI without a query */ withoutQuery(): URI { return this.withQuery(''); } /** * return a new URI replacing the current with the given fragment */ withFragment(fragment: string): URI { const newCodeUri = Uri.from({ ...this.codeUri.toJSON(), scheme: this.codeUri.scheme, fragment }); return new URI(newCodeUri); } /** * return this URI without a fragment */ withoutFragment(): URI { return this.withFragment(''); } /** * return a new URI replacing the current with its normalized path, resolving '..' and '.' segments */ normalizePath(): URI { return this.withPath(this.path.normalize()); } get scheme(): string { return this.codeUri.scheme; } get authority(): string { return this.codeUri.authority; } get path(): Path { if (this._path === undefined) { this._path = new Path(this.codeUri.path); } return this._path; } get query(): string { return this.codeUri.query; } get fragment(): string { return this.codeUri.fragment; } toString(skipEncoding?: boolean): string { return this.codeUri.toString(skipEncoding); } isEqual(uri: URI, caseSensitive: boolean = true): boolean { if (!this.hasSameOrigin(uri)) { return false; } return caseSensitive ? this.toString() === uri.toString() : this.toString().toLowerCase() === uri.toString().toLowerCase(); } isEqualOrParent(uri: URI, caseSensitive: boolean = true): boolean { if (!this.hasSameOrigin(uri)) { return false; } let left = this.path; let right = uri.path; if (!caseSensitive) { left = new Path(left.toString().toLowerCase()); right = new Path(right.toString().toLowerCase()); } return left.isEqualOrParent(right); } static getDistinctParents(uris: URI[]): URI[] { const result: URI[] = []; uris.forEach((uri, i) => { if (!uris.some((otherUri, index) => index !== i && otherUri.isEqualOrParent(uri))) { result.push(uri); } }); return result; } private hasSameOrigin(uri: URI): boolean { return (this.authority === uri.authority) && (this.scheme === uri.scheme); } toComponents(): UriComponents { return { scheme: this.scheme, authority: this.authority, path: this.path.toString(), query: this.query, fragment: this.fragment }; } } export interface UriComponents { scheme: string; authority: string; path: string; query: string; fragment: string; external?: string; } export default URI;