@azure-tools/uri
Version:
Common URI handling code.
235 lines • 9.16 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MakeRelativeUri = exports.ParentFolderUri = exports.ResolveUri = exports.GetFilenameWithoutExtension = exports.GetFilename = exports.ToRawDataUrl = exports.CreateFolderUri = exports.CreateFileUri = exports.EnsureIsFolderUri = exports.EnsureIfFileUri = exports.CreateFileOrFolderUri = exports.IsUri = exports.makeRelativeUri = exports.parentFolderUri = exports.resolveUri = exports.toRawDataUrl = exports.getFilenameWithoutExtension = exports.getFilename = exports.createFolderUri = exports.createFileUri = exports.ensureIsFolderUri = exports.ensureIfFileUri = exports.createFileOrFolderUri = exports.isUri = exports.simplifyUri = void 0;
/* eslint-disable no-useless-escape */
const os_1 = require("os");
const url_1 = require("url");
const URI = require("urijs");
const fileUri = require("file-url");
const RELATIVE_PROTOCOL = "relative:///";
/**
* Remove extra / in the url path.
* @param url
*/
function cleanUrlPath(url) {
const pathname = url.pathname
.replace(/\\/g, "/") // Replace \ => /
.replace(/\/\//g, "/"); // Replace // => /;
// Means the url is a windows absolute path without the file:// protocol(drive letter gets parsed as the protocol.)
if (url.protocol.length === 2) {
return new url_1.URL(`${url.protocol}${pathname}`);
}
const newUrl = new url_1.URL(url.toString());
newUrl.pathname = pathname;
return newUrl;
}
/**
* Simplify the given uri by resolving relative paths.
*
* @param uri
* @returns fully qualified url with protocol. Defaults to null:// if not provided
*/
function simplifyUri(uri) {
return cleanUrlPath(new url_1.URL(uri, RELATIVE_PROTOCOL)).toString();
}
exports.simplifyUri = simplifyUri;
function isUri(uri) {
return /^([a-z0-9+.-]+):(?:\/\/(?:((?:[a-z0-9-._~!$&'()*+,;=:]|%[0-9A-F]{2})*)@)?((?:[a-z0-9-._~!$&'()*+,;=]|%[0-9A-F]{2})*)(?::(\d*))?(\/(?:[a-z0-9-._~!$&'()*+,;=:@/]|%[0-9A-F]{2})*)?|(\/?(?:[a-z0-9-._~!$&'()*+,;=:@]|%[0-9A-F]{2})+(?:[a-z0-9-._~!$&'()*+,;=:@/]|%[0-9A-F]{2})*)?)(?:\?((?:[a-z0-9-._~!$&'()*+,;=:/?@]|%[0-9A-F]{2})*))?(?:#((?:[a-z0-9-._~!$&'()*+,;=:/?@]|%[0-9A-F]{2})*))?$/i.test(uri);
}
exports.isUri = isUri;
/**
* remake of path.isAbsolute... because it's platform dependent:
* Windows: C:\\... -> true /... -> true
* Linux: C:\\... -> false /... -> true
*/
function isAbsolute(path) {
return !!path.match(/^([a-zA-Z]:)?(\/|\\)/);
}
/**
* determines what an absolute URI is for our purposes, consider:
* - we had Ruby try to use "Azure::ARM::SQL" as a file name, so that should not be considered absolute
* - we want simple, easily predictable semantics
*/
function isUriAbsolute(url) {
return /^[a-z]+:\/\//.test(url);
}
/**
* Create a 'file:///' URI from given absolute path.
* Examples:
* - "C:\swagger\storage.yaml" -> "file:///C:/swagger/storage.yaml"
* - "/input/swagger.yaml" -> "file:///input/swagger.yaml"
*/
function createFileOrFolderUri(absolutePath) {
if (!isAbsolute(absolutePath)) {
throw new Error(`Can only create file URIs from absolute paths. Got '${absolutePath}'`);
}
let result = fileUri(absolutePath, { resolve: false });
// handle UNCs
if (absolutePath.startsWith("//") || absolutePath.startsWith("\\\\")) {
result = result.replace(/^file:\/\/\/\//, "file://");
}
return result;
}
exports.createFileOrFolderUri = createFileOrFolderUri;
function ensureIfFileUri(uri) {
return uri.replace(/\/$/g, "");
}
exports.ensureIfFileUri = ensureIfFileUri;
function ensureIsFolderUri(uri) {
return ensureIfFileUri(uri) + "/";
}
exports.ensureIsFolderUri = ensureIsFolderUri;
function createFileUri(absolutePath) {
return ensureIfFileUri(createFileOrFolderUri(absolutePath));
}
exports.createFileUri = createFileUri;
function createFolderUri(absolutePath) {
return ensureIsFolderUri(createFileOrFolderUri(absolutePath));
}
exports.createFolderUri = createFolderUri;
function getFilename(uri) {
return uri.split("/").reverse()[0].split("\\").reverse()[0];
}
exports.getFilename = getFilename;
function getFilenameWithoutExtension(uri) {
const lastPart = getFilename(uri);
const ext = lastPart.indexOf(".") === -1 ? "" : lastPart.split(".").reverse()[0];
return lastPart.substr(0, lastPart.length - ext.length - 1);
}
exports.getFilenameWithoutExtension = getFilenameWithoutExtension;
function toRawDataUrl(uri) {
uri = simplifyUri(uri);
// special URI handlers (the 'if's shouldn't be necessary but provide some additional isolation in case there is anything wrong with one of the regexes)
// - GitHub repo
if (uri.startsWith("https://github.com")) {
uri = uri.replace(/^https?:\/\/(github.com)(\/[^\/]+\/[^\/]+\/)(blob|tree)\/(.*)$/gi, "https://raw.githubusercontent.com$2$4");
}
// - GitHub gist
if (uri.startsWith("gist://")) {
uri = uri.replace(/^gist:\/\/([^\/]+\/[^\/]+)$/gi, "https://gist.githubusercontent.com/$1/raw/");
}
if (uri.startsWith("https://gist.github.com")) {
uri = uri.replace(/^https?:\/\/gist.github.com\/([^\/]+\/[^\/]+)$/gi, "https://gist.githubusercontent.com/$1/raw/");
}
if (uri.startsWith(RELATIVE_PROTOCOL)) {
uri = uri.substr(RELATIVE_PROTOCOL.length);
}
return uri;
}
exports.toRawDataUrl = toRawDataUrl;
/**
* The singularity of all resolving.
* With URI as our one data type of truth, this method maps an absolute or relative path or URI to a URI using given base URI.
* @param baseUri Absolute base URI
* @param pathOrUri Relative/absolute path/URI
* @returns Absolute URI
*/
function resolveUri(baseUri, pathOrUri) {
if (pathOrUri.startsWith("~/")) {
pathOrUri = pathOrUri.replace(/^~/, os_1.homedir());
}
if (isAbsolute(pathOrUri)) {
return createFileOrFolderUri(pathOrUri);
}
// known here: `pathOrUri` is eiher URI (relative or absolute) or relative path - which we can normalize to a relative URI
pathOrUri = pathOrUri.replace(/\\/g, "/");
// known here: `pathOrUri` is a URI (relative or absolute)
if (isUriAbsolute(pathOrUri)) {
return pathOrUri;
}
// known here: `pathOrUri` is a relative URI
if (!baseUri) {
throw new Error("'pathOrUri' was detected to be relative so 'baseUri' is required");
}
try {
const base = new URI(baseUri);
const relative = new URI(pathOrUri);
if (baseUri.startsWith("untitled:///") && pathOrUri.startsWith("untitled:")) {
return pathOrUri;
}
const result = relative.absoluteTo(base);
// GitHub simple token forwarding, for when you pass a URI to a private repo file with `?token=` query parameter.
// this may be easier for quick testing than getting and passing an OAuth token.
if (base.protocol() === "https" &&
base.hostname() === "raw.githubusercontent.com" &&
result.protocol() === "https" &&
result.hostname() === "raw.githubusercontent.com") {
result.query(base.query());
}
return simplifyUri(result.toString());
}
catch (e) {
throw new Error(`Failed resolving '${pathOrUri}' against '${baseUri}'.`);
}
}
exports.resolveUri = resolveUri;
function parentFolderUri(uri) {
// root?
if (uri.endsWith("//")) {
return null;
}
// folder? => cut away last "/"
if (uri.endsWith("/")) {
uri = uri.slice(0, uri.length - 1);
}
// cut away last component
const compLen = uri.split("/").reverse()[0].length;
return uri.slice(0, uri.length - compLen);
}
exports.parentFolderUri = parentFolderUri;
function makeRelativeUri(baseUri, absoluteUri) {
return new URI(absoluteUri).relativeTo(baseUri).toString();
}
exports.makeRelativeUri = makeRelativeUri;
//------------------------------------------
// Legacy names, will be removed in next major version
//------------------------------------------
/**
* @deprecated use isUri instead.
*/
exports.IsUri = isUri;
/**
* @deprecated use createFileOrFolderUri instead.
*/
exports.CreateFileOrFolderUri = createFileOrFolderUri;
/**
* @deprecated use ensureIfFileUri instead.
*/
exports.EnsureIfFileUri = ensureIfFileUri;
/**
* @deprecated use ensureIsFolderUri instead.
*/
exports.EnsureIsFolderUri = ensureIsFolderUri;
/**
* @deprecated use createFileUri instead.
*/
exports.CreateFileUri = createFileUri;
/**
* @deprecated use createFolderUri instead.
*/
exports.CreateFolderUri = createFolderUri;
/**
* @deprecated use toRawDataUrl instead.
*/
exports.ToRawDataUrl = toRawDataUrl;
/**
* @deprecated use getFilename instead.
*/
exports.GetFilename = getFilename;
/**
* @deprecated use getFilenameWithoutExtension instead.
*/
exports.GetFilenameWithoutExtension = getFilenameWithoutExtension;
/**
* @deprecated use resolveUri instead.
*/
exports.ResolveUri = resolveUri;
/**
* @deprecated use parentFolderUri instead.
*/
exports.ParentFolderUri = parentFolderUri;
/**
* @deprecated use makeRelativeUri instead.
*/
exports.MakeRelativeUri = makeRelativeUri;
//# sourceMappingURL=uri-manipulation.js.map