mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-27 17:23:21 -05:00
move code from parts to contrib (#8319)
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
export type CellType = 'code' | 'markdown' | 'raw';
|
||||
|
||||
export class CellTypes {
|
||||
public static readonly Code = 'code';
|
||||
public static readonly Markdown = 'markdown';
|
||||
public static readonly Raw = 'raw';
|
||||
}
|
||||
|
||||
// to do: add all mime types
|
||||
export type MimeType = 'text/plain' | 'text/html';
|
||||
|
||||
// to do: add all mime types
|
||||
export class MimeTypes {
|
||||
public static readonly PlainText = 'text/plain';
|
||||
public static readonly HTML = 'text/html';
|
||||
}
|
||||
|
||||
export type OutputType =
|
||||
| 'execute_result'
|
||||
| 'display_data'
|
||||
| 'stream'
|
||||
| 'error'
|
||||
| 'update_display_data';
|
||||
|
||||
export class OutputTypes {
|
||||
public static readonly ExecuteResult = 'execute_result';
|
||||
public static readonly DisplayData = 'display_data';
|
||||
public static readonly Stream = 'stream';
|
||||
public static readonly Error = 'error';
|
||||
public static readonly UpdateDisplayData = 'update_display_data';
|
||||
}
|
||||
|
||||
export enum NotebookChangeType {
|
||||
CellsModified,
|
||||
CellSourceUpdated,
|
||||
CellOutputUpdated,
|
||||
DirtyStateChanged,
|
||||
KernelChanged,
|
||||
TrustChanged,
|
||||
Saved,
|
||||
CellExecuted,
|
||||
CellInputVisibilityChanged,
|
||||
CellOutputCleared
|
||||
}
|
||||
53
src/sql/workbench/contrib/notebook/common/models/jsonext.ts
Normal file
53
src/sql/workbench/contrib/notebook/common/models/jsonext.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
/**
|
||||
* A type alias for a JSON primitive.
|
||||
*/
|
||||
export declare type JSONPrimitive = boolean | number | string | null;
|
||||
/**
|
||||
* A type alias for a JSON value.
|
||||
*/
|
||||
export declare type JSONValue = JSONPrimitive | JSONObject | JSONArray;
|
||||
/**
|
||||
* A type definition for a JSON object.
|
||||
*/
|
||||
export interface JSONObject {
|
||||
[key: string]: JSONValue;
|
||||
}
|
||||
/**
|
||||
* A type definition for a JSON array.
|
||||
*/
|
||||
export interface JSONArray extends Array<JSONValue> {
|
||||
}
|
||||
/**
|
||||
* A type definition for a readonly JSON object.
|
||||
*/
|
||||
export interface ReadonlyJSONObject {
|
||||
readonly [key: string]: ReadonlyJSONValue;
|
||||
}
|
||||
/**
|
||||
* A type definition for a readonly JSON array.
|
||||
*/
|
||||
export interface ReadonlyJSONArray extends ReadonlyArray<ReadonlyJSONValue> {
|
||||
}
|
||||
/**
|
||||
* A type alias for a readonly JSON value.
|
||||
*/
|
||||
export declare type ReadonlyJSONValue = JSONPrimitive | ReadonlyJSONObject | ReadonlyJSONArray;
|
||||
/**
|
||||
* Test whether a JSON value is a primitive.
|
||||
*
|
||||
* @param value - The JSON value of interest.
|
||||
*
|
||||
* @returns `true` if the value is a primitive,`false` otherwise.
|
||||
*/
|
||||
export function isPrimitive(value: any): boolean {
|
||||
return (
|
||||
value === null ||
|
||||
typeof value === 'boolean' ||
|
||||
typeof value === 'number' ||
|
||||
typeof value === 'string'
|
||||
);
|
||||
}
|
||||
494
src/sql/workbench/contrib/notebook/common/models/nbformat.ts
Normal file
494
src/sql/workbench/contrib/notebook/common/models/nbformat.ts
Normal file
@@ -0,0 +1,494 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
// Notebook format interfaces
|
||||
// https://nbformat.readthedocs.io/en/latest/format_description.html
|
||||
// https://github.com/jupyter/nbformat/blob/master/nbformat/v4/nbformat.v4.schema.json
|
||||
|
||||
|
||||
import { JSONObject } from './jsonext';
|
||||
import { nb } from 'azdata';
|
||||
|
||||
/**
|
||||
* A namespace for nbformat interfaces.
|
||||
*/
|
||||
export namespace nbformat {
|
||||
/**
|
||||
* The major version of the notebook format.
|
||||
*/
|
||||
export const MAJOR_VERSION: number = 4;
|
||||
|
||||
/**
|
||||
* The minor version of the notebook format.
|
||||
*/
|
||||
export const MINOR_VERSION: number = 2;
|
||||
|
||||
/**
|
||||
* The kernelspec metadata.
|
||||
*/
|
||||
export interface IKernelspecMetadata extends JSONObject {
|
||||
name: string;
|
||||
display_name: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The language info metatda
|
||||
*/
|
||||
export interface ILanguageInfoMetadata extends JSONObject {
|
||||
name: string;
|
||||
codemirror_mode?: string | JSONObject;
|
||||
file_extension?: string;
|
||||
mimetype?: string;
|
||||
pygments_lexer?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default metadata for the notebook.
|
||||
*/
|
||||
export interface INotebookMetadata extends JSONObject {
|
||||
kernelspec?: IKernelspecMetadata;
|
||||
language_info?: ILanguageInfoMetadata;
|
||||
orig_nbformat: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* The notebook content.
|
||||
*/
|
||||
export interface INotebookContent {
|
||||
metadata: INotebookMetadata;
|
||||
nbformat_minor: number;
|
||||
nbformat: number;
|
||||
cells: ICell[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A multiline string.
|
||||
*/
|
||||
export type MultilineString = string | string[];
|
||||
|
||||
/**
|
||||
* A mime-type keyed dictionary of data.
|
||||
*/
|
||||
export interface IMimeBundle extends JSONObject {
|
||||
[key: string]: MultilineString | JSONObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Media attachments (e.g. inline images).
|
||||
*/
|
||||
export interface IAttachments {
|
||||
[key: string]: IMimeBundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* The code cell's prompt number. Will be null if the cell has not been run.
|
||||
*/
|
||||
export type ExecutionCount = number | null;
|
||||
|
||||
/**
|
||||
* Cell output metadata.
|
||||
*/
|
||||
export type OutputMetadata = JSONObject;
|
||||
|
||||
/**
|
||||
* Validate a mime type/value pair.
|
||||
*
|
||||
* @param type - The mimetype name.
|
||||
*
|
||||
* @param value - The value associated with the type.
|
||||
*
|
||||
* @returns Whether the type/value pair are valid.
|
||||
*/
|
||||
export function validateMimeValue(
|
||||
type: string,
|
||||
value: MultilineString | JSONObject
|
||||
): boolean {
|
||||
// Check if "application/json" or "application/foo+json"
|
||||
const jsonTest = /^application\/(.*?)+\+json$/;
|
||||
const isJSONType = type === 'application/json' || jsonTest.test(type);
|
||||
|
||||
let isString = (x: any) => {
|
||||
return Object.prototype.toString.call(x) === '[object String]';
|
||||
};
|
||||
|
||||
// If it is an array, make sure if is not a JSON type and it is an
|
||||
// array of strings.
|
||||
if (Array.isArray(value)) {
|
||||
if (isJSONType) {
|
||||
return false;
|
||||
}
|
||||
let valid = true;
|
||||
(value as string[]).forEach(v => {
|
||||
if (!isString(v)) {
|
||||
valid = false;
|
||||
}
|
||||
});
|
||||
return valid;
|
||||
}
|
||||
|
||||
// If it is a string, make sure we are not a JSON type.
|
||||
if (isString(value)) {
|
||||
return !isJSONType;
|
||||
}
|
||||
|
||||
// It is not a string, make sure it is a JSON type.
|
||||
if (!isJSONType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// It is a JSON type, make sure it is a valid JSON object.
|
||||
// return JSONExt.isObject(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cell-level metadata.
|
||||
*/
|
||||
export interface IBaseCellMetadata extends JSONObject {
|
||||
/**
|
||||
* Whether the cell is trusted.
|
||||
*
|
||||
* #### Notes
|
||||
* This is not strictly part of the nbformat spec, but it is added by
|
||||
* the contents manager.
|
||||
*
|
||||
* See https://jupyter-notebook.readthedocs.io/en/latest/security.html.
|
||||
*/
|
||||
trusted: boolean;
|
||||
|
||||
/**
|
||||
* The cell's name. If present, must be a non-empty string.
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* The cell's tags. Tags must be unique, and must not contain commas.
|
||||
*/
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* The base cell interface.
|
||||
*/
|
||||
export interface IBaseCell {
|
||||
/**
|
||||
* String identifying the type of cell.
|
||||
*/
|
||||
cell_type: string;
|
||||
|
||||
/**
|
||||
* Contents of the cell, represented as an array of lines.
|
||||
*/
|
||||
source: MultilineString;
|
||||
|
||||
/**
|
||||
* Cell-level metadata.
|
||||
*/
|
||||
metadata: Partial<ICellMetadata>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Metadata for the raw cell.
|
||||
*/
|
||||
export interface IRawCellMetadata extends IBaseCellMetadata {
|
||||
/**
|
||||
* Raw cell metadata format for nbconvert.
|
||||
*/
|
||||
format: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A raw cell.
|
||||
*/
|
||||
export interface IRawCell extends IBaseCell {
|
||||
/**
|
||||
* String identifying the type of cell.
|
||||
*/
|
||||
cell_type: 'raw';
|
||||
|
||||
/**
|
||||
* Cell-level metadata.
|
||||
*/
|
||||
metadata: Partial<IRawCellMetadata>;
|
||||
|
||||
/**
|
||||
* Cell attachments.
|
||||
*/
|
||||
attachments?: IAttachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* A markdown cell.
|
||||
*/
|
||||
export interface IMarkdownCell extends IBaseCell {
|
||||
/**
|
||||
* String identifying the type of cell.
|
||||
*/
|
||||
cell_type: 'markdown';
|
||||
|
||||
/**
|
||||
* Cell attachments.
|
||||
*/
|
||||
attachments?: IAttachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Metadata for a code cell.
|
||||
*/
|
||||
export interface ICodeCellMetadata extends IBaseCellMetadata {
|
||||
/**
|
||||
* Whether the cell is collapsed/expanded.
|
||||
*/
|
||||
collapsed: boolean;
|
||||
|
||||
/**
|
||||
* Whether the cell's output is scrolled, unscrolled, or autoscrolled.
|
||||
*/
|
||||
scrolled: boolean | 'auto';
|
||||
}
|
||||
|
||||
/**
|
||||
* A code cell.
|
||||
*/
|
||||
export interface ICodeCell extends IBaseCell {
|
||||
/**
|
||||
* String identifying the type of cell.
|
||||
*/
|
||||
cell_type: 'code';
|
||||
|
||||
/**
|
||||
* Cell-level metadata.
|
||||
*/
|
||||
metadata: Partial<ICodeCellMetadata>;
|
||||
|
||||
/**
|
||||
* Execution, display, or stream outputs.
|
||||
*/
|
||||
outputs: IOutput[];
|
||||
|
||||
/**
|
||||
* The code cell's prompt number. Will be null if the cell has not been run.
|
||||
*/
|
||||
execution_count: ExecutionCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* An unrecognized cell.
|
||||
*/
|
||||
export interface IUnrecognizedCell extends IBaseCell { }
|
||||
|
||||
/**
|
||||
* A cell union type.
|
||||
*/
|
||||
export type ICell = IRawCell | IMarkdownCell | ICodeCell | IUnrecognizedCell;
|
||||
|
||||
/**
|
||||
* Test whether a cell is a raw cell.
|
||||
*/
|
||||
export function isRaw(cell: ICell): cell is IRawCell {
|
||||
return cell.cell_type === 'raw';
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a cell is a markdown cell.
|
||||
*/
|
||||
export function isMarkdown(cell: ICell): cell is IMarkdownCell {
|
||||
return cell.cell_type === 'markdown';
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a cell is a code cell.
|
||||
*/
|
||||
export function isCode(cell: ICell): cell is ICodeCell {
|
||||
return cell.cell_type === 'code';
|
||||
}
|
||||
|
||||
/**
|
||||
* A union metadata type.
|
||||
*/
|
||||
export type ICellMetadata =
|
||||
| IBaseCellMetadata
|
||||
| IRawCellMetadata
|
||||
| ICodeCellMetadata;
|
||||
|
||||
/**
|
||||
* The valid output types.
|
||||
*/
|
||||
export type OutputType =
|
||||
| 'execute_result'
|
||||
| 'display_data'
|
||||
| 'stream'
|
||||
| 'error'
|
||||
| 'update_display_data';
|
||||
|
||||
|
||||
/**
|
||||
* Result of executing a code cell.
|
||||
*/
|
||||
export interface IExecuteResult extends nb.ICellOutput {
|
||||
/**
|
||||
* Type of cell output.
|
||||
*/
|
||||
output_type: 'execute_result';
|
||||
|
||||
/**
|
||||
* A result's prompt number.
|
||||
*/
|
||||
execution_count: ExecutionCount;
|
||||
|
||||
/**
|
||||
* A mime-type keyed dictionary of data.
|
||||
*/
|
||||
data: IMimeBundle;
|
||||
|
||||
/**
|
||||
* Cell output metadata.
|
||||
*/
|
||||
metadata: OutputMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data displayed as a result of code cell execution.
|
||||
*/
|
||||
export interface IDisplayData extends nb.ICellOutput {
|
||||
/**
|
||||
* Type of cell output.
|
||||
*/
|
||||
output_type: 'display_data';
|
||||
|
||||
/**
|
||||
* A mime-type keyed dictionary of data.
|
||||
*/
|
||||
data: IMimeBundle;
|
||||
|
||||
/**
|
||||
* Cell output metadata.
|
||||
*/
|
||||
metadata: OutputMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data displayed as an update to existing display data.
|
||||
*/
|
||||
export interface IDisplayUpdate extends nb.ICellOutput {
|
||||
/**
|
||||
* Type of cell output.
|
||||
*/
|
||||
output_type: 'update_display_data';
|
||||
|
||||
/**
|
||||
* A mime-type keyed dictionary of data.
|
||||
*/
|
||||
data: IMimeBundle;
|
||||
|
||||
/**
|
||||
* Cell output metadata.
|
||||
*/
|
||||
metadata: OutputMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream output from a code cell.
|
||||
*/
|
||||
export interface IStream extends nb.ICellOutput {
|
||||
/**
|
||||
* Type of cell output.
|
||||
*/
|
||||
output_type: 'stream';
|
||||
|
||||
/**
|
||||
* The name of the stream.
|
||||
*/
|
||||
name: StreamType;
|
||||
|
||||
/**
|
||||
* The stream's text output.
|
||||
*/
|
||||
text: MultilineString;
|
||||
}
|
||||
|
||||
/**
|
||||
* An alias for a stream type.
|
||||
*/
|
||||
export type StreamType = 'stdout' | 'stderr';
|
||||
|
||||
/**
|
||||
* Output of an error that occurred during code cell execution.
|
||||
*/
|
||||
export interface IError extends nb.ICellOutput {
|
||||
/**
|
||||
* Type of cell output.
|
||||
*/
|
||||
output_type: 'error';
|
||||
|
||||
/**
|
||||
* The name of the error.
|
||||
*/
|
||||
ename: string;
|
||||
|
||||
/**
|
||||
* The value, or message, of the error.
|
||||
*/
|
||||
evalue: string;
|
||||
|
||||
/**
|
||||
* The error's traceback.
|
||||
*/
|
||||
traceback: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Unrecognized output.
|
||||
*/
|
||||
export interface IUnrecognizedOutput extends nb.ICellOutput { }
|
||||
|
||||
/**
|
||||
* Test whether an output is an execute result.
|
||||
*/
|
||||
export function isExecuteResult(output: IOutput): output is IExecuteResult {
|
||||
return output.output_type === 'execute_result';
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether an output is from display data.
|
||||
*/
|
||||
export function isDisplayData(output: IOutput): output is IDisplayData {
|
||||
return output.output_type === 'display_data';
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether an output is from updated display data.
|
||||
*/
|
||||
export function isDisplayUpdate(output: IOutput): output is IDisplayUpdate {
|
||||
return output.output_type === 'update_display_data';
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether an output is from a stream.
|
||||
*/
|
||||
export function isStream(output: IOutput): output is IStream {
|
||||
return output.output_type === 'stream';
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether an output is from a stream.
|
||||
*/
|
||||
export function isError(output: IOutput): output is IError {
|
||||
return output.output_type === 'error';
|
||||
}
|
||||
|
||||
/**
|
||||
* An output union type.
|
||||
*/
|
||||
export type IOutput =
|
||||
| IUnrecognizedOutput
|
||||
| IExecuteResult
|
||||
| IDisplayData
|
||||
| IStream
|
||||
| IError;
|
||||
}
|
||||
|
||||
export interface ICellOutputWithIdAndTrust extends nb.ICellOutput {
|
||||
id: number;
|
||||
trusted: boolean;
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
|
||||
|
||||
export namespace constants {
|
||||
export const userPropName = 'user';
|
||||
export const knoxPortPropName = 'knoxport';
|
||||
export const clusterPropName = 'clustername';
|
||||
export const passwordPropName = 'password';
|
||||
export const defaultKnoxPort = '30443';
|
||||
}
|
||||
/**
|
||||
* This is a temporary connection definition, with known properties for Knox gateway connections.
|
||||
* Long term this should be refactored to an extension contribution
|
||||
*
|
||||
* @export
|
||||
*/
|
||||
export class NotebookConnection {
|
||||
private _host: string;
|
||||
private _knoxPort: string;
|
||||
|
||||
constructor(private _connectionProfile: IConnectionProfile) {
|
||||
if (!this._connectionProfile) {
|
||||
throw new Error(localize('connectionInfoMissing', "connectionInfo is required"));
|
||||
}
|
||||
}
|
||||
|
||||
public get connectionProfile(): IConnectionProfile {
|
||||
return this._connectionProfile;
|
||||
}
|
||||
|
||||
|
||||
public get host(): string {
|
||||
if (!this._host) {
|
||||
this.ensureHostAndPort();
|
||||
}
|
||||
return this._host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets host and port values, using any ',' or ':' delimited port in the hostname in
|
||||
* preference to the built in port.
|
||||
*/
|
||||
private ensureHostAndPort(): void {
|
||||
this._host = this.connectionProfile.serverName;
|
||||
this._knoxPort = NotebookConnection.getKnoxPortOrDefault(this.connectionProfile);
|
||||
// determine whether the host has either a ',' or ':' in it
|
||||
this.setHostAndPort(',');
|
||||
this.setHostAndPort(':');
|
||||
}
|
||||
|
||||
// set port and host correctly after we've identified that a delimiter exists in the host name
|
||||
private setHostAndPort(delimeter: string): void {
|
||||
let originalHost = this._host;
|
||||
let index = originalHost.indexOf(delimeter);
|
||||
if (index > -1) {
|
||||
this._host = originalHost.slice(0, index);
|
||||
this._knoxPort = originalHost.slice(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
public get user(): string {
|
||||
return this._connectionProfile.options[constants.userPropName];
|
||||
}
|
||||
|
||||
public get password(): string {
|
||||
return this._connectionProfile.options[constants.passwordPropName];
|
||||
}
|
||||
|
||||
public get knoxport(): string {
|
||||
if (!this._knoxPort) {
|
||||
this.ensureHostAndPort();
|
||||
}
|
||||
return this._knoxPort;
|
||||
}
|
||||
|
||||
private static getKnoxPortOrDefault(connectionProfile: IConnectionProfile): string {
|
||||
let port = connectionProfile.options[constants.knoxPortPropName];
|
||||
if (!port) {
|
||||
port = constants.defaultKnoxPort;
|
||||
}
|
||||
return port;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export namespace nbversion {
|
||||
/**
|
||||
* The major version of the notebook format.
|
||||
*/
|
||||
export const MAJOR_VERSION: number = 4;
|
||||
|
||||
/**
|
||||
* The minor version of the notebook format.
|
||||
*/
|
||||
export const MINOR_VERSION: number = 2;
|
||||
}
|
||||
181
src/sql/workbench/contrib/notebook/common/models/url.ts
Normal file
181
src/sql/workbench/contrib/notebook/common/models/url.ts
Normal file
@@ -0,0 +1,181 @@
|
||||
// Copyright (c) Jupyter Development Team.
|
||||
// Distributed under the terms of the Modified BSD License.
|
||||
|
||||
import { JSONObject } from './jsonext';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
/**
|
||||
* The namespace for URL-related functions.
|
||||
*/
|
||||
export namespace URLExt {
|
||||
/**
|
||||
* Normalize a url.
|
||||
*/
|
||||
export function normalize(url: string): string {
|
||||
return URI.parse(url).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Join a sequence of url components and normalizes as in node `path.join`.
|
||||
*
|
||||
* @param parts - The url components.
|
||||
*
|
||||
* @returns the joined url.
|
||||
*/
|
||||
export function join(...parts: string[]): string {
|
||||
parts = parts || [];
|
||||
|
||||
// Isolate the top element.
|
||||
const top = parts[0] || '';
|
||||
|
||||
// Check whether protocol shorthand is being used.
|
||||
const shorthand = top.indexOf('//') === 0;
|
||||
|
||||
// Parse the top element into a header collection.
|
||||
const header = top.match(/(\w+)(:)(\/\/)?/);
|
||||
const protocol = header && header[1];
|
||||
const colon = protocol && header[2];
|
||||
const slashes = colon && header[3];
|
||||
|
||||
// Construct the URL prefix.
|
||||
const prefix = shorthand
|
||||
? '//'
|
||||
: [protocol, colon, slashes].filter(str => str).join('');
|
||||
|
||||
// Construct the URL body omitting the prefix of the top value.
|
||||
const body = [top.indexOf(prefix) === 0 ? top.replace(prefix, '') : top]
|
||||
// Filter out top value if empty.
|
||||
.filter(str => str)
|
||||
// Remove leading slashes in all subsequent URL body elements.
|
||||
.concat(parts.slice(1).map(str => str.replace(/^\//, '')))
|
||||
.join('/')
|
||||
// Replace multiple slashes with one.
|
||||
.replace(/\/+/g, '/');
|
||||
|
||||
return prefix + body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the components of a multi-segment url.
|
||||
*
|
||||
* @param url - The url to encode.
|
||||
*
|
||||
* @returns the encoded url.
|
||||
*
|
||||
* #### Notes
|
||||
* Preserves the `'/'` separators.
|
||||
* Should not include the base url, since all parts are escaped.
|
||||
*/
|
||||
export function encodeParts(url: string): string {
|
||||
return join(...url.split('/').map(encodeURIComponent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a serialized object string suitable for a query.
|
||||
*
|
||||
* @param object - The source object.
|
||||
*
|
||||
* @returns an encoded url query.
|
||||
*
|
||||
* #### Notes
|
||||
* Modified version of [stackoverflow](http://stackoverflow.com/a/30707423).
|
||||
*/
|
||||
export function objectToQueryString(value: JSONObject): string {
|
||||
const keys = Object.keys(value);
|
||||
|
||||
if (!keys.length) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (
|
||||
'?' +
|
||||
keys
|
||||
.map(key => {
|
||||
const content = encodeURIComponent(String(value[key]));
|
||||
return key + (content ? '=' + content : '');
|
||||
})
|
||||
.join('&')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a parsed object that represents the values in a query string.
|
||||
*/
|
||||
export function queryStringToObject(
|
||||
value: string
|
||||
): { [key: string]: string } {
|
||||
return value
|
||||
.replace(/^\?/, '')
|
||||
.split('&')
|
||||
.reduce(
|
||||
(acc, val) => {
|
||||
const [key, value] = val.split('=');
|
||||
acc[key] = decodeURIComponent(value || '');
|
||||
return acc;
|
||||
},
|
||||
{} as { [key: string]: string }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the url is a local url.
|
||||
*
|
||||
* #### Notes
|
||||
* This function returns `false` for any fully qualified url, including
|
||||
* `data:`, `file:`, and `//` protocol URLs.
|
||||
*/
|
||||
export function isLocal(url: string): boolean {
|
||||
// If if doesn't have a scheme such as file: or http:// it's local
|
||||
return !!URI.parse(url).scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
* The interface for a URL object
|
||||
*/
|
||||
export interface IUrl {
|
||||
/**
|
||||
* The full URL string that was parsed with both the protocol and host
|
||||
* components converted to lower-case.
|
||||
*/
|
||||
href?: string;
|
||||
|
||||
/**
|
||||
* Identifies the URL's lower-cased protocol scheme.
|
||||
*/
|
||||
protocol?: string;
|
||||
|
||||
/**
|
||||
* The full lower-cased host portion of the URL, including the port if
|
||||
* specified.
|
||||
*/
|
||||
host?: string;
|
||||
|
||||
/**
|
||||
* The lower-cased host name portion of the host component without the
|
||||
* port included.
|
||||
*/
|
||||
hostname?: string;
|
||||
|
||||
/**
|
||||
* The numeric port portion of the host component.
|
||||
*/
|
||||
port?: string;
|
||||
|
||||
/**
|
||||
* The entire path section of the URL.
|
||||
*/
|
||||
pathname?: string;
|
||||
|
||||
/**
|
||||
* The "fragment" portion of the URL including the leading ASCII hash
|
||||
* `(#)` character
|
||||
*/
|
||||
hash?: string;
|
||||
|
||||
/**
|
||||
* The search element, including leading question mark (`'?'`), if any,
|
||||
* of the URL.
|
||||
*/
|
||||
search?: string;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user