From 8adbe76e6636f22cba5f3d7192aa365fd16c4462 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 10 Aug 2020 17:27:10 +0800 Subject: [PATCH 01/78] Use proposed api --- package.json | 1 + vscode.proposed.d.ts | 2104 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2105 insertions(+) create mode 100644 vscode.proposed.d.ts diff --git a/package.json b/package.json index 010e3d9da..07789a1d8 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "onCommand:r.helpPanel.back", "onCommand:r.helpPanel.forward" ], + "enableProposedApi": true, "main": "./dist/extension", "contributes": { "viewsContainers": { diff --git a/vscode.proposed.d.ts b/vscode.proposed.d.ts new file mode 100644 index 000000000..e97105984 --- /dev/null +++ b/vscode.proposed.d.ts @@ -0,0 +1,2104 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * This is the place for API experiments and proposals. + * These API are NOT stable and subject to change. They are only available in the Insiders + * distribution and CANNOT be used in published extensions. + * + * To test these API in local environment: + * - Use Insiders release of VS Code. + * - Add `"enableProposedApi": true` to your package.json. + * - Copy this file to your project. + */ + +declare module 'vscode' { + + // #region auth provider: https://github.com/microsoft/vscode/issues/88309 + + /** + * An [event](#Event) which fires when an [AuthenticationProvider](#AuthenticationProvider) is added or removed. + */ + export interface AuthenticationProvidersChangeEvent { + /** + * The ids of the [authenticationProvider](#AuthenticationProvider)s that have been added. + */ + readonly added: ReadonlyArray; + + /** + * The ids of the [authenticationProvider](#AuthenticationProvider)s that have been removed. + */ + readonly removed: ReadonlyArray; + } + + /** + * An [event](#Event) which fires when an [AuthenticationSession](#AuthenticationSession) is added, removed, or changed. + */ + export interface AuthenticationProviderAuthenticationSessionsChangeEvent { + /** + * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been added. + */ + readonly added: ReadonlyArray; + + /** + * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been removed. + */ + readonly removed: ReadonlyArray; + + /** + * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been changed. + */ + readonly changed: ReadonlyArray; + } + + /** + * **WARNING** When writing an AuthenticationProvider, `id` should be treated as part of your extension's + * API, changing it is a breaking change for all extensions relying on the provider. The id is + * treated case-sensitively. + */ + export interface AuthenticationProvider { + /** + * Used as an identifier for extensions trying to work with a particular + * provider: 'microsoft', 'github', etc. id must be unique, registering + * another provider with the same id will fail. + */ + readonly id: string; + + /** + * The human-readable name of the provider. + */ + readonly label: string; + + /** + * Whether it is possible to be signed into multiple accounts at once with this provider + */ + readonly supportsMultipleAccounts: boolean; + + /** + * An [event](#Event) which fires when the array of sessions has changed, or data + * within a session has changed. + */ + readonly onDidChangeSessions: Event; + + /** + * Returns an array of current sessions. + */ + getSessions(): Thenable>; + + /** + * Prompts a user to login. + */ + login(scopes: string[]): Thenable; + + /** + * Removes the session corresponding to session id. + * @param sessionId The session id to log out of + */ + logout(sessionId: string): Thenable; + } + + export namespace authentication { + /** + * Register an authentication provider. + * + * There can only be one provider per id and an error is being thrown when an id + * has already been used by another provider. + * + * @param provider The authentication provider provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerAuthenticationProvider(provider: AuthenticationProvider): Disposable; + + /** + * Fires with the provider id that was registered or unregistered. + */ + export const onDidChangeAuthenticationProviders: Event; + + /** + * @deprecated + * The ids of the currently registered authentication providers. + * @returns An array of the ids of authentication providers that are currently registered. + */ + export function getProviderIds(): Thenable>; + + /** + * @deprecated + * An array of the ids of authentication providers that are currently registered. + */ + export const providerIds: ReadonlyArray; + + /** + * An array of the information of authentication providers that are currently registered. + */ + export const providers: ReadonlyArray; + + /** + * @deprecated + * Logout of a specific session. + * @param providerId The id of the provider to use + * @param sessionId The session id to remove + * provider + */ + export function logout(providerId: string, sessionId: string): Thenable; + } + + //#endregion + + //#region @alexdima - resolvers + + export interface RemoteAuthorityResolverContext { + resolveAttempt: number; + } + + export class ResolvedAuthority { + readonly host: string; + readonly port: number; + + constructor(host: string, port: number); + } + + export interface ResolvedOptions { + extensionHostEnv?: { [key: string]: string | null; }; + } + + export interface TunnelOptions { + remoteAddress: { port: number, host: string; }; + // The desired local port. If this port can't be used, then another will be chosen. + localAddressPort?: number; + label?: string; + } + + export interface TunnelDescription { + remoteAddress: { port: number, host: string; }; + //The complete local address(ex. localhost:1234) + localAddress: { port: number, host: string; } | string; + } + + export interface Tunnel extends TunnelDescription { + // Implementers of Tunnel should fire onDidDispose when dispose is called. + onDidDispose: Event; + dispose(): void; + } + + /** + * Used as part of the ResolverResult if the extension has any candidate, + * published, or forwarded ports. + */ + export interface TunnelInformation { + /** + * Tunnels that are detected by the extension. The remotePort is used for display purposes. + * The localAddress should be the complete local address (ex. localhost:1234) for connecting to the port. Tunnels provided through + * detected are read-only from the forwarded ports UI. + */ + environmentTunnels?: TunnelDescription[]; + + } + + export type ResolverResult = ResolvedAuthority & ResolvedOptions & TunnelInformation; + + export class RemoteAuthorityResolverError extends Error { + static NotAvailable(message?: string, handled?: boolean): RemoteAuthorityResolverError; + static TemporarilyNotAvailable(message?: string): RemoteAuthorityResolverError; + + constructor(message?: string); + } + + export interface RemoteAuthorityResolver { + resolve(authority: string, context: RemoteAuthorityResolverContext): ResolverResult | Thenable; + /** + * Can be optionally implemented if the extension can forward ports better than the core. + * When not implemented, the core will use its default forwarding logic. + * When implemented, the core will use this to forward ports. + */ + tunnelFactory?: (tunnelOptions: TunnelOptions) => Thenable | undefined; + + /** + * Provides filtering for candidate ports. + */ + showCandidatePort?: (host: string, port: number, detail: string) => Thenable; + } + + export namespace workspace { + /** + * Forwards a port. If the current resolver implements RemoteAuthorityResolver:forwardPort then that will be used to make the tunnel. + * By default, openTunnel only support localhost; however, RemoteAuthorityResolver:tunnelFactory can be used to support other ips. + * + * @throws When run in an environment without a remote. + * + * @param tunnelOptions The `localPort` is a suggestion only. If that port is not available another will be chosen. + */ + export function openTunnel(tunnelOptions: TunnelOptions): Thenable; + + /** + * Gets an array of the currently available tunnels. This does not include environment tunnels, only tunnels that have been created by the user. + * Note that these are of type TunnelDescription and cannot be disposed. + */ + export let tunnels: Thenable; + + /** + * Fired when the list of tunnels has changed. + */ + export const onDidChangeTunnels: Event; + } + + export interface ResourceLabelFormatter { + scheme: string; + authority?: string; + formatting: ResourceLabelFormatting; + } + + export interface ResourceLabelFormatting { + label: string; // myLabel:/${path} + // For historic reasons we use an or string here. Once we finalize this API we should start using enums instead and adopt it in extensions. + // eslint-disable-next-line vscode-dts-literal-or-types + separator: '/' | '\\' | ''; + tildify?: boolean; + normalizeDriveLetter?: boolean; + workspaceSuffix?: string; + authorityPrefix?: string; + stripPathStartingSeparator?: boolean; + } + + export namespace workspace { + export function registerRemoteAuthorityResolver(authorityPrefix: string, resolver: RemoteAuthorityResolver): Disposable; + export function registerResourceLabelFormatter(formatter: ResourceLabelFormatter): Disposable; + } + + //#endregion + + //#region editor insets: https://github.com/microsoft/vscode/issues/85682 + + export interface WebviewEditorInset { + readonly editor: TextEditor; + readonly line: number; + readonly height: number; + readonly webview: Webview; + readonly onDidDispose: Event; + dispose(): void; + } + + export namespace window { + export function createWebviewTextEditorInset(editor: TextEditor, line: number, height: number, options?: WebviewOptions): WebviewEditorInset; + } + + //#endregion + + //#region read/write in chunks: https://github.com/microsoft/vscode/issues/84515 + + export interface FileSystemProvider { + open?(resource: Uri, options: { create: boolean; }): number | Thenable; + close?(fd: number): void | Thenable; + read?(fd: number, pos: number, data: Uint8Array, offset: number, length: number): number | Thenable; + write?(fd: number, pos: number, data: Uint8Array, offset: number, length: number): number | Thenable; + } + + //#endregion + + //#region TextSearchProvider: https://github.com/microsoft/vscode/issues/59921 + + /** + * The parameters of a query for text search. + */ + export interface TextSearchQuery { + /** + * The text pattern to search for. + */ + pattern: string; + + /** + * Whether or not `pattern` should match multiple lines of text. + */ + isMultiline?: boolean; + + /** + * Whether or not `pattern` should be interpreted as a regular expression. + */ + isRegExp?: boolean; + + /** + * Whether or not the search should be case-sensitive. + */ + isCaseSensitive?: boolean; + + /** + * Whether or not to search for whole word matches only. + */ + isWordMatch?: boolean; + } + + /** + * A file glob pattern to match file paths against. + * TODO@roblourens merge this with the GlobPattern docs/definition in vscode.d.ts. + * @see [GlobPattern](#GlobPattern) + */ + export type GlobString = string; + + /** + * Options common to file and text search + */ + export interface SearchOptions { + /** + * The root folder to search within. + */ + folder: Uri; + + /** + * Files that match an `includes` glob pattern should be included in the search. + */ + includes: GlobString[]; + + /** + * Files that match an `excludes` glob pattern should be excluded from the search. + */ + excludes: GlobString[]; + + /** + * Whether external files that exclude files, like .gitignore, should be respected. + * See the vscode setting `"search.useIgnoreFiles"`. + */ + useIgnoreFiles: boolean; + + /** + * Whether symlinks should be followed while searching. + * See the vscode setting `"search.followSymlinks"`. + */ + followSymlinks: boolean; + + /** + * Whether global files that exclude files, like .gitignore, should be respected. + * See the vscode setting `"search.useGlobalIgnoreFiles"`. + */ + useGlobalIgnoreFiles: boolean; + } + + /** + * Options to specify the size of the result text preview. + * These options don't affect the size of the match itself, just the amount of preview text. + */ + export interface TextSearchPreviewOptions { + /** + * The maximum number of lines in the preview. + * Only search providers that support multiline search will ever return more than one line in the match. + */ + matchLines: number; + + /** + * The maximum number of characters included per line. + */ + charsPerLine: number; + } + + /** + * Options that apply to text search. + */ + export interface TextSearchOptions extends SearchOptions { + /** + * The maximum number of results to be returned. + */ + maxResults: number; + + /** + * Options to specify the size of the result text preview. + */ + previewOptions?: TextSearchPreviewOptions; + + /** + * Exclude files larger than `maxFileSize` in bytes. + */ + maxFileSize?: number; + + /** + * Interpret files using this encoding. + * See the vscode setting `"files.encoding"` + */ + encoding?: string; + + /** + * Number of lines of context to include before each match. + */ + beforeContext?: number; + + /** + * Number of lines of context to include after each match. + */ + afterContext?: number; + } + + /** + * Information collected when text search is complete. + */ + export interface TextSearchComplete { + /** + * Whether the search hit the limit on the maximum number of search results. + * `maxResults` on [`TextSearchOptions`](#TextSearchOptions) specifies the max number of results. + * - If exactly that number of matches exist, this should be false. + * - If `maxResults` matches are returned and more exist, this should be true. + * - If search hits an internal limit which is less than `maxResults`, this should be true. + */ + limitHit?: boolean; + } + + /** + * A preview of the text result. + */ + export interface TextSearchMatchPreview { + /** + * The matching lines of text, or a portion of the matching line that contains the match. + */ + text: string; + + /** + * The Range within `text` corresponding to the text of the match. + * The number of matches must match the TextSearchMatch's range property. + */ + matches: Range | Range[]; + } + + /** + * A match from a text search + */ + export interface TextSearchMatch { + /** + * The uri for the matching document. + */ + uri: Uri; + + /** + * The range of the match within the document, or multiple ranges for multiple matches. + */ + ranges: Range | Range[]; + + /** + * A preview of the text match. + */ + preview: TextSearchMatchPreview; + } + + /** + * A line of context surrounding a TextSearchMatch. + */ + export interface TextSearchContext { + /** + * The uri for the matching document. + */ + uri: Uri; + + /** + * One line of text. + * previewOptions.charsPerLine applies to this + */ + text: string; + + /** + * The line number of this line of context. + */ + lineNumber: number; + } + + export type TextSearchResult = TextSearchMatch | TextSearchContext; + + /** + * A TextSearchProvider provides search results for text results inside files in the workspace. + */ + export interface TextSearchProvider { + /** + * Provide results that match the given text pattern. + * @param query The parameters for this query. + * @param options A set of options to consider while searching. + * @param progress A progress callback that must be invoked for all results. + * @param token A cancellation token. + */ + provideTextSearchResults(query: TextSearchQuery, options: TextSearchOptions, progress: Progress, token: CancellationToken): ProviderResult; + } + + //#endregion + + //#region FileSearchProvider: https://github.com/microsoft/vscode/issues/73524 + + /** + * The parameters of a query for file search. + */ + export interface FileSearchQuery { + /** + * The search pattern to match against file paths. + */ + pattern: string; + } + + /** + * Options that apply to file search. + */ + export interface FileSearchOptions extends SearchOptions { + /** + * The maximum number of results to be returned. + */ + maxResults?: number; + + /** + * A CancellationToken that represents the session for this search query. If the provider chooses to, this object can be used as the key for a cache, + * and searches with the same session object can search the same cache. When the token is cancelled, the session is complete and the cache can be cleared. + */ + session?: CancellationToken; + } + + /** + * A FileSearchProvider provides search results for files in the given folder that match a query string. It can be invoked by quickopen or other extensions. + * + * A FileSearchProvider is the more powerful of two ways to implement file search in VS Code. Use a FileSearchProvider if you wish to search within a folder for + * all files that match the user's query. + * + * The FileSearchProvider will be invoked on every keypress in quickopen. When `workspace.findFiles` is called, it will be invoked with an empty query string, + * and in that case, every file in the folder should be returned. + */ + export interface FileSearchProvider { + /** + * Provide the set of files that match a certain file path pattern. + * @param query The parameters for this query. + * @param options A set of options to consider while searching files. + * @param token A cancellation token. + */ + provideFileSearchResults(query: FileSearchQuery, options: FileSearchOptions, token: CancellationToken): ProviderResult; + } + + export namespace workspace { + /** + * Register a search provider. + * + * Only one provider can be registered per scheme. + * + * @param scheme The provider will be invoked for workspace folders that have this file scheme. + * @param provider The provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerFileSearchProvider(scheme: string, provider: FileSearchProvider): Disposable; + + /** + * Register a text search provider. + * + * Only one provider can be registered per scheme. + * + * @param scheme The provider will be invoked for workspace folders that have this file scheme. + * @param provider The provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerTextSearchProvider(scheme: string, provider: TextSearchProvider): Disposable; + } + + //#endregion + + //#region findTextInFiles: https://github.com/microsoft/vscode/issues/59924 + + /** + * Options that can be set on a findTextInFiles search. + */ + export interface FindTextInFilesOptions { + /** + * A [glob pattern](#GlobPattern) that defines the files to search for. The glob pattern + * will be matched against the file paths of files relative to their workspace. Use a [relative pattern](#RelativePattern) + * to restrict the search results to a [workspace folder](#WorkspaceFolder). + */ + include?: GlobPattern; + + /** + * A [glob pattern](#GlobPattern) that defines files and folders to exclude. The glob pattern + * will be matched against the file paths of resulting matches relative to their workspace. When `undefined`, default excludes will + * apply. + */ + exclude?: GlobPattern; + + /** + * Whether to use the default and user-configured excludes. Defaults to true. + */ + useDefaultExcludes?: boolean; + + /** + * The maximum number of results to search for + */ + maxResults?: number; + + /** + * Whether external files that exclude files, like .gitignore, should be respected. + * See the vscode setting `"search.useIgnoreFiles"`. + */ + useIgnoreFiles?: boolean; + + /** + * Whether global files that exclude files, like .gitignore, should be respected. + * See the vscode setting `"search.useGlobalIgnoreFiles"`. + */ + useGlobalIgnoreFiles?: boolean; + + /** + * Whether symlinks should be followed while searching. + * See the vscode setting `"search.followSymlinks"`. + */ + followSymlinks?: boolean; + + /** + * Interpret files using this encoding. + * See the vscode setting `"files.encoding"` + */ + encoding?: string; + + /** + * Options to specify the size of the result text preview. + */ + previewOptions?: TextSearchPreviewOptions; + + /** + * Number of lines of context to include before each match. + */ + beforeContext?: number; + + /** + * Number of lines of context to include after each match. + */ + afterContext?: number; + } + + export namespace workspace { + /** + * Search text in files across all [workspace folders](#workspace.workspaceFolders) in the workspace. + * @param query The query parameters for the search - the search string, whether it's case-sensitive, or a regex, or matches whole words. + * @param callback A callback, called for each result + * @param token A token that can be used to signal cancellation to the underlying search engine. + * @return A thenable that resolves when the search is complete. + */ + export function findTextInFiles(query: TextSearchQuery, callback: (result: TextSearchResult) => void, token?: CancellationToken): Thenable; + + /** + * Search text in files across all [workspace folders](#workspace.workspaceFolders) in the workspace. + * @param query The query parameters for the search - the search string, whether it's case-sensitive, or a regex, or matches whole words. + * @param options An optional set of query options. Include and exclude patterns, maxResults, etc. + * @param callback A callback, called for each result + * @param token A token that can be used to signal cancellation to the underlying search engine. + * @return A thenable that resolves when the search is complete. + */ + export function findTextInFiles(query: TextSearchQuery, options: FindTextInFilesOptions, callback: (result: TextSearchResult) => void, token?: CancellationToken): Thenable; + } + + //#endregion + + //#region diff command: https://github.com/microsoft/vscode/issues/84899 + + /** + * The contiguous set of modified lines in a diff. + */ + export interface LineChange { + readonly originalStartLineNumber: number; + readonly originalEndLineNumber: number; + readonly modifiedStartLineNumber: number; + readonly modifiedEndLineNumber: number; + } + + export namespace commands { + + /** + * Registers a diff information command that can be invoked via a keyboard shortcut, + * a menu item, an action, or directly. + * + * Diff information commands are different from ordinary [commands](#commands.registerCommand) as + * they only execute when there is an active diff editor when the command is called, and the diff + * information has been computed. Also, the command handler of an editor command has access to + * the diff information. + * + * @param command A unique identifier for the command. + * @param callback A command handler function with access to the [diff information](#LineChange). + * @param thisArg The `this` context used when invoking the handler function. + * @return Disposable which unregisters this command on disposal. + */ + export function registerDiffInformationCommand(command: string, callback: (diff: LineChange[], ...args: any[]) => any, thisArg?: any): Disposable; + } + + //#endregion + + //#region file-decorations: https://github.com/microsoft/vscode/issues/54938 + + export class Decoration { + letter?: string; + title?: string; + color?: ThemeColor; + priority?: number; + bubble?: boolean; + } + + export interface DecorationProvider { + onDidChangeDecorations: Event; + provideDecoration(uri: Uri, token: CancellationToken): ProviderResult; + } + + export namespace window { + export function registerDecorationProvider(provider: DecorationProvider): Disposable; + } + + //#endregion + + //#region debug + + export interface DebugSessionOptions { + /** + * Controls whether this session should run without debugging, thus ignoring breakpoints. + * When this property is not specified, the value from the parent session (if there is one) is used. + */ + noDebug?: boolean; + + /** + * Controls if the debug session's parent session is shown in the CALL STACK view even if it has only a single child. + * By default, the debug session will never hide its parent. + * If compact is true, debug sessions with a single child are hidden in the CALL STACK view to make the tree more compact. + */ + compact?: boolean; + } + + // deprecated debug API + + export interface DebugConfigurationProvider { + /** + * Deprecated, use DebugAdapterDescriptorFactory.provideDebugAdapter instead. + * @deprecated Use DebugAdapterDescriptorFactory.createDebugAdapterDescriptor instead + */ + debugAdapterExecutable?(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult; + } + + export namespace debug { + + /** + * Stop the given debug session or stop all debug sessions if session is omitted. + * @param session The [debug session](#DebugSession) to stop; if omitted all sessions are stopped. + */ + export function stopDebugging(session?: DebugSession): Thenable; + } + + //#endregion + + //#region LogLevel: https://github.com/microsoft/vscode/issues/85992 + + /** + * @deprecated DO NOT USE, will be removed + */ + export enum LogLevel { + Trace = 1, + Debug = 2, + Info = 3, + Warning = 4, + Error = 5, + Critical = 6, + Off = 7 + } + + export namespace env { + /** + * @deprecated DO NOT USE, will be removed + */ + export const logLevel: LogLevel; + + /** + * @deprecated DO NOT USE, will be removed + */ + export const onDidChangeLogLevel: Event; + } + + //#endregion + + //#region @joaomoreno: SCM validation + + /** + * Represents the validation type of the Source Control input. + */ + export enum SourceControlInputBoxValidationType { + + /** + * Something not allowed by the rules of a language or other means. + */ + Error = 0, + + /** + * Something suspicious but allowed. + */ + Warning = 1, + + /** + * Something to inform about but not a problem. + */ + Information = 2 + } + + export interface SourceControlInputBoxValidation { + + /** + * The validation message to display. + */ + readonly message: string; + + /** + * The validation type. + */ + readonly type: SourceControlInputBoxValidationType; + } + + /** + * Represents the input box in the Source Control viewlet. + */ + export interface SourceControlInputBox { + + /** + * A validation function for the input box. It's possible to change + * the validation provider simply by setting this property to a different function. + */ + validateInput?(value: string, cursorPosition: number): ProviderResult; + } + + //#endregion + + //#region @joaomoreno: SCM selected provider + + export interface SourceControl { + + /** + * Whether the source control is selected. + */ + readonly selected: boolean; + + /** + * An event signaling when the selection state changes. + */ + readonly onDidChangeSelection: Event; + } + + //#endregion + + //#region Terminal data write event https://github.com/microsoft/vscode/issues/78502 + + export interface TerminalDataWriteEvent { + /** + * The [terminal](#Terminal) for which the data was written. + */ + readonly terminal: Terminal; + /** + * The data being written. + */ + readonly data: string; + } + + namespace window { + /** + * An event which fires when the terminal's child pseudo-device is written to (the shell). + * In other words, this provides access to the raw data stream from the process running + * within the terminal, including VT sequences. + */ + export const onDidWriteTerminalData: Event; + } + + //#endregion + + //#region Terminal dimensions property and change event https://github.com/microsoft/vscode/issues/55718 + + /** + * An [event](#Event) which fires when a [Terminal](#Terminal)'s dimensions change. + */ + export interface TerminalDimensionsChangeEvent { + /** + * The [terminal](#Terminal) for which the dimensions have changed. + */ + readonly terminal: Terminal; + /** + * The new value for the [terminal's dimensions](#Terminal.dimensions). + */ + readonly dimensions: TerminalDimensions; + } + + export namespace window { + /** + * An event which fires when the [dimensions](#Terminal.dimensions) of the terminal change. + */ + export const onDidChangeTerminalDimensions: Event; + } + + export interface Terminal { + /** + * The current dimensions of the terminal. This will be `undefined` immediately after the + * terminal is created as the dimensions are not known until shortly after the terminal is + * created. + */ + readonly dimensions: TerminalDimensions | undefined; + } + + //#endregion + + //#region Terminal link handlers https://github.com/microsoft/vscode/issues/91606 + + export namespace window { + /** + * Register a [TerminalLinkHandler](#TerminalLinkHandler) that can be used to intercept and + * handle links that are activated within terminals. + * @param handler The link handler being registered. + * @return A disposable that unregisters the link handler. + */ + export function registerTerminalLinkHandler(handler: TerminalLinkHandler): Disposable; + } + + /** + * Describes how to handle terminal links. + */ + export interface TerminalLinkHandler { + /** + * Handles a link that is activated within the terminal. + * + * @param terminal The terminal the link was activated on. + * @param link The text of the link activated. + * @return Whether the link was handled, if the link was handled this link will not be + * considered by any other extension or by the default built-in link handler. + */ + handleLink(terminal: Terminal, link: string): ProviderResult; + } + + //#endregion + + //#region Terminal link provider https://github.com/microsoft/vscode/issues/91606 + + export namespace window { + export function registerTerminalLinkProvider(provider: TerminalLinkProvider): Disposable; + } + + export interface TerminalLinkContext { + /** + * This is the text from the unwrapped line in the terminal. + */ + line: string; + + /** + * The terminal the link belongs to. + */ + terminal: Terminal; + } + + export interface TerminalLinkProvider { + /** + * Provide terminal links for the given context. Note that this can be called multiple times + * even before previous calls resolve, make sure to not share global objects (eg. `RegExp`) + * that could have problems when asynchronous usage may overlap. + * @param context Information about what links are being provided for. + * @param token A cancellation token. + * @return A list of terminal links for the given line. + */ + provideTerminalLinks(context: TerminalLinkContext, token: CancellationToken): ProviderResult + + /** + * Handle an activated terminal link. + */ + handleTerminalLink(link: T): ProviderResult; + } + + export interface TerminalLink { + /** + * The start index of the link on [TerminalLinkContext.line](#TerminalLinkContext.line]. + */ + startIndex: number; + + /** + * The length of the link on [TerminalLinkContext.line](#TerminalLinkContext.line] + */ + length: number; + + /** + * The tooltip text when you hover over this link. + * + * If a tooltip is provided, is will be displayed in a string that includes instructions on + * how to trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary + * depending on OS, user settings, and localization. + */ + tooltip?: string; + } + + //#endregion + + //#region @jrieken -> exclusive document filters + + export interface DocumentFilter { + exclusive?: boolean; + } + + //#endregion + + //#region @alexdima - OnEnter enhancement + export interface OnEnterRule { + /** + * This rule will only execute if the text above the this line matches this regular expression. + */ + oneLineAboveText?: RegExp; + } + //#endregion + + //#region Tree View: https://github.com/microsoft/vscode/issues/61313 + /** + * Label describing the [Tree item](#TreeItem) + */ + export interface TreeItemLabel { + + /** + * A human-readable string describing the [Tree item](#TreeItem). + */ + label: string; + + /** + * Ranges in the label to highlight. A range is defined as a tuple of two number where the + * first is the inclusive start index and the second the exclusive end index + */ + highlights?: [number, number][]; + + } + + // https://github.com/microsoft/vscode/issues/100741 + export interface TreeDataProvider { + resolveTreeItem?(element: T, item: TreeItem2): TreeItem2 | Thenable; + } + + export class TreeItem2 extends TreeItem { + /** + * Label describing this item. When `falsy`, it is derived from [resourceUri](#TreeItem.resourceUri). + */ + label?: string | TreeItemLabel | /* for compilation */ any; + + /** + * Content to be shown when you hover over the tree item. + */ + tooltip?: string | MarkdownString | /* for compilation */ any; + + /** + * @param label Label describing this item + * @param collapsibleState [TreeItemCollapsibleState](#TreeItemCollapsibleState) of the tree item. Default is [TreeItemCollapsibleState.None](#TreeItemCollapsibleState.None) + */ + constructor(label: TreeItemLabel, collapsibleState?: TreeItemCollapsibleState); + } + //#endregion + + //#region CustomExecution: https://github.com/microsoft/vscode/issues/81007 + /** + * A task to execute + */ + export class Task2 extends Task { + detail?: string; + } + + export class CustomExecution2 extends CustomExecution { + /** + * Constructs a CustomExecution task object. The callback will be executed the task is run, at which point the + * extension should return the Pseudoterminal it will "run in". The task should wait to do further execution until + * [Pseudoterminal.open](#Pseudoterminal.open) is called. Task cancellation should be handled using + * [Pseudoterminal.close](#Pseudoterminal.close). When the task is complete fire + * [Pseudoterminal.onDidClose](#Pseudoterminal.onDidClose). + * @param callback The callback that will be called when the task is started by a user. + */ + constructor(callback: (resolvedDefinition?: TaskDefinition) => Thenable); + } + //#endregion + + //#region Task presentation group: https://github.com/microsoft/vscode/issues/47265 + export interface TaskPresentationOptions { + /** + * Controls whether the task is executed in a specific terminal group using split panes. + */ + group?: string; + } + //#endregion + + //#region Status bar item with ID and Name: https://github.com/microsoft/vscode/issues/74972 + + export namespace window { + + /** + * Options to configure the status bar item. + */ + export interface StatusBarItemOptions { + + /** + * A unique identifier of the status bar item. The identifier + * is for example used to allow a user to show or hide the + * status bar item in the UI. + */ + id: string; + + /** + * A human readable name of the status bar item. The name is + * for example used as a label in the UI to show or hide the + * status bar item. + */ + name: string; + + /** + * Accessibility information used when screen reader interacts with this status bar item. + */ + accessibilityInformation?: AccessibilityInformation; + + /** + * The alignment of the status bar item. + */ + alignment?: StatusBarAlignment; + + /** + * The priority of the status bar item. Higher value means the item should + * be shown more to the left. + */ + priority?: number; + } + + /** + * Creates a status bar [item](#StatusBarItem). + * + * @param options The options of the item. If not provided, some default values + * will be assumed. For example, the `StatusBarItemOptions.id` will be the id + * of the extension and the `StatusBarItemOptions.name` will be the extension name. + * @return A new status bar item. + */ + export function createStatusBarItem(options?: StatusBarItemOptions): StatusBarItem; + } + + //#endregion + + //#region OnTypeRename: https://github.com/microsoft/vscode/issues/88424 + + /** + * The rename provider interface defines the contract between extensions and + * the live-rename feature. + */ + export interface OnTypeRenameProvider { + /** + * Provide a list of ranges that can be live renamed together. + * + * @param document The document in which the command was invoked. + * @param position The position at which the command was invoked. + * @param token A cancellation token. + * @return A list of ranges that can be live-renamed togehter. The ranges must have + * identical length and contain identical text content. The ranges cannot overlap. + */ + provideOnTypeRenameRanges(document: TextDocument, position: Position, token: CancellationToken): ProviderResult; + } + + namespace languages { + /** + * Register a rename provider that works on type. + * + * Multiple providers can be registered for a language. In that case providers are sorted + * by their [score](#languages.match) and the best-matching provider is used. Failure + * of the selected provider will cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider An on type rename provider. + * @param stopPattern Stop on type renaming when input text matches the regular expression. Defaults to `^\s`. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerOnTypeRenameProvider(selector: DocumentSelector, provider: OnTypeRenameProvider, stopPattern?: RegExp): Disposable; + } + + //#endregion + + //#region Custom editor move https://github.com/microsoft/vscode/issues/86146 + + // TODO: Also for custom editor + + export interface CustomTextEditorProvider { + + /** + * Handle when the underlying resource for a custom editor is renamed. + * + * This allows the webview for the editor be preserved throughout the rename. If this method is not implemented, + * VS Code will destory the previous custom editor and create a replacement one. + * + * @param newDocument New text document to use for the custom editor. + * @param existingWebviewPanel Webview panel for the custom editor. + * @param token A cancellation token that indicates the result is no longer needed. + * + * @return Thenable indicating that the webview editor has been moved. + */ + moveCustomTextEditor?(newDocument: TextDocument, existingWebviewPanel: WebviewPanel, token: CancellationToken): Thenable; + } + + //#endregion + + //#region allow QuickPicks to skip sorting: https://github.com/microsoft/vscode/issues/73904 + + export interface QuickPick extends QuickInput { + /** + * An optional flag to sort the final results by index of first query match in label. Defaults to true. + */ + sortByLabel: boolean; + } + + //#endregion + + //#region @rebornix: Notebook + + export enum CellKind { + Markdown = 1, + Code = 2 + } + + export enum CellOutputKind { + Text = 1, + Error = 2, + Rich = 3 + } + + export interface CellStreamOutput { + outputKind: CellOutputKind.Text; + text: string; + } + + export interface CellErrorOutput { + outputKind: CellOutputKind.Error; + /** + * Exception Name + */ + ename: string; + /** + * Exception Value + */ + evalue: string; + /** + * Exception call stack + */ + traceback: string[]; + } + + export interface NotebookCellOutputMetadata { + /** + * Additional attributes of a cell metadata. + */ + custom?: { [key: string]: any }; + } + + export interface CellDisplayOutput { + outputKind: CellOutputKind.Rich; + /** + * { mime_type: value } + * + * Example: + * ```json + * { + * "outputKind": vscode.CellOutputKind.Rich, + * "data": { + * "text/html": [ + * "

Hello

" + * ], + * "text/plain": [ + * "" + * ] + * } + * } + */ + data: { [key: string]: any; }; + + readonly metadata?: NotebookCellOutputMetadata; + } + + export type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput; + + export enum NotebookCellRunState { + Running = 1, + Idle = 2, + Success = 3, + Error = 4 + } + + export enum NotebookRunState { + Running = 1, + Idle = 2 + } + + export interface NotebookCellMetadata { + /** + * Controls if the content of a cell is editable or not. + */ + editable?: boolean; + + /** + * Controls if the cell is executable. + * This metadata is ignored for markdown cell. + */ + runnable?: boolean; + + /** + * Controls if the cell has a margin to support the breakpoint UI. + * This metadata is ignored for markdown cell. + */ + breakpointMargin?: boolean; + + /** + * Whether the [execution order](#NotebookCellMetadata.executionOrder) indicator will be displayed. + * Defaults to true. + */ + hasExecutionOrder?: boolean; + + /** + * The order in which this cell was executed. + */ + executionOrder?: number; + + /** + * A status message to be shown in the cell's status bar + */ + statusMessage?: string; + + /** + * The cell's current run state + */ + runState?: NotebookCellRunState; + + /** + * If the cell is running, the time at which the cell started running + */ + runStartTime?: number; + + /** + * The total duration of the cell's last run + */ + lastRunDuration?: number; + + /** + * Whether a code cell's editor is collapsed + */ + inputCollapsed?: boolean; + + /** + * Whether a code cell's outputs are collapsed + */ + outputCollapsed?: boolean; + + /** + * Additional attributes of a cell metadata. + */ + custom?: { [key: string]: any }; + } + + export interface NotebookCell { + readonly notebook: NotebookDocument; + readonly uri: Uri; + readonly cellKind: CellKind; + readonly document: TextDocument; + language: string; + outputs: CellOutput[]; + metadata: NotebookCellMetadata; + } + + export interface NotebookDocumentMetadata { + /** + * Controls if users can add or delete cells + * Defaults to true + */ + editable?: boolean; + + /** + * Controls whether the full notebook can be run at once. + * Defaults to true + */ + runnable?: boolean; + + /** + * Default value for [cell editable metadata](#NotebookCellMetadata.editable). + * Defaults to true. + */ + cellEditable?: boolean; + + /** + * Default value for [cell runnable metadata](#NotebookCellMetadata.runnable). + * Defaults to true. + */ + cellRunnable?: boolean; + + /** + * Default value for [cell hasExecutionOrder metadata](#NotebookCellMetadata.hasExecutionOrder). + * Defaults to true. + */ + cellHasExecutionOrder?: boolean; + + displayOrder?: GlobPattern[]; + + /** + * Additional attributes of the document metadata. + */ + custom?: { [key: string]: any }; + + /** + * The document's current run state + */ + runState?: NotebookRunState; + } + + export interface NotebookDocument { + readonly uri: Uri; + readonly fileName: string; + readonly viewType: string; + readonly isDirty: boolean; + readonly isUntitled: boolean; + readonly cells: NotebookCell[]; + languages: string[]; + displayOrder?: GlobPattern[]; + metadata: NotebookDocumentMetadata; + } + + export interface NotebookConcatTextDocument { + uri: Uri; + isClosed: boolean; + dispose(): void; + onDidChange: Event; + version: number; + getText(): string; + getText(range: Range): string; + + offsetAt(position: Position): number; + positionAt(offset: number): Position; + validateRange(range: Range): Range; + validatePosition(position: Position): Position; + + locationAt(positionOrRange: Position | Range): Location; + positionAt(location: Location): Position; + contains(uri: Uri): boolean + } + + export interface NotebookEditorCellEdit { + insert(index: number, content: string | string[], language: string, type: CellKind, outputs: CellOutput[], metadata: NotebookCellMetadata | undefined): void; + delete(index: number): void; + } + + export interface NotebookEditor { + /** + * The document associated with this notebook editor. + */ + readonly document: NotebookDocument; + + /** + * The primary selected cell on this notebook editor. + */ + readonly selection?: NotebookCell; + + /** + * The column in which this editor shows. + */ + viewColumn?: ViewColumn; + + /** + * Whether the panel is active (focused by the user). + */ + readonly active: boolean; + + /** + * Whether the panel is visible. + */ + readonly visible: boolean; + + /** + * Fired when the panel is disposed. + */ + readonly onDidDispose: Event; + + /** + * Active kernel used in the editor + */ + readonly kernel?: NotebookKernel; + + /** + * Fired when the output hosting webview posts a message. + */ + readonly onDidReceiveMessage: Event; + /** + * Post a message to the output hosting webview. + * + * Messages are only delivered if the editor is live. + * + * @param message Body of the message. This must be a string or other json serilizable object. + */ + postMessage(message: any): Thenable; + + /** + * Convert a uri for the local file system to one that can be used inside outputs webview. + */ + asWebviewUri(localResource: Uri): Uri; + + edit(callback: (editBuilder: NotebookEditorCellEdit) => void): Thenable; + } + + export interface NotebookOutputSelector { + mimeTypes?: string[]; + } + + export interface NotebookRenderRequest { + output: CellDisplayOutput; + mimeType: string; + outputId: string; + } + + export interface NotebookOutputRenderer { + /** + * + * @returns HTML fragment. We can probably return `CellOutput` instead of string ? + * + */ + render(document: NotebookDocument, request: NotebookRenderRequest): string; + + /** + * Call before HTML from the renderer is executed, and will be called for + * every editor associated with notebook documents where the renderer + * is or was used. + * + * The communication object will only send and receive messages to the + * render API, retrieved via `acquireNotebookRendererApi`, acquired with + * this specific renderer's ID. + * + * If you need to keep an association between the communication object + * and the document for use in the `render()` method, you can use a WeakMap. + */ + resolveNotebook?(document: NotebookDocument, communication: NotebookCommunication): void; + + readonly preloads?: Uri[]; + } + + export interface NotebookCellsChangeData { + readonly start: number; + readonly deletedCount: number; + readonly deletedItems: NotebookCell[]; + readonly items: NotebookCell[]; + } + + export interface NotebookCellsChangeEvent { + + /** + * The affected document. + */ + readonly document: NotebookDocument; + readonly changes: ReadonlyArray; + } + + export interface NotebookCellMoveEvent { + + /** + * The affected document. + */ + readonly document: NotebookDocument; + readonly index: number; + readonly newIndex: number; + } + + export interface NotebookCellOutputsChangeEvent { + + /** + * The affected document. + */ + readonly document: NotebookDocument; + readonly cells: NotebookCell[]; + } + + export interface NotebookCellLanguageChangeEvent { + + /** + * The affected document. + */ + readonly document: NotebookDocument; + readonly cell: NotebookCell; + readonly language: string; + } + + export interface NotebookCellMetadataChangeEvent { + readonly document: NotebookDocument; + readonly cell: NotebookCell; + } + + export interface NotebookCellData { + readonly cellKind: CellKind; + readonly source: string; + language: string; + outputs: CellOutput[]; + metadata: NotebookCellMetadata; + } + + export interface NotebookData { + readonly cells: NotebookCellData[]; + readonly languages: string[]; + readonly metadata: NotebookDocumentMetadata; + } + + interface NotebookDocumentContentChangeEvent { + + /** + * The document that the edit is for. + */ + readonly document: NotebookDocument; + } + + interface NotebookDocumentEditEvent { + + /** + * The document that the edit is for. + */ + readonly document: NotebookDocument; + + /** + * Undo the edit operation. + * + * This is invoked by VS Code when the user undoes this edit. To implement `undo`, your + * extension should restore the document and editor to the state they were in just before this + * edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`. + */ + undo(): Thenable | void; + + /** + * Redo the edit operation. + * + * This is invoked by VS Code when the user redoes this edit. To implement `redo`, your + * extension should restore the document and editor to the state they were in just after this + * edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`. + */ + redo(): Thenable | void; + + /** + * Display name describing the edit. + * + * This will be shown to users in the UI for undo/redo operations. + */ + readonly label?: string; + } + + interface NotebookDocumentBackup { + /** + * Unique identifier for the backup. + * + * This id is passed back to your extension in `openCustomDocument` when opening a notebook editor from a backup. + */ + readonly id: string; + + /** + * Delete the current backup. + * + * This is called by VS Code when it is clear the current backup is no longer needed, such as when a new backup + * is made or when the file is saved. + */ + delete(): void; + } + + interface NotebookDocumentBackupContext { + readonly destination: Uri; + } + + interface NotebookDocumentOpenContext { + readonly backupId?: string; + } + + /** + * Communication object passed to the {@link NotebookContentProvider} and + * {@link NotebookOutputRenderer} to communicate with the webview. + */ + export interface NotebookCommunication { + /** + * ID of the editor this object communicates with. A single notebook + * document can have multiple attached webviews and editors, when the + * notebook is split for instance. The editor ID lets you differentiate + * between them. + */ + readonly editorId: string; + + /** + * Fired when the output hosting webview posts a message. + */ + readonly onDidReceiveMessage: Event; + /** + * Post a message to the output hosting webview. + * + * Messages are only delivered if the editor is live. + * + * @param message Body of the message. This must be a string or other json serilizable object. + */ + postMessage(message: any): Thenable; + + /** + * Convert a uri for the local file system to one that can be used inside outputs webview. + */ + asWebviewUri(localResource: Uri): Uri; + } + + export interface NotebookContentProvider { + /** + * Content providers should always use [file system providers](#FileSystemProvider) to + * resolve the raw content for `uri` as the resouce is not necessarily a file on disk. + */ + openNotebook(uri: Uri, openContext: NotebookDocumentOpenContext): NotebookData | Promise; + resolveNotebook(document: NotebookDocument, webview: NotebookCommunication): Promise; + saveNotebook(document: NotebookDocument, cancellation: CancellationToken): Promise; + saveNotebookAs(targetResource: Uri, document: NotebookDocument, cancellation: CancellationToken): Promise; + readonly onDidChangeNotebook: Event; + backupNotebook(document: NotebookDocument, context: NotebookDocumentBackupContext, cancellation: CancellationToken): Promise; + + kernel?: NotebookKernel; + } + + export interface NotebookKernel { + readonly id?: string; + label: string; + description?: string; + isPreferred?: boolean; + preloads?: Uri[]; + executeCell(document: NotebookDocument, cell: NotebookCell): void; + cancelCellExecution(document: NotebookDocument, cell: NotebookCell): void; + executeAllCells(document: NotebookDocument): void; + cancelAllCellsExecution(document: NotebookDocument): void; + } + + export interface NotebookDocumentFilter { + viewType?: string; + filenamePattern?: GlobPattern; + excludeFileNamePattern?: GlobPattern; + } + + export interface NotebookKernelProvider { + onDidChangeKernels?: Event; + provideKernels(document: NotebookDocument, token: CancellationToken): ProviderResult; + resolveKernel?(kernel: T, document: NotebookDocument, webview: NotebookCommunication, token: CancellationToken): ProviderResult; + } + + export namespace notebook { + export function registerNotebookContentProvider( + notebookType: string, + provider: NotebookContentProvider + ): Disposable; + + export function registerNotebookKernelProvider( + selector: NotebookDocumentFilter, + provider: NotebookKernelProvider + ): Disposable; + + export function registerNotebookKernel( + id: string, + selectors: GlobPattern[], + kernel: NotebookKernel + ): Disposable; + + export function registerNotebookOutputRenderer( + id: string, + outputSelector: NotebookOutputSelector, + renderer: NotebookOutputRenderer + ): Disposable; + + export const onDidOpenNotebookDocument: Event; + export const onDidCloseNotebookDocument: Event; + export const onDidSaveNotebookDocument: Event; + + /** + * All currently known notebook documents. + */ + export const notebookDocuments: ReadonlyArray; + + export let visibleNotebookEditors: NotebookEditor[]; + export const onDidChangeVisibleNotebookEditors: Event; + + export let activeNotebookEditor: NotebookEditor | undefined; + export const onDidChangeActiveNotebookEditor: Event; + export const onDidChangeNotebookCells: Event; + export const onDidChangeCellOutputs: Event; + export const onDidChangeCellLanguage: Event; + export const onDidChangeCellMetadata: Event; + /** + * Create a document that is the concatenation of all notebook cells. By default all code-cells are included + * but a selector can be provided to narrow to down the set of cells. + * + * @param notebook + * @param selector + */ + export function createConcatTextDocument(notebook: NotebookDocument, selector?: DocumentSelector): NotebookConcatTextDocument; + + export const onDidChangeActiveNotebookKernel: Event<{ document: NotebookDocument, kernel: NotebookKernel | undefined }>; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/39441 + + export interface CompletionItem { + /** + * Will be merged into CompletionItem#label + */ + label2?: CompletionItemLabel; + } + + export interface CompletionItemLabel { + /** + * The function or variable. Rendered leftmost. + */ + name: string; + + /** + * The parameters without the return type. Render after `name`. + */ + parameters?: string; + + /** + * The fully qualified name, like package name or file path. Rendered after `signature`. + */ + qualifier?: string; + + /** + * The return-type of a function or type of a property/variable. Rendered rightmost. + */ + type?: string; + } + + //#endregion + + //#region @eamodio - timeline: https://github.com/microsoft/vscode/issues/84297 + + export class TimelineItem { + /** + * A timestamp (in milliseconds since 1 January 1970 00:00:00) for when the timeline item occurred. + */ + timestamp: number; + + /** + * A human-readable string describing the timeline item. + */ + label: string; + + /** + * Optional id for the timeline item. It must be unique across all the timeline items provided by this source. + * + * If not provided, an id is generated using the timeline item's timestamp. + */ + id?: string; + + /** + * The icon path or [ThemeIcon](#ThemeIcon) for the timeline item. + */ + iconPath?: Uri | { light: Uri; dark: Uri; } | ThemeIcon; + + /** + * A human readable string describing less prominent details of the timeline item. + */ + description?: string; + + /** + * The tooltip text when you hover over the timeline item. + */ + detail?: string; + + /** + * The [command](#Command) that should be executed when the timeline item is selected. + */ + command?: Command; + + /** + * Context value of the timeline item. This can be used to contribute specific actions to the item. + * For example, a timeline item is given a context value as `commit`. When contributing actions to `timeline/item/context` + * using `menus` extension point, you can specify context value for key `timelineItem` in `when` expression like `timelineItem == commit`. + * ``` + * "contributes": { + * "menus": { + * "timeline/item/context": [ + * { + * "command": "extension.copyCommitId", + * "when": "timelineItem == commit" + * } + * ] + * } + * } + * ``` + * This will show the `extension.copyCommitId` action only for items where `contextValue` is `commit`. + */ + contextValue?: string; + + /** + * Accessibility information used when screen reader interacts with this timeline item. + */ + accessibilityInformation?: AccessibilityInformation; + + /** + * @param label A human-readable string describing the timeline item + * @param timestamp A timestamp (in milliseconds since 1 January 1970 00:00:00) for when the timeline item occurred + */ + constructor(label: string, timestamp: number); + } + + export interface TimelineChangeEvent { + /** + * The [uri](#Uri) of the resource for which the timeline changed. + */ + uri: Uri; + + /** + * A flag which indicates whether the entire timeline should be reset. + */ + reset?: boolean; + } + + export interface Timeline { + readonly paging?: { + /** + * A provider-defined cursor specifying the starting point of timeline items which are after the ones returned. + * Use `undefined` to signal that there are no more items to be returned. + */ + readonly cursor: string | undefined; + }; + + /** + * An array of [timeline items](#TimelineItem). + */ + readonly items: readonly TimelineItem[]; + } + + export interface TimelineOptions { + /** + * A provider-defined cursor specifying the starting point of the timeline items that should be returned. + */ + cursor?: string; + + /** + * An optional maximum number timeline items or the all timeline items newer (inclusive) than the timestamp or id that should be returned. + * If `undefined` all timeline items should be returned. + */ + limit?: number | { timestamp: number; id?: string; }; + } + + export interface TimelineProvider { + /** + * An optional event to signal that the timeline for a source has changed. + * To signal that the timeline for all resources (uris) has changed, do not pass any argument or pass `undefined`. + */ + onDidChange?: Event; + + /** + * An identifier of the source of the timeline items. This can be used to filter sources. + */ + readonly id: string; + + /** + * A human-readable string describing the source of the timeline items. This can be used as the display label when filtering sources. + */ + readonly label: string; + + /** + * Provide [timeline items](#TimelineItem) for a [Uri](#Uri). + * + * @param uri The [uri](#Uri) of the file to provide the timeline for. + * @param options A set of options to determine how results should be returned. + * @param token A cancellation token. + * @return The [timeline result](#TimelineResult) or a thenable that resolves to such. The lack of a result + * can be signaled by returning `undefined`, `null`, or an empty array. + */ + provideTimeline(uri: Uri, options: TimelineOptions, token: CancellationToken): ProviderResult; + } + + export namespace workspace { + /** + * Register a timeline provider. + * + * Multiple providers can be registered. In that case, providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param scheme A scheme or schemes that defines which documents this provider is applicable to. Can be `*` to target all documents. + * @param provider A timeline provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerTimelineProvider(scheme: string | string[], provider: TimelineProvider): Disposable; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/91555 + + export enum StandardTokenType { + Other = 0, + Comment = 1, + String = 2, + RegEx = 4 + } + + export interface TokenInformation { + type: StandardTokenType; + range: Range; + } + + export namespace languages { + export function getTokenInformationAtPosition(document: TextDocument, position: Position): Promise; + } + + //#endregion + + //#region Support `scmResourceState` in `when` clauses #86180 https://github.com/microsoft/vscode/issues/86180 + + export interface SourceControlResourceState { + /** + * Context value of the resource state. This can be used to contribute resource specific actions. + * For example, if a resource is given a context value as `diffable`. When contributing actions to `scm/resourceState/context` + * using `menus` extension point, you can specify context value for key `scmResourceState` in `when` expressions, like `scmResourceState == diffable`. + * ``` + * "contributes": { + * "menus": { + * "scm/resourceState/context": [ + * { + * "command": "extension.diff", + * "when": "scmResourceState == diffable" + * } + * ] + * } + * } + * ``` + * This will show action `extension.diff` only for resources with `contextValue` is `diffable`. + */ + readonly contextValue?: string; + } + + //#endregion + //#region https://github.com/microsoft/vscode/issues/101857 + + export interface ExtensionContext { + + /** + * The uri of a directory in which the extension can create log files. + * The directory might not exist on disk and creation is up to the extension. However, + * the parent directory is guaranteed to be existent. + * + * @see [`workspace.fs`](#FileSystem) for how to read and write files and folders from + * an uri. + */ + readonly logUri: Uri; + + /** + * The uri of a workspace specific directory in which the extension + * can store private state. The directory might not exist and creation is + * up to the extension. However, the parent directory is guaranteed to be existent. + * The value is `undefined` when no workspace nor folder has been opened. + * + * Use [`workspaceState`](#ExtensionContext.workspaceState) or + * [`globalState`](#ExtensionContext.globalState) to store key value data. + * + * @see [`workspace.fs`](#FileSystem) for how to read and write files and folders from + * an uri. + */ + readonly storageUri: Uri | undefined; + + /** + * The uri of a directory in which the extension can store global state. + * The directory might not exist on disk and creation is + * up to the extension. However, the parent directory is guaranteed to be existent. + * + * Use [`globalState`](#ExtensionContext.globalState) to store key value data. + * + * @see [`workspace.fs`](#FileSystem) for how to read and write files and folders from + * an uri. + */ + readonly globalStorageUri: Uri; + + /** + * @deprecated Use [logUri](#ExtensionContext.logUri) instead. + */ + readonly logPath: string; + /** + * @deprecated Use [storagePath](#ExtensionContent.storageUri) instead. + */ + readonly storagePath: string | undefined; + /** + * @deprecated Use [globalStoragePath](#ExtensionContent.globalStorageUri) instead. + */ + readonly globalStoragePath: string; + } + + //#endregion +} From b677ebc27a975bf5cf8e38f56835a0bfaf60dd9d Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 10 Aug 2020 18:02:33 +0800 Subject: [PATCH 02/78] Use RNotebookProvider --- package.json | 14 +++++++++++- src/extension.ts | 11 ++++++++-- src/notebook.ts | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 src/notebook.ts diff --git a/package.json b/package.json index 07789a1d8..cee20cbfc 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "onLanguage:rmd", "onLanguage:debian-control.r", "workspaceContains:*.{rproj,Rproj,r,R,rd,Rd,rmd,Rmd}", + "onNotebookEditor:r-notebook", "onCommand:r.createRTerm", "onCommand:r.runSource", "onCommand:r.knitRmd", @@ -984,7 +985,18 @@ "description": "Remove hidden items when clearing workspace." } } - } + }, + "notebookProvider": [ + { + "viewType": "r-notebook-provider", + "displayName": "R Notebook Provider", + "selector": [ + { + "filenamePattern": "*.Rmd" + } + ] + } + ] }, "scripts": { "vscode:prepublish": "webpack --mode production", diff --git a/src/extension.ts b/src/extension.ts index 5a2111cb7..276432c2f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -16,6 +16,7 @@ import * as workspaceViewer from './workspaceViewer'; import * as apiImplementation from './apiImplementation'; import * as rHelp from './rHelp'; import * as completions from './completions'; +import { RNotebookProvider } from './notebook'; // global objects used in other files @@ -36,7 +37,7 @@ export async function activate(context: vscode.ExtensionContext): Promise rTerminal.runSelectionOrWord(['nrow']), 'r.length': () => rTerminal.runSelectionOrWord(['length']), 'r.head': () => rTerminal.runSelectionOrWord(['head']), @@ -168,6 +169,12 @@ export async function activate(context: vscode.ExtensionContext): Promise { + const content = (await vscode.workspace.fs.readFile(uri)).toString(); + const lines = content.split(/\r?\n/); + const cells: vscode.NotebookCellData[] = []; + + let cell: vscode.NotebookCellData; + let line = 0; + while (line < lines.length) { + + line++; + } + + return { + languages: ['r'], + metadata: {}, + cells: cells, + }; + + // return { + // languages: [ 'r' ], + // metadata: { custom: content.metadata }, + // cells: content.cells.map((cell: any) => { + // if (cell.cell_type === 'markdown') { + // return { + // cellKind: vscode.CellKind.Markdown, + // source: cell.source, + // language: 'markdown', + // outputs: [], + // metadata: {} + // }; + // } else if (cell.cell_type === 'code') { + // return { + // cellKind: vscode.CellKind.Code, + // source: cell.source, + // language: content.metadata?.language_info?.name || 'r', + // outputs: [/* not implemented */], + // metadata: {} + // }; + // } else { + // console.error('Unexpected cell:', cell); + // } + // }) + // }; + } + + // The following are dummy implementations not relevant to this example. + onDidChangeNotebook = new vscode.EventEmitter().event; + async resolveNotebook(): Promise { } + async saveNotebook(): Promise { } + async saveNotebookAs(): Promise { } + async backupNotebook(): Promise { return { id: '', delete: () => { } }; } +} From 0525207c07e7e026f2529b8200402ff878514c3f Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Tue, 11 Aug 2020 16:07:26 +0800 Subject: [PATCH 03/78] Read Rmd into cells --- src/notebook.ts | 80 +++++++++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index dffac12e8..455d6681d 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -7,44 +7,66 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { const lines = content.split(/\r?\n/); const cells: vscode.NotebookCellData[] = []; - let cell: vscode.NotebookCellData; let line = 0; + let cellType = 'markdown'; + let cellStartLine = 1; while (line < lines.length) { - + if (cellType === 'markdown') { + if (lines[line].startsWith('---')) { + cellType = 'yaml'; + cellStartLine = line; + } else if (lines[line].startsWith('```{r')) { + cells.push({ + cellKind: vscode.CellKind.Markdown, + source: lines.slice(cellStartLine, line).join('\n'), + language: 'markdown', + outputs: [], + metadata: {}, + }); + cellType = 'r'; + cellStartLine = line; + } + } else if (cellType === 'yaml') { + if (lines[line].startsWith('---')) { + cells.push({ + cellKind: vscode.CellKind.Code, + source: lines.slice(cellStartLine, line + 1).join('\n'), + language: 'yaml', + outputs: [], + metadata: { }, + }) + cellType = 'markdown'; + cellStartLine = line + 1; + } + } else if (cellType === 'r') { + if (lines[line].startsWith('```')) { + cells.push({ + cellKind: vscode.CellKind.Code, + source: lines.slice(cellStartLine + 1, line).join('\n'), + language: 'r', + outputs: [], + metadata: {}, + }) + cellType = 'markdown'; + cellStartLine = line + 1; + } + } else if (line == lines.length - 1) { + cells.push({ + cellKind: vscode.CellKind.Markdown, + source: lines.slice(cellStartLine, line).join('\n'), + language: 'markdown', + outputs: [], + metadata: {}, + }); + } line++; } return { - languages: ['r'], + languages: ['r', 'yaml'], metadata: {}, cells: cells, }; - - // return { - // languages: [ 'r' ], - // metadata: { custom: content.metadata }, - // cells: content.cells.map((cell: any) => { - // if (cell.cell_type === 'markdown') { - // return { - // cellKind: vscode.CellKind.Markdown, - // source: cell.source, - // language: 'markdown', - // outputs: [], - // metadata: {} - // }; - // } else if (cell.cell_type === 'code') { - // return { - // cellKind: vscode.CellKind.Code, - // source: cell.source, - // language: content.metadata?.language_info?.name || 'r', - // outputs: [/* not implemented */], - // metadata: {} - // }; - // } else { - // console.error('Unexpected cell:', cell); - // } - // }) - // }; } // The following are dummy implementations not relevant to this example. From 6378beced37c1541a8308f9daf01dcd8b001e769 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Tue, 11 Aug 2020 16:28:48 +0800 Subject: [PATCH 04/78] Fix code --- src/notebook.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index 455d6681d..37122b094 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -33,8 +33,8 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { source: lines.slice(cellStartLine, line + 1).join('\n'), language: 'yaml', outputs: [], - metadata: { }, - }) + metadata: {}, + }); cellType = 'markdown'; cellStartLine = line + 1; } @@ -46,7 +46,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { language: 'r', outputs: [], metadata: {}, - }) + }); cellType = 'markdown'; cellStartLine = line + 1; } From 493eb5a09efef897dbcd9d2769e4ae46f9209113 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Tue, 11 Aug 2020 17:07:43 +0800 Subject: [PATCH 05/78] Add simple notebook kernel script --- R/client.R | 8 ++++++++ R/notebook.R | 33 +++++++++++++++++++++++++++++++++ src/notebook.ts | 2 +- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 R/client.R create mode 100644 R/notebook.R diff --git a/R/client.R b/R/client.R new file mode 100644 index 000000000..752ac1770 --- /dev/null +++ b/R/client.R @@ -0,0 +1,8 @@ +con <- socketConnection(host = "127.0.0.1", port = 8780, blocking = TRUE, + server = FALSE, open = "r+", timeout = 86400) +on.exit(close(con)) +request <- list(client = "hello", time = format(Sys.time()), expr = "1+1") +json <- jsonlite::toJSON(request, auto_unbox = TRUE) +writeLines(json, con) +response <- readLines(con) +response diff --git a/R/notebook.R b/R/notebook.R new file mode 100644 index 000000000..15f65fd26 --- /dev/null +++ b/R/notebook.R @@ -0,0 +1,33 @@ +local({ + requireNamespace("jsonlite") + port <- 8780 + args <- commandArgs(trailingOnly = TRUE) + for (arg in args) { + eval(arg, globalenv()) + } + + while (TRUE) { + con <- try(socketConnection(host = "127.0.0.1", port = port, + blocking = TRUE, server = TRUE, + open = "r+", timeout = 86400L), silent = TRUE) + if (inherits(con, "try-error")) { + message(con, "\n") + } else { + tryCatch({ + request <- jsonlite::fromJSON(readLines(con, n = 1)) + cat(sprintf("[%s] %s > %s\n", + request$time, + request$client, request$expr)) + expr <- parse(text = request$expr) + res <- try(eval(expr, globalenv()), silent = TRUE) + str <- list( + type = if (inherits(res, "try-error")) "error" else "output", + result = utils::capture.output(print(res)) + ) + writeLines(jsonlite::toJSON(str), con) + }, error = function(e) message(e, "\n"), + warning = function(w) message(w, "\n"), + finally = close(con)) + } + } +}) diff --git a/src/notebook.ts b/src/notebook.ts index 37122b094..70193f295 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -1,5 +1,5 @@ import * as vscode from 'vscode'; -import fs = require('fs-extra'); +import * as cp from 'child_process'; export class RNotebookProvider implements vscode.NotebookContentProvider { async openNotebook(uri: vscode.Uri): Promise { From b95d003054d756ffea1c9d5bb8370c8f9b47338b Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Tue, 11 Aug 2020 17:39:27 +0800 Subject: [PATCH 06/78] Fix openNotebook --- src/notebook.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index 70193f295..3e4894b26 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -9,7 +9,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { let line = 0; let cellType = 'markdown'; - let cellStartLine = 1; + let cellStartLine = 0; while (line < lines.length) { if (cellType === 'markdown') { if (lines[line].startsWith('---')) { @@ -25,6 +25,14 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { }); cellType = 'r'; cellStartLine = line; + } else if (line == lines.length - 1) { + cells.push({ + cellKind: vscode.CellKind.Markdown, + source: lines.slice(cellStartLine, line).join('\n'), + language: 'markdown', + outputs: [], + metadata: {}, + }); } } else if (cellType === 'yaml') { if (lines[line].startsWith('---')) { @@ -50,14 +58,6 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { cellType = 'markdown'; cellStartLine = line + 1; } - } else if (line == lines.length - 1) { - cells.push({ - cellKind: vscode.CellKind.Markdown, - source: lines.slice(cellStartLine, line).join('\n'), - language: 'markdown', - outputs: [], - metadata: {}, - }); } line++; } From b6c9fc6b9590da9ce48b5d7f39d7b00054a370c9 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Tue, 11 Aug 2020 18:03:20 +0800 Subject: [PATCH 07/78] Start R from script --- src/extension.ts | 1 - src/notebook.ts | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 276432c2f..02b4fd5bd 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -18,7 +18,6 @@ import * as rHelp from './rHelp'; import * as completions from './completions'; import { RNotebookProvider } from './notebook'; - // global objects used in other files export let rWorkspace: workspaceViewer.WorkspaceDataProvider | undefined = undefined; export let globalRHelp: rHelp.RHelp | undefined = undefined; diff --git a/src/notebook.ts b/src/notebook.ts index 3e4894b26..6af23b13c 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -1,7 +1,13 @@ import * as vscode from 'vscode'; -import * as cp from 'child_process'; +import net = require('net'); +import { spawn } from 'child_process'; export class RNotebookProvider implements vscode.NotebookContentProvider { + private kernalScript: string; + constructor(kernelScript: string) { + this.kernalScript = kernelScript; + } + async openNotebook(uri: vscode.Uri): Promise { const content = (await vscode.workspace.fs.readFile(uri)).toString(); const lines = content.split(/\r?\n/); @@ -61,6 +67,32 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { } line++; } + + const env = Object.create(process.env); + env.LANG = "en_US.UTF-8" + + const childProcess = spawn('R', ["--quite", "--slave", "-f", this.kernalScript], + { cwd: vscode.workspace.workspaceFolders[0].uri.fsPath, env: env }); + childProcess.stderr.on('data', (chunk: Buffer) => { + const str = chunk.toString(); + console.log(`R process (${childProcess.pid}): ${str}`); + }); + childProcess.on('exit', (code, signal) => { + console.log(`R process exited with code ${code}`); + }); + + const client = net.createConnection({ + port: 8780, + }, () => { + console.log('connected to server!'); + }); + client.on('data', (data) => { + console.log(data.toString()); + client.end(); + }); + client.on('end', () => { + console.log('disconnected from server'); + }); return { languages: ['r', 'yaml'], From c4ecfedac4d6b461966bc3bbec41f65655d3fb5b Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Tue, 11 Aug 2020 18:47:00 +0800 Subject: [PATCH 08/78] Use single quotes --- src/notebook.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index 6af23b13c..a9eb2ed10 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -31,7 +31,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { }); cellType = 'r'; cellStartLine = line; - } else if (line == lines.length - 1) { + } else if (line === lines.length - 1) { cells.push({ cellKind: vscode.CellKind.Markdown, source: lines.slice(cellStartLine, line).join('\n'), @@ -69,9 +69,9 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { } const env = Object.create(process.env); - env.LANG = "en_US.UTF-8" + env.LANG = 'en_US.UTF-8'; - const childProcess = spawn('R', ["--quite", "--slave", "-f", this.kernalScript], + const childProcess = spawn('R', ['--quite', '--slave', '-f', this.kernalScript], { cwd: vscode.workspace.workspaceFolders[0].uri.fsPath, env: env }); childProcess.stderr.on('data', (chunk: Buffer) => { const str = chunk.toString(); From 504ece866083a8bf8d4c1329813c31719ab73613 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Tue, 11 Aug 2020 18:53:19 +0800 Subject: [PATCH 09/78] Rename notebook --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index cee20cbfc..d88334980 100644 --- a/package.json +++ b/package.json @@ -988,11 +988,11 @@ }, "notebookProvider": [ { - "viewType": "r-notebook-provider", - "displayName": "R Notebook Provider", + "viewType": "r-notebook", + "displayName": "R Notebook", "selector": [ { - "filenamePattern": "*.Rmd" + "filenamePattern": "*.rmd" } ] } From b46d1b34032774d0458b022579714d085f64821c Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Tue, 11 Aug 2020 18:59:25 +0800 Subject: [PATCH 10/78] Update notebook.ts --- src/notebook.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index a9eb2ed10..194009fc3 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -43,11 +43,13 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { } else if (cellType === 'yaml') { if (lines[line].startsWith('---')) { cells.push({ - cellKind: vscode.CellKind.Code, + cellKind: vscode.CellKind.Markdown, source: lines.slice(cellStartLine, line + 1).join('\n'), language: 'yaml', outputs: [], - metadata: {}, + metadata: { + runnable: false, + }, }); cellType = 'markdown'; cellStartLine = line + 1; @@ -59,7 +61,9 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { source: lines.slice(cellStartLine + 1, line).join('\n'), language: 'r', outputs: [], - metadata: {}, + metadata: { + runnable: true, + }, }); cellType = 'markdown'; cellStartLine = line + 1; From bdec79b9f0dca2964e480796254d46ea12ddcc39 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Tue, 11 Aug 2020 19:01:08 +0800 Subject: [PATCH 11/78] Update folder --- src/notebook.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/notebook.ts b/src/notebook.ts index 194009fc3..ebcbafdc1 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -75,8 +75,9 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { const env = Object.create(process.env); env.LANG = 'en_US.UTF-8'; + const folder = vscode.workspace.getWorkspaceFolder(uri); const childProcess = spawn('R', ['--quite', '--slave', '-f', this.kernalScript], - { cwd: vscode.workspace.workspaceFolders[0].uri.fsPath, env: env }); + { cwd: folder.uri.fsPath, env: env }); childProcess.stderr.on('data', (chunk: Buffer) => { const str = chunk.toString(); console.log(`R process (${childProcess.pid}): ${str}`); From d97ae297591ecd29d7db646a2e3495700ad5b34b Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Tue, 11 Aug 2020 19:01:55 +0800 Subject: [PATCH 12/78] Update notebook.ts --- src/notebook.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index ebcbafdc1..3cd612470 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -1,6 +1,7 @@ import * as vscode from 'vscode'; import net = require('net'); import { spawn } from 'child_process'; +import { dirname } from 'path'; export class RNotebookProvider implements vscode.NotebookContentProvider { private kernalScript: string; @@ -75,9 +76,8 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { const env = Object.create(process.env); env.LANG = 'en_US.UTF-8'; - const folder = vscode.workspace.getWorkspaceFolder(uri); const childProcess = spawn('R', ['--quite', '--slave', '-f', this.kernalScript], - { cwd: folder.uri.fsPath, env: env }); + { cwd: dirname(uri.fsPath), env: env }); childProcess.stderr.on('data', (chunk: Buffer) => { const str = chunk.toString(); console.log(`R process (${childProcess.pid}): ${str}`); From a2cb420976c3ea4c3537df8b3e8d82db65639293 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Tue, 11 Aug 2020 23:07:16 +0800 Subject: [PATCH 13/78] Update notebook server --- R/notebook.R | 50 +++++----- src/notebook.ts | 258 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 247 insertions(+), 61 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index 15f65fd26..47b7d1397 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -1,33 +1,33 @@ local({ requireNamespace("jsonlite") - port <- 8780 args <- commandArgs(trailingOnly = TRUE) - for (arg in args) { - eval(arg, globalenv()) + exprs <- parse(text = args, keep.source = FALSE) + env <- new.env() + for (expr in exprs) { + eval(expr, env) + } + + con <- try(socketConnection(host = "127.0.0.1", port = env$port, + blocking = TRUE, server = TRUE, + open = "r+", timeout = 86400L), silent = TRUE) + if (inherits(con, "try-error")) { + stop(con) } while (TRUE) { - con <- try(socketConnection(host = "127.0.0.1", port = port, - blocking = TRUE, server = TRUE, - open = "r+", timeout = 86400L), silent = TRUE) - if (inherits(con, "try-error")) { - message(con, "\n") - } else { - tryCatch({ - request <- jsonlite::fromJSON(readLines(con, n = 1)) - cat(sprintf("[%s] %s > %s\n", - request$time, - request$client, request$expr)) - expr <- parse(text = request$expr) - res <- try(eval(expr, globalenv()), silent = TRUE) - str <- list( - type = if (inherits(res, "try-error")) "error" else "output", - result = utils::capture.output(print(res)) - ) - writeLines(jsonlite::toJSON(str), con) - }, error = function(e) message(e, "\n"), - warning = function(w) message(w, "\n"), - finally = close(con)) - } + tryCatch({ + request <- jsonlite::fromJSON(readLines(con, n = 1)) + cat(sprintf("[%s] %s > %s\n", + request$time, request$expr)) + expr <- parse(text = request$expr) + res <- try(eval(expr, globalenv()), silent = TRUE) + str <- list( + type = if (inherits(res, "try-error")) "error" else "output", + result = utils::capture.output(print(res)) + ) + writeLines(jsonlite::toJSON(str), con) + }, error = function(e) message(e, "\n"), + warning = function(w) message(w, "\n"), + finally = close(con)) } }) diff --git a/src/notebook.ts b/src/notebook.ts index 3cd612470..cc6a86516 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -1,12 +1,156 @@ import * as vscode from 'vscode'; import net = require('net'); -import { spawn } from 'child_process'; +import { spawn, ChildProcess } from 'child_process'; import { dirname } from 'path'; -export class RNotebookProvider implements vscode.NotebookContentProvider { - private kernalScript: string; +class RKernel { + private kernelScript: string; + private cwd: string; + private process: ChildProcess; + private server: net.Server; + private port: number; + private outputBuffer = ''; + + constructor(kernelScript: string, doc: vscode.NotebookDocument) { + this.kernelScript = kernelScript; + this.cwd = dirname(doc.uri.fsPath); + } + + public start() { + if (this.process) { + return; + } + + const env = Object.create(process.env); + env.LANG = 'en_US.UTF-8'; + + const server = net.createServer((socket) => { + console.log('server created'); + socket.on('end', () => { + console.log('R process disconnected'); + }); + socket.on('data', (data) => { + console.log(data.toString()); + socket.end(); + }); + server.close(); + }); + + this.server = server; + + server.listen(0, () => { + const port = (server.address() as net.AddressInfo).port; + const childProcess = spawn('R', ['--quite', '--slave', '-f', this.kernelScript, '--args', `port=${port}`], + { cwd: this.cwd, env: env }); + childProcess.stderr.on('data', (chunk: Buffer) => { + const str = chunk.toString(); + console.log(`R process (${childProcess.pid}): ${str}`); + }); + childProcess.on('exit', (code, signal) => { + console.log(`R process exited with code ${code}`); + }); + this.process = childProcess; + this.port = port; + }); + } + + public stop() { + if (this.process) { + this.process.kill(); + this.process = undefined; + } + + if (this.server) { + this.server.close(); + this.server = undefined; + } + } + + public restart() { + this.stop(); + this.start(); + } + + public async eval(cell: vscode.NotebookCell): Promise { + if (this.process && this.server) { + this.outputBuffer = ''; + await new Promise(res => setTimeout(res, 500)); + + const client = net.createConnection({ port: this.port }, () => { + console.log('connected to server!'); + }); + + client.on('data', (data) => { + const result = data.toString(); + console.log(result); + this.outputBuffer += result; + client.end(); + }); + + client.on('end', () => { + console.log('disconnected from server'); + }); + + client.write(JSON.stringify({ + time: Date.now(), + uri: cell.uri.toString(), + expr: '1+1', + })); + + return Promise.resolve(this.outputBuffer); + } + } +} + +class RNotebook implements vscode.Disposable { + private kernel: RKernel; + private disposables: vscode.Disposable[] = []; + + constructor(kernelScript: string, doc: vscode.NotebookDocument) { + this.kernel = new RKernel(kernelScript, doc); + } + + dispose() { + this.kernel.stop(); + } + + public async restartKernel() { + await vscode.commands.executeCommand('notebook.clearAllCellsOutputs'); + this.kernel.restart(); + } + + public async eval(cell: vscode.NotebookCell): Promise { + this.kernel.start(); + return this.kernel.eval(cell); + } +} + +export class RNotebookProvider implements vscode.NotebookContentProvider, vscode.NotebookKernel { + public label = 'R Kernel'; + public kernel = this; + + private kernelScript: string; + private disposables: vscode.Disposable[] = []; + private readonly notebooks = new Map(); + constructor(kernelScript: string) { - this.kernalScript = kernelScript; + this.kernelScript = kernelScript; + this.disposables.push( + vscode.notebook.onDidOpenNotebookDocument(document => { + const docKey = document.uri.toString(); + if (!this.notebooks.has(docKey)) { + this.notebooks.set(docKey, new RNotebook(this.kernelScript, document)); + } + }), + vscode.notebook.onDidCloseNotebookDocument(document => { + const docKey = document.uri.toString(); + const notebook = this.notebooks.get(docKey); + if (notebook) { + notebook.dispose(); + this.notebooks.delete(docKey); + } + }), + ); } async openNotebook(uri: vscode.Uri): Promise { @@ -28,7 +172,10 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { source: lines.slice(cellStartLine, line).join('\n'), language: 'markdown', outputs: [], - metadata: {}, + metadata: { + editable: true, + runnable: false, + }, }); cellType = 'r'; cellStartLine = line; @@ -38,7 +185,10 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { source: lines.slice(cellStartLine, line).join('\n'), language: 'markdown', outputs: [], - metadata: {}, + metadata: { + editable: true, + runnable: false, + }, }); } } else if (cellType === 'yaml') { @@ -49,6 +199,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { language: 'yaml', outputs: [], metadata: { + editable: true, runnable: false, }, }); @@ -63,6 +214,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { language: 'r', outputs: [], metadata: { + editable: true, runnable: true, }, }); @@ -72,36 +224,10 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { } line++; } - - const env = Object.create(process.env); - env.LANG = 'en_US.UTF-8'; - - const childProcess = spawn('R', ['--quite', '--slave', '-f', this.kernalScript], - { cwd: dirname(uri.fsPath), env: env }); - childProcess.stderr.on('data', (chunk: Buffer) => { - const str = chunk.toString(); - console.log(`R process (${childProcess.pid}): ${str}`); - }); - childProcess.on('exit', (code, signal) => { - console.log(`R process exited with code ${code}`); - }); - - const client = net.createConnection({ - port: 8780, - }, () => { - console.log('connected to server!'); - }); - client.on('data', (data) => { - console.log(data.toString()); - client.end(); - }); - client.on('end', () => { - console.log('disconnected from server'); - }); return { languages: ['r', 'yaml'], - metadata: {}, + metadata: { }, cells: cells, }; } @@ -109,7 +235,67 @@ export class RNotebookProvider implements vscode.NotebookContentProvider { // The following are dummy implementations not relevant to this example. onDidChangeNotebook = new vscode.EventEmitter().event; async resolveNotebook(): Promise { } - async saveNotebook(): Promise { } - async saveNotebookAs(): Promise { } - async backupNotebook(): Promise { return { id: '', delete: () => { } }; } + async saveNotebook(document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { } + async saveNotebookAs(targetResource: vscode.Uri, document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { } + async backupNotebook(document: vscode.NotebookDocument, context: vscode.NotebookDocumentBackupContext, cancellation: vscode.CancellationToken): Promise { return { id: '', delete: () => { } }; } + async executeCell(document: vscode.NotebookDocument, cell: vscode.NotebookCell) { + const notebook = this.notebooks.get(document.uri.toString()); + + if (!cell) { + if (notebook) { + notebook.restartKernel(); + } + + for (const cell of document.cells) { + if (cell.cellKind === vscode.CellKind.Code && cell.metadata.runnable) { + await this.executeCell(document, cell); + } + } + + return; + } + + let output = ''; + let error: Error; + + if (notebook) { + try { + output = await notebook.eval(cell); + } catch (e) { + error = e; + } + } + + if (error) { + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Error, + evalue: error.toString(), + ename: '', + traceback: [], + }]; + } else { + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Text, + text: output, + }]; + } + } + + async executeAllCells(document: vscode.NotebookDocument): Promise { + for (const cell of document.cells) { + await this.executeCell(document, cell); + } + } + + async cancelCellExecution(document: vscode.NotebookDocument, cell: vscode.NotebookCell) { + + } + + async cancelAllCellsExecution(document: vscode.NotebookDocument) { + + } + + public dispose() { + this.disposables.forEach(d => d.dispose()); + } } From 24a3c6da934fbbb220774b918c0294d054a49c11 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Wed, 12 Aug 2020 00:24:38 +0800 Subject: [PATCH 14/78] Update notebook --- R/client.R | 6 ++--- R/notebook.R | 43 ++++++++++++++++---------------- src/notebook.ts | 65 +++++++++++++++++-------------------------------- 3 files changed, 47 insertions(+), 67 deletions(-) diff --git a/R/client.R b/R/client.R index 752ac1770..71e2baed6 100644 --- a/R/client.R +++ b/R/client.R @@ -1,7 +1,7 @@ -con <- socketConnection(host = "127.0.0.1", port = 8780, blocking = TRUE, - server = FALSE, open = "r+", timeout = 86400) +con <- socketConnection(host = "127.0.0.1", port = 8781, blocking = TRUE, + server = FALSE, open = "w", timeout = 86400) on.exit(close(con)) -request <- list(client = "hello", time = format(Sys.time()), expr = "1+1") +request <- list(time = format(Sys.time()), expr = "1+1") json <- jsonlite::toJSON(request, auto_unbox = TRUE) writeLines(json, con) response <- readLines(con) diff --git a/R/notebook.R b/R/notebook.R index 47b7d1397..c82765038 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -7,27 +7,28 @@ local({ eval(expr, env) } - con <- try(socketConnection(host = "127.0.0.1", port = env$port, - blocking = TRUE, server = TRUE, - open = "r+", timeout = 86400L), silent = TRUE) - if (inherits(con, "try-error")) { - stop(con) - } - + print(ls.str(env)) while (TRUE) { - tryCatch({ - request <- jsonlite::fromJSON(readLines(con, n = 1)) - cat(sprintf("[%s] %s > %s\n", - request$time, request$expr)) - expr <- parse(text = request$expr) - res <- try(eval(expr, globalenv()), silent = TRUE) - str <- list( - type = if (inherits(res, "try-error")) "error" else "output", - result = utils::capture.output(print(res)) - ) - writeLines(jsonlite::toJSON(str), con) - }, error = function(e) message(e, "\n"), - warning = function(w) message(w, "\n"), - finally = close(con)) + con <- try(socketConnection(host = "127.0.0.1", port = env$port, + blocking = TRUE, server = TRUE, + open = "r+", timeout = 86400L), silent = TRUE) + if (inherits(con, "try-error")) { + message(con, "\n") + } else { + tryCatch({ + request <- jsonlite::fromJSON(readLines(con, n = 1)) + cat(sprintf("[%s] %s\n", + request$time, request$expr)) + expr <- parse(text = request$expr) + res <- try(eval(expr, globalenv()), silent = TRUE) + str <- list( + type = if (inherits(res, "try-error")) "error" else "output", + result = utils::capture.output(print(res)) + ) + writeLines(jsonlite::toJSON(str), con) + }, error = function(e) message(e, "\n"), + warning = function(w) message(w, "\n"), + finally = close(con)) + } } }) diff --git a/src/notebook.ts b/src/notebook.ts index cc6a86516..6ece77f7f 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -2,21 +2,20 @@ import * as vscode from 'vscode'; import net = require('net'); import { spawn, ChildProcess } from 'child_process'; import { dirname } from 'path'; +import getPort = require('get-port'); class RKernel { private kernelScript: string; private cwd: string; private process: ChildProcess; - private server: net.Server; private port: number; - private outputBuffer = ''; constructor(kernelScript: string, doc: vscode.NotebookDocument) { this.kernelScript = kernelScript; this.cwd = dirname(doc.uri.fsPath); } - public start() { + public async start() { if (this.process) { return; } @@ -24,34 +23,17 @@ class RKernel { const env = Object.create(process.env); env.LANG = 'en_US.UTF-8'; - const server = net.createServer((socket) => { - console.log('server created'); - socket.on('end', () => { - console.log('R process disconnected'); - }); - socket.on('data', (data) => { - console.log(data.toString()); - socket.end(); - }); - server.close(); + this.port = await getPort(); + const childProcess = spawn('R', ['--quite', '--slave', '-f', this.kernelScript, '--args', `port=${this.port}`], + { cwd: this.cwd, env: env }); + childProcess.stderr.on('data', (chunk: Buffer) => { + const str = chunk.toString(); + console.log(`R process (${childProcess.pid}): ${str}`); }); - - this.server = server; - - server.listen(0, () => { - const port = (server.address() as net.AddressInfo).port; - const childProcess = spawn('R', ['--quite', '--slave', '-f', this.kernelScript, '--args', `port=${port}`], - { cwd: this.cwd, env: env }); - childProcess.stderr.on('data', (chunk: Buffer) => { - const str = chunk.toString(); - console.log(`R process (${childProcess.pid}): ${str}`); - }); - childProcess.on('exit', (code, signal) => { - console.log(`R process exited with code ${code}`); - }); - this.process = childProcess; - this.port = port; + childProcess.on('exit', (code, signal) => { + console.log(`R process exited with code ${code}`); }); + this.process = childProcess; } public stop() { @@ -59,22 +41,17 @@ class RKernel { this.process.kill(); this.process = undefined; } - - if (this.server) { - this.server.close(); - this.server = undefined; - } } - public restart() { + public async restart() { this.stop(); - this.start(); + await this.start(); } public async eval(cell: vscode.NotebookCell): Promise { - if (this.process && this.server) { - this.outputBuffer = ''; - await new Promise(res => setTimeout(res, 500)); + if (this.process) { + let outputBuffer = ''; + await new Promise(res => setTimeout(res, 1000)); const client = net.createConnection({ port: this.port }, () => { console.log('connected to server!'); @@ -83,7 +60,7 @@ class RKernel { client.on('data', (data) => { const result = data.toString(); console.log(result); - this.outputBuffer += result; + outputBuffer += result; client.end(); }); @@ -91,13 +68,15 @@ class RKernel { console.log('disconnected from server'); }); - client.write(JSON.stringify({ + const json = JSON.stringify({ time: Date.now(), uri: cell.uri.toString(), expr: '1+1', - })); + }); + console.log(`Send: ${json}`); + client.write(json); - return Promise.resolve(this.outputBuffer); + return Promise.resolve(outputBuffer); } } } From 20a5b4b6ce74fe49a6a015898137ab966629093c Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Wed, 12 Aug 2020 11:25:41 +0800 Subject: [PATCH 15/78] Update notebook --- R/client.R | 8 ++++---- R/notebook.R | 35 +++++++++++++++-------------------- package-lock.json | 5 +++++ src/notebook.ts | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/R/client.R b/R/client.R index 71e2baed6..11d236b5b 100644 --- a/R/client.R +++ b/R/client.R @@ -1,8 +1,8 @@ -con <- socketConnection(host = "127.0.0.1", port = 8781, blocking = TRUE, - server = FALSE, open = "w", timeout = 86400) -on.exit(close(con)) +con <- socketConnection(host = "127.0.0.1", port = 8708, + blocking = TRUE, server = FALSE, open = "r+") request <- list(time = format(Sys.time()), expr = "1+1") json <- jsonlite::toJSON(request, auto_unbox = TRUE) writeLines(json, con) -response <- readLines(con) +response <- readLines(con, n = 1) response +close(con) diff --git a/R/notebook.R b/R/notebook.R index c82765038..b36b3bbe0 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -9,26 +9,21 @@ local({ print(ls.str(env)) while (TRUE) { - con <- try(socketConnection(host = "127.0.0.1", port = env$port, + con <- socketConnection(host = "127.0.0.1", port = env$port, blocking = TRUE, server = TRUE, - open = "r+", timeout = 86400L), silent = TRUE) - if (inherits(con, "try-error")) { - message(con, "\n") - } else { - tryCatch({ - request <- jsonlite::fromJSON(readLines(con, n = 1)) - cat(sprintf("[%s] %s\n", - request$time, request$expr)) - expr <- parse(text = request$expr) - res <- try(eval(expr, globalenv()), silent = TRUE) - str <- list( - type = if (inherits(res, "try-error")) "error" else "output", - result = utils::capture.output(print(res)) - ) - writeLines(jsonlite::toJSON(str), con) - }, error = function(e) message(e, "\n"), - warning = function(w) message(w, "\n"), - finally = close(con)) - } + open = "r+") + line <- readLines(con, n = 1) + request <- jsonlite::fromJSON(line) + cat(sprintf("[%s] %s\n", + request$time, request$expr)) + expr <- parse(text = request$expr) + res <- try(eval(expr, globalenv()), silent = TRUE) + str <- list( + type = if (inherits(res, "try-error")) "error" else "output", + result = utils::capture.output(print(res)) + ) + result <- jsonlite::toJSON(str, force = TRUE) + writeLines(result, con) + close(con) } }) diff --git a/package-lock.json b/package-lock.json index 539f534e9..221ca320c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1831,6 +1831,11 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, + "get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==" + }, "get-stream": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", diff --git a/src/notebook.ts b/src/notebook.ts index 6ece77f7f..fd9bab6bf 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -99,7 +99,7 @@ class RNotebook implements vscode.Disposable { } public async eval(cell: vscode.NotebookCell): Promise { - this.kernel.start(); + await this.kernel.start(); return this.kernel.eval(cell); } } From cd90c189de3e93574d47c4e35f57c7c9db7d9218 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Wed, 12 Aug 2020 12:23:18 +0800 Subject: [PATCH 16/78] Update notebook --- src/notebook.ts | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index fd9bab6bf..bd79cb12b 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -55,27 +55,27 @@ class RKernel { const client = net.createConnection({ port: this.port }, () => { console.log('connected to server!'); + client.on('data', (data) => { + const result = data.toString(); + console.log(result); + outputBuffer += result; + client.end(); + }); + + client.on('end', () => { + console.log('disconnected from server'); + }); + + const json = JSON.stringify({ + time: Date.now(), + uri: cell.uri.toString(), + expr: '1+1', + }); + + console.log(`Send: ${json}`); + client.write(json); }); - client.on('data', (data) => { - const result = data.toString(); - console.log(result); - outputBuffer += result; - client.end(); - }); - - client.on('end', () => { - console.log('disconnected from server'); - }); - - const json = JSON.stringify({ - time: Date.now(), - uri: cell.uri.toString(), - expr: '1+1', - }); - console.log(`Send: ${json}`); - client.write(json); - return Promise.resolve(outputBuffer); } } From 54ec035c8f20aa36bb8c1eda342e6370194c6759 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Wed, 12 Aug 2020 14:58:31 +0800 Subject: [PATCH 17/78] Update socket --- R/notebook.R | 5 +++-- src/notebook.ts | 46 ++++++++++++++++++++++++---------------------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index b36b3bbe0..e1f07e647 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -7,8 +7,9 @@ local({ eval(expr, env) } - print(ls.str(env)) + ls.str(env) while (TRUE) { + cat("Waiting\n") con <- socketConnection(host = "127.0.0.1", port = env$port, blocking = TRUE, server = TRUE, open = "r+") @@ -22,7 +23,7 @@ local({ type = if (inherits(res, "try-error")) "error" else "output", result = utils::capture.output(print(res)) ) - result <- jsonlite::toJSON(str, force = TRUE) + result <- jsonlite::toJSON(str, auto_unbox = TRUE, force = TRUE) writeLines(result, con) close(con) } diff --git a/src/notebook.ts b/src/notebook.ts index bd79cb12b..64c138080 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -1,7 +1,7 @@ import * as vscode from 'vscode'; import net = require('net'); import { spawn, ChildProcess } from 'child_process'; -import { dirname } from 'path'; +import { dirname, resolve } from 'path'; import getPort = require('get-port'); class RKernel { @@ -24,14 +24,18 @@ class RKernel { env.LANG = 'en_US.UTF-8'; this.port = await getPort(); - const childProcess = spawn('R', ['--quite', '--slave', '-f', this.kernelScript, '--args', `port=${this.port}`], + const childProcess = spawn('R', ['--quiet', '--slave', '-f', this.kernelScript, '--args', `port=${this.port}`], { cwd: this.cwd, env: env }); childProcess.stderr.on('data', (chunk: Buffer) => { const str = chunk.toString(); - console.log(`R process (${childProcess.pid}): ${str}`); + console.log(`R stderr (${childProcess.pid}): ${str}`); + }); + childProcess.stdout.on('data', (chunk: Buffer) => { + const str = chunk.toString(); + console.log(`R stdout (${childProcess.pid}): ${str}`); }); childProcess.on('exit', (code, signal) => { - console.log(`R process exited with code ${code}`); + console.log(`R exited with code ${code}`); }); this.process = childProcess; } @@ -50,33 +54,29 @@ class RKernel { public async eval(cell: vscode.NotebookCell): Promise { if (this.process) { - let outputBuffer = ''; - await new Promise(res => setTimeout(res, 1000)); - const client = net.createConnection({ port: this.port }, () => { console.log('connected to server!'); + const json = `{"time":"${Date.now().toString()}","expr":"rnorm(3)"}\n`; + console.log(`Send: ${json}`); + client.write(json); + }); + + client.on('end', () => { + console.log('disconnected from server'); + }); + + return new Promise((resolve, reject) => { client.on('data', (data) => { const result = data.toString(); console.log(result); - outputBuffer += result; client.end(); + resolve(result); }); - client.on('end', () => { - console.log('disconnected from server'); - }); - - const json = JSON.stringify({ - time: Date.now(), - uri: cell.uri.toString(), - expr: '1+1', + client.on('error', (err) => { + reject(err.message); }); - - console.log(`Send: ${json}`); - client.write(json); }); - - return Promise.resolve(outputBuffer); } } } @@ -118,7 +118,9 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode vscode.notebook.onDidOpenNotebookDocument(document => { const docKey = document.uri.toString(); if (!this.notebooks.has(docKey)) { - this.notebooks.set(docKey, new RNotebook(this.kernelScript, document)); + const notebook = new RNotebook(this.kernelScript, document); + notebook.restartKernel(); + this.notebooks.set(docKey, notebook); } }), vscode.notebook.onDidCloseNotebookDocument(document => { From 577e98b8ee0a5046bbfe45bb5519b368e06a498e Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Wed, 12 Aug 2020 15:58:40 +0800 Subject: [PATCH 18/78] Update notebook --- src/notebook.ts | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index 64c138080..bca50f21e 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -56,9 +56,12 @@ class RKernel { if (this.process) { const client = net.createConnection({ port: this.port }, () => { console.log('connected to server!'); - const json = `{"time":"${Date.now().toString()}","expr":"rnorm(3)"}\n`; - console.log(`Send: ${json}`); - client.write(json); + const request = JSON.stringify({ + time: Date.now(), + expr: cell.document.getText(), + }).concat('\n'); + console.log(`Send: ${request}`); + client.write(request); }); client.on('end', () => { @@ -67,10 +70,12 @@ class RKernel { return new Promise((resolve, reject) => { client.on('data', (data) => { - const result = data.toString(); - console.log(result); + const response = data.toString(); + console.log(response); client.end(); - resolve(result); + const output = JSON.parse(response); + const result: string[] = output.result; + resolve(result.join('\n')); }); client.on('error', (err) => { From 3d2c61a5e404e43a30287858265f26699a3daae4 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Wed, 12 Aug 2020 23:31:51 +0800 Subject: [PATCH 19/78] Update R/notebook.R --- R/notebook.R | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index e1f07e647..c3cb962a6 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -9,22 +9,28 @@ local({ ls.str(env) while (TRUE) { - cat("Waiting\n") - con <- socketConnection(host = "127.0.0.1", port = env$port, + con <- try(socketConnection(host = "127.0.0.1", port = env$port, blocking = TRUE, server = TRUE, - open = "r+") - line <- readLines(con, n = 1) - request <- jsonlite::fromJSON(line) - cat(sprintf("[%s] %s\n", - request$time, request$expr)) - expr <- parse(text = request$expr) - res <- try(eval(expr, globalenv()), silent = TRUE) - str <- list( - type = if (inherits(res, "try-error")) "error" else "output", - result = utils::capture.output(print(res)) - ) - result <- jsonlite::toJSON(str, auto_unbox = TRUE, force = TRUE) - writeLines(result, con) - close(con) + open = "r+"), silent = TRUE) + if (inherits(con, "try-error")) { + message(con) + } else { + tryCatch({ + line <- readLines(con, n = 1) + request <- jsonlite::fromJSON(line) + cat(sprintf("[%s]\n%s\n", + request$time, request$expr)) + expr <- parse(text = request$expr) + res <- try(eval(expr, globalenv()), silent = TRUE) + str <- list( + type = if (inherits(res, "try-error")) "error" else "output", + result = utils::capture.output(print(res)) + ) + result <- jsonlite::toJSON(str, auto_unbox = TRUE, force = TRUE) + writeLines(result, con) + }, error = function(e) { + message(e) + }, finally = close(con)) + } } }) From af838cda141d27a8c2dce1d26aeecaadf2153ca5 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Thu, 13 Aug 2020 11:48:44 +0800 Subject: [PATCH 20/78] Implement saveNotebook --- src/notebook.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index bca50f21e..28cc27ebc 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -180,7 +180,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } else if (cellType === 'yaml') { if (lines[line].startsWith('---')) { cells.push({ - cellKind: vscode.CellKind.Markdown, + cellKind: vscode.CellKind.Code, source: lines.slice(cellStartLine, line + 1).join('\n'), language: 'yaml', outputs: [], @@ -218,10 +218,26 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode }; } - // The following are dummy implementations not relevant to this example. onDidChangeNotebook = new vscode.EventEmitter().event; async resolveNotebook(): Promise { } - async saveNotebook(document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { } + async saveNotebook(document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { + let content = ''; + for (const cell of document.cells) { + if (cell.cellKind === vscode.CellKind.Markdown) { + content += '\n\n' + cell.document.getText() + '\n\n'; + } else if (cell.cellKind === vscode.CellKind.Code) { + if (cell.language === 'r') { + content += '\n\n```{r}\n' + cell.document.getText() + '\n```\n'; + } else if (cell.language === 'yaml') { + content += '---\n' + cell.document.getText() + '\n---\n'; + } else { + content += '\n\n```{' + cell.language + '}\n' + cell.document.getText() + '\n```\n'; + } + } + } + vscode.workspace.fs.writeFile(document.uri, Buffer.from(content)); + } + async saveNotebookAs(targetResource: vscode.Uri, document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { } async backupNotebook(document: vscode.NotebookDocument, context: vscode.NotebookDocumentBackupContext, cancellation: vscode.CancellationToken): Promise { return { id: '', delete: () => { } }; } async executeCell(document: vscode.NotebookDocument, cell: vscode.NotebookCell) { From ec170d26daf3e1865838c72bc305a053cbfd31cc Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Thu, 13 Aug 2020 11:57:51 +0800 Subject: [PATCH 21/78] Update save notebook --- src/notebook.ts | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index 28cc27ebc..6742d837e 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -218,27 +218,37 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode }; } - onDidChangeNotebook = new vscode.EventEmitter().event; - async resolveNotebook(): Promise { } - async saveNotebook(document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { + async save(targetResource: vscode.Uri, document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { let content = ''; for (const cell of document.cells) { + if (cancellation.isCancellationRequested) { + return; + } if (cell.cellKind === vscode.CellKind.Markdown) { - content += '\n\n' + cell.document.getText() + '\n\n'; + content += cell.document.getText(); } else if (cell.cellKind === vscode.CellKind.Code) { if (cell.language === 'r') { - content += '\n\n```{r}\n' + cell.document.getText() + '\n```\n'; + content += '```{r}\n' + cell.document.getText() + '\n```\n\n'; } else if (cell.language === 'yaml') { content += '---\n' + cell.document.getText() + '\n---\n'; } else { - content += '\n\n```{' + cell.language + '}\n' + cell.document.getText() + '\n```\n'; + content += '```{' + cell.language + '}\n' + cell.document.getText() + '\n```\n\n'; } } } - vscode.workspace.fs.writeFile(document.uri, Buffer.from(content)); + await vscode.workspace.fs.writeFile(document.uri, Buffer.from(content)); + } + + onDidChangeNotebook = new vscode.EventEmitter().event; + async resolveNotebook(): Promise { } + async saveNotebook(document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { + await this.save(document.uri, document, cancellation); + } + + async saveNotebookAs(targetResource: vscode.Uri, document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { + await this.save(targetResource, document, cancellation); } - async saveNotebookAs(targetResource: vscode.Uri, document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { } async backupNotebook(document: vscode.NotebookDocument, context: vscode.NotebookDocumentBackupContext, cancellation: vscode.CancellationToken): Promise { return { id: '', delete: () => { } }; } async executeCell(document: vscode.NotebookDocument, cell: vscode.NotebookCell) { const notebook = this.notebooks.get(document.uri.toString()); From 0b882c917958f8df229c87b4b19f37583e280031 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Thu, 13 Aug 2020 13:11:45 +0800 Subject: [PATCH 22/78] Update notebook --- src/notebook.ts | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index 6742d837e..56bd133b6 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -212,13 +212,13 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } return { - languages: ['r', 'yaml'], + languages: ['r'], metadata: { }, cells: cells, }; } - async save(targetResource: vscode.Uri, document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { + async save(document: vscode.NotebookDocument, targetResource: vscode.Uri, cancellation: vscode.CancellationToken): Promise { let content = ''; for (const cell of document.cells) { if (cancellation.isCancellationRequested) { @@ -236,20 +236,29 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } } } - await vscode.workspace.fs.writeFile(document.uri, Buffer.from(content)); + await vscode.workspace.fs.writeFile(targetResource, Buffer.from(content)); } onDidChangeNotebook = new vscode.EventEmitter().event; + async resolveNotebook(): Promise { } + async saveNotebook(document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { - await this.save(document.uri, document, cancellation); + await this.save(document, document.uri, cancellation); } async saveNotebookAs(targetResource: vscode.Uri, document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { - await this.save(targetResource, document, cancellation); + await this.save(document, targetResource, cancellation); + } + + async backupNotebook(document: vscode.NotebookDocument, context: vscode.NotebookDocumentBackupContext, cancellation: vscode.CancellationToken): Promise { + await this.save(document, context.destination, cancellation); + return { + id: context.destination.toString(), + delete: () => vscode.workspace.fs.delete(context.destination) + }; } - async backupNotebook(document: vscode.NotebookDocument, context: vscode.NotebookDocumentBackupContext, cancellation: vscode.CancellationToken): Promise { return { id: '', delete: () => { } }; } async executeCell(document: vscode.NotebookDocument, cell: vscode.NotebookCell) { const notebook = this.notebooks.get(document.uri.toString()); From c5eb58f929d959949a0b406d79ba78cebcf67078 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Thu, 13 Aug 2020 13:12:52 +0800 Subject: [PATCH 23/78] Update notebook --- src/notebook.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/notebook.ts b/src/notebook.ts index 56bd133b6..f9f6e9eed 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -1,7 +1,7 @@ import * as vscode from 'vscode'; import net = require('net'); import { spawn, ChildProcess } from 'child_process'; -import { dirname, resolve } from 'path'; +import { dirname } from 'path'; import getPort = require('get-port'); class RKernel { From c58ac7ce91e624c5811246de442b4f50bd460400 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Thu, 13 Aug 2020 13:54:02 +0800 Subject: [PATCH 24/78] Update notebook --- src/notebook.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index f9f6e9eed..10b3e480f 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -225,12 +225,12 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode return; } if (cell.cellKind === vscode.CellKind.Markdown) { - content += cell.document.getText(); + content += cell.document.getText() + '\n\n'; } else if (cell.cellKind === vscode.CellKind.Code) { if (cell.language === 'r') { content += '```{r}\n' + cell.document.getText() + '\n```\n\n'; } else if (cell.language === 'yaml') { - content += '---\n' + cell.document.getText() + '\n---\n'; + content += cell.document.getText() + '\n\n'; } else { content += '```{' + cell.language + '}\n' + cell.document.getText() + '\n```\n\n'; } From 435674d9289b8f6539fa511124c39c050cfe0939 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Thu, 13 Aug 2020 17:07:36 +0800 Subject: [PATCH 25/78] Update eval --- src/notebook.ts | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index 10b3e480f..9d7a8dd09 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -117,6 +117,8 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode private disposables: vscode.Disposable[] = []; private readonly notebooks = new Map(); + private runIndex: number = 0; + constructor(kernelScript: string) { this.kernelScript = kernelScript; this.disposables.push( @@ -276,30 +278,28 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode return; } - let output = ''; - let error: Error; - if (notebook) { try { - output = await notebook.eval(cell); + cell.metadata.runState = vscode.NotebookCellRunState.Running; + const start = +new Date(); + cell.metadata.runStartTime = start; + cell.metadata.executionOrder = ++this.runIndex; + const output = await notebook.eval(cell); + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Text, + text: output, + }]; + cell.metadata.runState = vscode.NotebookCellRunState.Success; + cell.metadata.lastRunDuration = +new Date() - start; } catch (e) { - error = e; + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Error, + evalue: e.toString(), + ename: '', + traceback: [], + }]; } } - - if (error) { - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Error, - evalue: error.toString(), - ename: '', - traceback: [], - }]; - } else { - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Text, - text: output, - }]; - } } async executeAllCells(document: vscode.NotebookDocument): Promise { From 53e1ac04b3e885e9dfad0212db1d2c26847f0ec6 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Thu, 13 Aug 2020 17:23:28 +0800 Subject: [PATCH 26/78] Handle error and output --- R/notebook.R | 25 ++++++++++++++++--------- src/notebook.ts | 28 +++++++++++++++++++++------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index c3cb962a6..8526aa8a2 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -18,16 +18,23 @@ local({ tryCatch({ line <- readLines(con, n = 1) request <- jsonlite::fromJSON(line) - cat(sprintf("[%s]\n%s\n", - request$time, request$expr)) - expr <- parse(text = request$expr) - res <- try(eval(expr, globalenv()), silent = TRUE) - str <- list( - type = if (inherits(res, "try-error")) "error" else "output", - result = utils::capture.output(print(res)) + cat(sprintf("[%s]\n%s\n", request$time, request$expr)) + str <- tryCatch({ + expr <- parse(text = request$expr) + out <- eval(expr, globalenv()) + list( + type = "output", + result = paste0(utils::capture.output(print(out)), collapse = "\n") + ) + }, error = function(e) { + list( + type = "error", + result = conditionMessage(e) + ) + } ) - result <- jsonlite::toJSON(str, auto_unbox = TRUE, force = TRUE) - writeLines(result, con) + response <- jsonlite::toJSON(str, auto_unbox = TRUE, force = TRUE) + writeLines(response, con) }, error = function(e) { message(e) }, finally = close(con)) diff --git a/src/notebook.ts b/src/notebook.ts index 9d7a8dd09..34c31d917 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -4,6 +4,11 @@ import { spawn, ChildProcess } from 'child_process'; import { dirname } from 'path'; import getPort = require('get-port'); +interface REvalOutput { + type: "output" | "error"; + result: string; +} + class RKernel { private kernelScript: string; private cwd: string; @@ -52,7 +57,7 @@ class RKernel { await this.start(); } - public async eval(cell: vscode.NotebookCell): Promise { + public async eval(cell: vscode.NotebookCell): Promise { if (this.process) { const client = net.createConnection({ port: this.port }, () => { console.log('connected to server!'); @@ -73,13 +78,17 @@ class RKernel { const response = data.toString(); console.log(response); client.end(); - const output = JSON.parse(response); - const result: string[] = output.result; - resolve(result.join('\n')); + const output: REvalOutput = JSON.parse(response); + resolve(output); }); client.on('error', (err) => { - reject(err.message); + reject({ + type: "error", + result: [ + err.message + ], + }); }); }); } @@ -103,7 +112,7 @@ class RNotebook implements vscode.Disposable { this.kernel.restart(); } - public async eval(cell: vscode.NotebookCell): Promise { + public async eval(cell: vscode.NotebookCell): Promise { await this.kernel.start(); return this.kernel.eval(cell); } @@ -285,9 +294,12 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode cell.metadata.runStartTime = start; cell.metadata.executionOrder = ++this.runIndex; const output = await notebook.eval(cell); + if (output.type === "error") { + throw new Error(output.result); + } cell.outputs = [{ outputKind: vscode.CellOutputKind.Text, - text: output, + text: output.result, }]; cell.metadata.runState = vscode.NotebookCellRunState.Success; cell.metadata.lastRunDuration = +new Date() - start; @@ -298,6 +310,8 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode ename: '', traceback: [], }]; + cell.metadata.runState = vscode.NotebookCellRunState.Error; + cell.metadata.lastRunDuration = undefined; } } } From f3f15554cd1e5379575a5c9230e1d6b79f9e5d5a Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Thu, 13 Aug 2020 17:37:08 +0800 Subject: [PATCH 27/78] Store Rmd chunk header and footer --- src/notebook.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/notebook.ts b/src/notebook.ts index 34c31d917..c179eeb09 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -213,6 +213,10 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode metadata: { editable: true, runnable: true, + custom: { + header: lines[cellStartLine], + footer: lines[line], + } }, }); cellType = 'markdown'; @@ -239,7 +243,13 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode content += cell.document.getText() + '\n\n'; } else if (cell.cellKind === vscode.CellKind.Code) { if (cell.language === 'r') { - content += '```{r}\n' + cell.document.getText() + '\n```\n\n'; + if (cell.metadata.custom === undefined) { + cell.metadata.custom = { + header: '```{r}', + footer: '```' + }; + } + content += cell.metadata.custom.header + '\n' + cell.document.getText() + '\n' + cell.metadata.custom.footer + '\n\n'; } else if (cell.language === 'yaml') { content += cell.document.getText() + '\n\n'; } else { From a716867f4b4f9d0a8d11fb09d2e77de94d600643 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Thu, 13 Aug 2020 18:29:14 +0800 Subject: [PATCH 28/78] Fix lint --- src/notebook.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index c179eeb09..1bcbb1787 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -5,7 +5,7 @@ import { dirname } from 'path'; import getPort = require('get-port'); interface REvalOutput { - type: "output" | "error"; + type: 'output' | 'error'; result: string; } @@ -84,7 +84,7 @@ class RKernel { client.on('error', (err) => { reject({ - type: "error", + type: 'error', result: [ err.message ], @@ -304,7 +304,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode cell.metadata.runStartTime = start; cell.metadata.executionOrder = ++this.runIndex; const output = await notebook.eval(cell); - if (output.type === "error") { + if (output.type === 'error') { throw new Error(output.result); } cell.outputs = [{ From d9da9708e18c5240157d3bf05883c8f15fac9a7b Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Thu, 13 Aug 2020 20:45:35 +0800 Subject: [PATCH 29/78] Update notebook --- src/notebook.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index 1bcbb1787..e06596c81 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -240,7 +240,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode return; } if (cell.cellKind === vscode.CellKind.Markdown) { - content += cell.document.getText() + '\n\n'; + content += cell.document.getText() + '\n'; } else if (cell.cellKind === vscode.CellKind.Code) { if (cell.language === 'r') { if (cell.metadata.custom === undefined) { @@ -249,11 +249,11 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode footer: '```' }; } - content += cell.metadata.custom.header + '\n' + cell.document.getText() + '\n' + cell.metadata.custom.footer + '\n\n'; + content += cell.metadata.custom.header + '\n' + cell.document.getText() + '\n' + cell.metadata.custom.footer + '\n'; } else if (cell.language === 'yaml') { content += cell.document.getText() + '\n\n'; } else { - content += '```{' + cell.language + '}\n' + cell.document.getText() + '\n```\n\n'; + content += '```{' + cell.language + '}\n' + cell.document.getText() + '\n```\n'; } } } From 7c8741cacf8fbe78bd067394b836b493a64f80be Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Sun, 16 Aug 2020 08:41:16 +0800 Subject: [PATCH 30/78] Update notebook --- R/notebook.R | 19 ++++++++++++++----- src/notebook.ts | 2 +- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index 8526aa8a2..b4832a4d0 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -21,11 +21,20 @@ local({ cat(sprintf("[%s]\n%s\n", request$time, request$expr)) str <- tryCatch({ expr <- parse(text = request$expr) - out <- eval(expr, globalenv()) - list( - type = "output", - result = paste0(utils::capture.output(print(out)), collapse = "\n") - ) + out <- withVisible(eval(expr, globalenv())) + if (out$visible) { + print_text <- utils::capture.output(print(out$value)) + res <- list( + type = "text", + result = paste0(print_text, collapse = "\n") + ) + } else { + res <- list( + type = "text", + result = "" + ) + } + res }, error = function(e) { list( type = "error", diff --git a/src/notebook.ts b/src/notebook.ts index e06596c81..ac229ef81 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -5,7 +5,7 @@ import { dirname } from 'path'; import getPort = require('get-port'); interface REvalOutput { - type: 'output' | 'error'; + type: 'text' | 'plot' | 'viewer' | 'browser' | 'error'; result: string; } From bf5665c9f8550fced1f61f55917cc23cc3807dd1 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Sun, 16 Aug 2020 09:15:59 +0800 Subject: [PATCH 31/78] Add initial capability of plot --- R/notebook.R | 31 ++++++++++++++++++++++++++++++- src/notebook.ts | 26 ++++++++++++++++++++------ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index b4832a4d0..c021aa4ea 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -7,6 +7,25 @@ local({ eval(expr, env) } + plot_file <- file.path(tempdir(), "plot.png") + null_dev_id <- c(pdf = 2L) + null_dev_size <- c(7 + pi, 7 + pi) + + options( + device = function(...) { + pdf(NULL, + width = null_dev_size[[1L]], + height = null_dev_size[[2L]], + bg = "white") + dev.control(displaylist = "enable") + } + ) + + check_null_dev <- function() { + identical(dev.cur(), null_dev_id) && + identical(dev.size(), null_dev_size) + } + ls.str(env) while (TRUE) { con <- try(socketConnection(host = "127.0.0.1", port = env$port, @@ -22,7 +41,17 @@ local({ str <- tryCatch({ expr <- parse(text = request$expr) out <- withVisible(eval(expr, globalenv())) - if (out$visible) { + if (check_null_dev()) { + record <- recordPlot() + png(filename = plot_file) + replayPlot(record) + dev.off() + dev.off() + res <- list( + type = "plot", + result = plot_file + ) + } else if (out$visible) { print_text <- utils::capture.output(print(out$value)) res <- list( type = "text", diff --git a/src/notebook.ts b/src/notebook.ts index ac229ef81..ab83135ef 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -3,6 +3,7 @@ import net = require('net'); import { spawn, ChildProcess } from 'child_process'; import { dirname } from 'path'; import getPort = require('get-port'); +import * as fs from 'fs'; interface REvalOutput { type: 'text' | 'plot' | 'viewer' | 'browser' | 'error'; @@ -304,13 +305,26 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode cell.metadata.runStartTime = start; cell.metadata.executionOrder = ++this.runIndex; const output = await notebook.eval(cell); - if (output.type === 'error') { - throw new Error(output.result); + switch (output.type) { + case 'text': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Text, + text: output.result, + }]; + break; + case 'plot': + const plotData = fs.readFileSync(output.result); + const buffer = new Buffer(plotData).toString('base64'); + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + 'image/png': buffer, + } + }]; + break; + case 'error': + throw new Error(output.result); } - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Text, - text: output.result, - }]; cell.metadata.runState = vscode.NotebookCellRunState.Success; cell.metadata.lastRunDuration = +new Date() - start; } catch (e) { From 42133812ed0994e0fbc8a7cd35e1c6abbb971ac6 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Sun, 16 Aug 2020 09:18:35 +0800 Subject: [PATCH 32/78] Update notebook --- src/notebook.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index ab83135ef..9231c15e2 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -313,12 +313,10 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode }]; break; case 'plot': - const plotData = fs.readFileSync(output.result); - const buffer = new Buffer(plotData).toString('base64'); cell.outputs = [{ outputKind: vscode.CellOutputKind.Rich, data: { - 'image/png': buffer, + 'image/png': fs.readFileSync(output.result).toString('base64'), } }]; break; From d588e419acf6358bcba08497350797e29117423c Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Sun, 16 Aug 2020 09:19:22 +0800 Subject: [PATCH 33/78] Update notebook --- src/notebook.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/notebook.ts b/src/notebook.ts index 9231c15e2..8d25fa32d 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -316,7 +316,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode cell.outputs = [{ outputKind: vscode.CellOutputKind.Rich, data: { - 'image/png': fs.readFileSync(output.result).toString('base64'), + 'image/png': fs.readFileSync(output.result, 'base64'), } }]; break; From c2be46e030879accd5d275860fc6c9779cd57a89 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 17 Aug 2020 09:23:39 +0800 Subject: [PATCH 34/78] Use svglite for plot --- R/notebook.R | 4 ++-- src/notebook.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index c021aa4ea..def3d4cd1 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -7,7 +7,7 @@ local({ eval(expr, env) } - plot_file <- file.path(tempdir(), "plot.png") + plot_file <- file.path(tempdir(), "plot") null_dev_id <- c(pdf = 2L) null_dev_size <- c(7 + pi, 7 + pi) @@ -43,7 +43,7 @@ local({ out <- withVisible(eval(expr, globalenv())) if (check_null_dev()) { record <- recordPlot() - png(filename = plot_file) + svglite::svglite(plot_file, width = 10, height = 6) replayPlot(record) dev.off() dev.off() diff --git a/src/notebook.ts b/src/notebook.ts index 8d25fa32d..6e74982f6 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -316,7 +316,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode cell.outputs = [{ outputKind: vscode.CellOutputKind.Rich, data: { - 'image/png': fs.readFileSync(output.result, 'base64'), + 'image/svg+xml': fs.readFileSync(output.result).toString(), } }]; break; From 9526454f8065d681e7a2b0f6da33c629e9db59e2 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 17 Aug 2020 11:53:18 +0800 Subject: [PATCH 35/78] Update svglite usage --- R/notebook.R | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index def3d4cd1..11cccbe5e 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -1,5 +1,6 @@ local({ requireNamespace("jsonlite") + requireNamespace("svglite") args <- commandArgs(trailingOnly = TRUE) exprs <- parse(text = args, keep.source = FALSE) env <- new.env() @@ -7,7 +8,6 @@ local({ eval(expr, env) } - plot_file <- file.path(tempdir(), "plot") null_dev_id <- c(pdf = 2L) null_dev_size <- c(7 + pi, 7 + pi) @@ -38,15 +38,16 @@ local({ line <- readLines(con, n = 1) request <- jsonlite::fromJSON(line) cat(sprintf("[%s]\n%s\n", request$time, request$expr)) + res <- list() str <- tryCatch({ expr <- parse(text = request$expr) out <- withVisible(eval(expr, globalenv())) if (check_null_dev()) { record <- recordPlot() - svglite::svglite(plot_file, width = 10, height = 6) + plot_file <- tempfile(fileext = ".svg") + svglite::svglite(plot_file, width = 12, height = 8) replayPlot(record) - dev.off() - dev.off() + graphics.off() res <- list( type = "plot", result = plot_file From 9fb31ab3f09e13f954df33603bba5637dea7c8be Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 17 Aug 2020 12:27:56 +0800 Subject: [PATCH 36/78] Update notebook --- R/notebook.R | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index 11cccbe5e..02a2c57fc 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -38,10 +38,10 @@ local({ line <- readLines(con, n = 1) request <- jsonlite::fromJSON(line) cat(sprintf("[%s]\n%s\n", request$time, request$expr)) - res <- list() str <- tryCatch({ expr <- parse(text = request$expr) out <- withVisible(eval(expr, globalenv())) + text <- utils::capture.output(print(out$value)) if (check_null_dev()) { record <- recordPlot() plot_file <- tempfile(fileext = ".svg") @@ -53,10 +53,9 @@ local({ result = plot_file ) } else if (out$visible) { - print_text <- utils::capture.output(print(out$value)) res <- list( type = "text", - result = paste0(print_text, collapse = "\n") + result = paste0(text, collapse = "\n") ) } else { res <- list( From 41f52832b9268e69122e31778539a5da8ccbeb74 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 17 Aug 2020 16:13:00 +0800 Subject: [PATCH 37/78] Capture viewer, page_viewer, and browser request --- R/notebook.R | 28 +++++++++++++++++++++++++++- src/notebook.ts | 16 ++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/R/notebook.R b/R/notebook.R index 02a2c57fc..bd44d214a 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -10,6 +10,8 @@ local({ null_dev_id <- c(pdf = 2L) null_dev_size <- c(7 + pi, 7 + pi) + viewer_file <- NULL + browser_url <- NULL options( device = function(...) { @@ -18,6 +20,18 @@ local({ height = null_dev_size[[2L]], bg = "white") dev.control(displaylist = "enable") + }, + viewer = function(url, ...) { + message("viewer: ", url) + viewer_file <<- url + }, + page_viewer = function(url, ...) { + message("page_viewer: ", url) + viewer_file <<- url + }, + browser = function(url, ...) { + message("browser: ", url) + browser_url <<- url } ) @@ -38,10 +52,12 @@ local({ line <- readLines(con, n = 1) request <- jsonlite::fromJSON(line) cat(sprintf("[%s]\n%s\n", request$time, request$expr)) + viewer_file <- NULL + browser_url <- NULL str <- tryCatch({ expr <- parse(text = request$expr) out <- withVisible(eval(expr, globalenv())) - text <- utils::capture.output(print(out$value)) + text <- utils::capture.output(print(out$value, view = TRUE)) if (check_null_dev()) { record <- recordPlot() plot_file <- tempfile(fileext = ".svg") @@ -52,6 +68,16 @@ local({ type = "plot", result = plot_file ) + } else if (!is.null(viewer_file)) { + res <- list( + type = "viewer", + result = viewer_file + ) + } else if (!is.null(browser_url)) { + res <- list( + type = "browser", + result = browser_url + ) } else if (out$visible) { res <- list( type = "text", diff --git a/src/notebook.ts b/src/notebook.ts index 6e74982f6..587d14c58 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -320,6 +320,22 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } }]; break; + case 'viewer': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + 'application/json': output, + } + }]; + break; + case 'browser': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + 'application/json': output, + } + }]; + break; case 'error': throw new Error(output.result); } From 503d242746a2c9684d53bf25d235c51421a9dd8a Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Wed, 26 Aug 2020 16:19:42 +0800 Subject: [PATCH 38/78] Initialize cell metadata --- src/notebook.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/notebook.ts b/src/notebook.ts index 587d14c58..08e0c0369 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -300,6 +300,10 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode if (notebook) { try { + if (cell.metadata === undefined) { + cell.metadata = {}; + } + cell.metadata.runState = vscode.NotebookCellRunState.Running; const start = +new Date(); cell.metadata.runStartTime = start; From 5dd3a91e7e723bce990c4ee24326a88ac801a14e Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Wed, 26 Aug 2020 17:08:27 +0800 Subject: [PATCH 39/78] Update vscode.proposed.d.ts --- vscode.proposed.d.ts | 362 ++++++++++++++++++++----------------------- 1 file changed, 164 insertions(+), 198 deletions(-) diff --git a/vscode.proposed.d.ts b/vscode.proposed.d.ts index e97105984..6ff3c4e25 100644 --- a/vscode.proposed.d.ts +++ b/vscode.proposed.d.ts @@ -737,21 +737,6 @@ declare module 'vscode' { //#region debug - export interface DebugSessionOptions { - /** - * Controls whether this session should run without debugging, thus ignoring breakpoints. - * When this property is not specified, the value from the parent session (if there is one) is used. - */ - noDebug?: boolean; - - /** - * Controls if the debug session's parent session is shown in the CALL STACK view even if it has only a single child. - * By default, the debug session will never hide its parent. - * If compact is true, debug sessions with a single child are hidden in the CALL STACK view to make the tree more compact. - */ - compact?: boolean; - } - // deprecated debug API export interface DebugConfigurationProvider { @@ -762,15 +747,6 @@ declare module 'vscode' { debugAdapterExecutable?(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult; } - export namespace debug { - - /** - * Stop the given debug session or stop all debug sessions if session is omitted. - * @param session The [debug session](#DebugSession) to stop; if omitted all sessions are stopped. - */ - export function stopDebugging(session?: DebugSession): Thenable; - } - //#endregion //#region LogLevel: https://github.com/microsoft/vscode/issues/85992 @@ -927,93 +903,6 @@ declare module 'vscode' { //#endregion - //#region Terminal link handlers https://github.com/microsoft/vscode/issues/91606 - - export namespace window { - /** - * Register a [TerminalLinkHandler](#TerminalLinkHandler) that can be used to intercept and - * handle links that are activated within terminals. - * @param handler The link handler being registered. - * @return A disposable that unregisters the link handler. - */ - export function registerTerminalLinkHandler(handler: TerminalLinkHandler): Disposable; - } - - /** - * Describes how to handle terminal links. - */ - export interface TerminalLinkHandler { - /** - * Handles a link that is activated within the terminal. - * - * @param terminal The terminal the link was activated on. - * @param link The text of the link activated. - * @return Whether the link was handled, if the link was handled this link will not be - * considered by any other extension or by the default built-in link handler. - */ - handleLink(terminal: Terminal, link: string): ProviderResult; - } - - //#endregion - - //#region Terminal link provider https://github.com/microsoft/vscode/issues/91606 - - export namespace window { - export function registerTerminalLinkProvider(provider: TerminalLinkProvider): Disposable; - } - - export interface TerminalLinkContext { - /** - * This is the text from the unwrapped line in the terminal. - */ - line: string; - - /** - * The terminal the link belongs to. - */ - terminal: Terminal; - } - - export interface TerminalLinkProvider { - /** - * Provide terminal links for the given context. Note that this can be called multiple times - * even before previous calls resolve, make sure to not share global objects (eg. `RegExp`) - * that could have problems when asynchronous usage may overlap. - * @param context Information about what links are being provided for. - * @param token A cancellation token. - * @return A list of terminal links for the given line. - */ - provideTerminalLinks(context: TerminalLinkContext, token: CancellationToken): ProviderResult - - /** - * Handle an activated terminal link. - */ - handleTerminalLink(link: T): ProviderResult; - } - - export interface TerminalLink { - /** - * The start index of the link on [TerminalLinkContext.line](#TerminalLinkContext.line]. - */ - startIndex: number; - - /** - * The length of the link on [TerminalLinkContext.line](#TerminalLinkContext.line] - */ - length: number; - - /** - * The tooltip text when you hover over this link. - * - * If a tooltip is provided, is will be displayed in a string that includes instructions on - * how to trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary - * depending on OS, user settings, and localization. - */ - tooltip?: string; - } - - //#endregion - //#region @jrieken -> exclusive document filters export interface DocumentFilter { @@ -1074,7 +963,6 @@ declare module 'vscode' { } //#endregion - //#region CustomExecution: https://github.com/microsoft/vscode/issues/81007 /** * A task to execute */ @@ -1082,19 +970,6 @@ declare module 'vscode' { detail?: string; } - export class CustomExecution2 extends CustomExecution { - /** - * Constructs a CustomExecution task object. The callback will be executed the task is run, at which point the - * extension should return the Pseudoterminal it will "run in". The task should wait to do further execution until - * [Pseudoterminal.open](#Pseudoterminal.open) is called. Task cancellation should be handled using - * [Pseudoterminal.close](#Pseudoterminal.close). When the task is complete fire - * [Pseudoterminal.onDidClose](#Pseudoterminal.onDidClose). - * @param callback The callback that will be called when the task is started by a user. - */ - constructor(callback: (resolvedDefinition?: TaskDefinition) => Thenable); - } - //#endregion - //#region Task presentation group: https://github.com/microsoft/vscode/issues/47265 export interface TaskPresentationOptions { /** @@ -1171,9 +1046,11 @@ declare module 'vscode' { * @param position The position at which the command was invoked. * @param token A cancellation token. * @return A list of ranges that can be live-renamed togehter. The ranges must have - * identical length and contain identical text content. The ranges cannot overlap. + * identical length and contain identical text content. The ranges cannot overlap. Optional a word pattern + * that overrides the word pattern defined when registering the provider. Live rename stops as soon as the renamed content + * no longer matches the word pattern. */ - provideOnTypeRenameRanges(document: TextDocument, position: Position, token: CancellationToken): ProviderResult; + provideOnTypeRenameRanges(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<{ ranges: Range[]; wordPattern?: RegExp; }>; } namespace languages { @@ -1186,10 +1063,10 @@ declare module 'vscode' { * * @param selector A selector that defines the documents this provider is applicable to. * @param provider An on type rename provider. - * @param stopPattern Stop on type renaming when input text matches the regular expression. Defaults to `^\s`. + * @param wordPattern Word pattern for this provider. * @return A [disposable](#Disposable) that unregisters this provider when being disposed. */ - export function registerOnTypeRenameProvider(selector: DocumentSelector, provider: OnTypeRenameProvider, stopPattern?: RegExp): Disposable; + export function registerOnTypeRenameProvider(selector: DocumentSelector, provider: OnTypeRenameProvider, wordPattern?: RegExp): Disposable; } //#endregion @@ -1377,7 +1254,7 @@ declare module 'vscode' { readonly uri: Uri; readonly cellKind: CellKind; readonly document: TextDocument; - language: string; + readonly language: string; outputs: CellOutput[]; metadata: NotebookCellMetadata; } @@ -1428,11 +1305,12 @@ declare module 'vscode' { export interface NotebookDocument { readonly uri: Uri; + readonly version: number; readonly fileName: string; readonly viewType: string; readonly isDirty: boolean; readonly isUntitled: boolean; - readonly cells: NotebookCell[]; + readonly cells: ReadonlyArray; languages: string[]; displayOrder?: GlobPattern[]; metadata: NotebookDocumentMetadata; @@ -1458,7 +1336,14 @@ declare module 'vscode' { } export interface NotebookEditorCellEdit { + + replaceCells(from: number, to: number, cells: NotebookCellData[]): void; + replaceOutputs(index: number, outputs: CellOutput[]): void; + replaceMetadata(index: number, metadata: NotebookCellMetadata): void; + + /** @deprecated */ insert(index: number, content: string | string[], language: string, type: CellKind, outputs: CellOutput[], metadata: NotebookCellMetadata | undefined): void; + /** @deprecated */ delete(index: number): void; } @@ -1476,7 +1361,7 @@ declare module 'vscode' { /** * The column in which this editor shows. */ - viewColumn?: ViewColumn; + readonly viewColumn?: ViewColumn; /** * Whether the panel is active (focused by the user). @@ -1529,31 +1414,6 @@ declare module 'vscode' { outputId: string; } - export interface NotebookOutputRenderer { - /** - * - * @returns HTML fragment. We can probably return `CellOutput` instead of string ? - * - */ - render(document: NotebookDocument, request: NotebookRenderRequest): string; - - /** - * Call before HTML from the renderer is executed, and will be called for - * every editor associated with notebook documents where the renderer - * is or was used. - * - * The communication object will only send and receive messages to the - * render API, retrieved via `acquireNotebookRendererApi`, acquired with - * this specific renderer's ID. - * - * If you need to keep an association between the communication object - * and the document for use in the `render()` method, you can use a WeakMap. - */ - resolveNotebook?(document: NotebookDocument, communication: NotebookCommunication): void; - - readonly preloads?: Uri[]; - } - export interface NotebookCellsChangeData { readonly start: number; readonly deletedCount: number; @@ -1607,9 +1467,9 @@ declare module 'vscode' { export interface NotebookCellData { readonly cellKind: CellKind; readonly source: string; - language: string; - outputs: CellOutput[]; - metadata: NotebookCellMetadata; + readonly language: string; + readonly outputs: CellOutput[]; + readonly metadata: NotebookCellMetadata | undefined; } export interface NotebookData { @@ -1727,8 +1587,6 @@ declare module 'vscode' { saveNotebookAs(targetResource: Uri, document: NotebookDocument, cancellation: CancellationToken): Promise; readonly onDidChangeNotebook: Event; backupNotebook(document: NotebookDocument, context: NotebookDocumentBackupContext, cancellation: CancellationToken): Promise; - - kernel?: NotebookKernel; } export interface NotebookKernel { @@ -1772,12 +1630,6 @@ declare module 'vscode' { kernel: NotebookKernel ): Disposable; - export function registerNotebookOutputRenderer( - id: string, - outputSelector: NotebookOutputSelector, - renderer: NotebookOutputRenderer - ): Disposable; - export const onDidOpenNotebookDocument: Event; export const onDidCloseNotebookDocument: Event; export const onDidSaveNotebookDocument: Event; @@ -2046,59 +1898,173 @@ declare module 'vscode' { } //#endregion - //#region https://github.com/microsoft/vscode/issues/101857 + + //#region https://github.com/microsoft/vscode/issues/104436 + + export enum ExtensionRuntime { + /** + * The extension is running in a NodeJS extension host. Runtime access to NodeJS APIs is available. + */ + Node = 1, + /** + * The extension is running in a Webworker extension host. Runtime access is limited to Webworker APIs. + */ + Webworker = 2 + } export interface ExtensionContext { + readonly extensionRuntime: ExtensionRuntime; + } + + //#endregion + + + //#region https://github.com/microsoft/vscode/issues/102091 + + export interface TextDocument { + + /** + * The [notebook](#NotebookDocument) that contains this document as a notebook cell or `undefined` when + * the document is not contained by a notebook (this should be the more frequent case). + */ + notebook: NotebookDocument | undefined; + } + //#endregion + + + //#region https://github.com/microsoft/vscode/issues/46585 + /** + * A webview based view. + */ + export interface WebviewView { /** - * The uri of a directory in which the extension can create log files. - * The directory might not exist on disk and creation is up to the extension. However, - * the parent directory is guaranteed to be existent. + * Identifies the type of the webview view, such as `'hexEditor.dataView'`. + */ + readonly viewType: string; + + /** + * The underlying webview for the view. + */ + readonly webview: Webview; + + /** + * View title displayed in the UI. * - * @see [`workspace.fs`](#FileSystem) for how to read and write files and folders from - * an uri. + * The view title is initially taken from the extension `package.json` contribution. */ - readonly logUri: Uri; + title?: string; /** - * The uri of a workspace specific directory in which the extension - * can store private state. The directory might not exist and creation is - * up to the extension. However, the parent directory is guaranteed to be existent. - * The value is `undefined` when no workspace nor folder has been opened. + * Event fired when the view is disposed. * - * Use [`workspaceState`](#ExtensionContext.workspaceState) or - * [`globalState`](#ExtensionContext.globalState) to store key value data. + * Views are disposed of in a few cases: * - * @see [`workspace.fs`](#FileSystem) for how to read and write files and folders from - * an uri. + * - When a view is collapsed and `retainContextWhenHidden` has not been set. + * - When a view is hidden by a user. + * + * Trying to use the view after it has been disposed throws an exception. */ - readonly storageUri: Uri | undefined; + readonly onDidDispose: Event; /** - * The uri of a directory in which the extension can store global state. - * The directory might not exist on disk and creation is - * up to the extension. However, the parent directory is guaranteed to be existent. + * Tracks if the webview is currently visible. * - * Use [`globalState`](#ExtensionContext.globalState) to store key value data. - * - * @see [`workspace.fs`](#FileSystem) for how to read and write files and folders from - * an uri. + * Views are visible when they are on the screen and expanded. */ - readonly globalStorageUri: Uri; + readonly visible: boolean; /** - * @deprecated Use [logUri](#ExtensionContext.logUri) instead. + * Event fired when the visibility of the view changes */ - readonly logPath: string; + readonly onDidChangeVisibility: Event; + } + + interface WebviewViewResolveContext { /** - * @deprecated Use [storagePath](#ExtensionContent.storageUri) instead. + * Persisted state from the webview content. + * + * To save resources, VS Code normally deallocates webview views that are not visible. For example, if the user + * collapse a view or switching to another top level activity, the underlying webview document is deallocates. + * + * You can prevent this behavior by setting `retainContextWhenHidden` in the `WebviewOptions`. However this + * increases resource usage and should be avoided wherever possible. Instead, you can use persisted state to + * save off a webview's state so that it can be quickly recreated as needed. + * + * To save off a persisted state, inside the webview call `acquireVsCodeApi().setState()` with + * any json serializable object. To restore the state again, call `getState()`. For example: + * + * ```js + * // Within the webview + * const vscode = acquireVsCodeApi(); + * + * // Get existing state + * const oldState = vscode.getState() || { value: 0 }; + * + * // Update state + * setState({ value: oldState.value + 1 }) + * ``` + * + * VS Code ensures that the persisted state is saved correctly when a webview is hidden and across + * editor restarts. */ - readonly storagePath: string | undefined; + readonly state: T | undefined; + } + + /** + * Provider for creating `WebviewView` elements. + */ + export interface WebviewViewProvider { /** - * @deprecated Use [globalStoragePath](#ExtensionContent.globalStorageUri) instead. + * Revolves a webview view. + * + * `resolveWebviewView` is called when a view first becomes visible. This may happen when the view is + * first loaded or when the user hides and then shows a view again. + * + * @param webviewView Webview panel to restore. The serializer should take ownership of this panel. The + * provider must set the webview's `.html` and hook up all webview events it is interested in. + * @param context Additional metadata about the view being resolved. + * @param token Cancellation token indicating that the view being provided is no longer needed. + * + * @return Optional thenable indicating that the view has been fully resolved. */ - readonly globalStoragePath: string; + resolveWebviewView(webviewView: WebviewView, context: WebviewViewResolveContext, token: CancellationToken): Thenable | void; } + namespace window { + /** + * Register a new provider for webview views. + * + * @param viewId Unique id of the view. This should match the `id` from the + * `views` contribution in the package.json. + * @param provider Provider for the webview views. + * + * @return Disposable that unregisters the provider. + */ + export function registerWebviewViewProvider(viewId: string, provider: WebviewViewProvider, options?: { + /** + * Content settings for the webview created for this view. + */ + readonly webviewOptions?: { + /** + * Controls if the webview panel's content (iframe) is kept around even when the panel + * is no longer visible. + * + * Normally the webview's html context is created when the panel becomes visible + * and destroyed when it is hidden. Extensions that have complex state + * or UI can set the `retainContextWhenHidden` to make VS Code keep the webview + * context around, even when the webview moves to a background tab. When a webview using + * `retainContextWhenHidden` becomes hidden, its scripts and other dynamic content are suspended. + * When the panel becomes visible again, the context is automatically restored + * in the exact same state it was in originally. You cannot send messages to a + * hidden webview, even with `retainContextWhenHidden` enabled. + * + * `retainContextWhenHidden` has a high memory overhead and should only be used if + * your panel's context cannot be quickly saved and restored. + */ + readonly retainContextWhenHidden?: boolean; + }; + }): Disposable; + } //#endregion } From 3e517d95354b2090b26d4868f063e1ee6fb9b0bc Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Wed, 26 Aug 2020 17:57:04 +0800 Subject: [PATCH 40/78] Refine notebook --- src/notebook.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index 08e0c0369..45f11a506 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -44,6 +44,8 @@ class RKernel { console.log(`R exited with code ${code}`); }); this.process = childProcess; + + return new Promise((resolve) => setTimeout(resolve, 500)); } public stop() { @@ -60,30 +62,31 @@ class RKernel { public async eval(cell: vscode.NotebookCell): Promise { if (this.process) { - const client = net.createConnection({ port: this.port }, () => { - console.log('connected to server!'); + const client = net.createConnection({ host: '127.0.0.1', port: this.port }, () => { + console.log(`uri: ${cell.uri}, connect`); const request = JSON.stringify({ time: Date.now(), expr: cell.document.getText(), - }).concat('\n'); - console.log(`Send: ${request}`); + }); + console.log(`uri: ${cell.uri}, write: ${request}`); client.write(request); }); client.on('end', () => { - console.log('disconnected from server'); + console.log(`uri: ${cell.uri}, end`); }); return new Promise((resolve, reject) => { client.on('data', (data) => { const response = data.toString(); - console.log(response); + console.log(`uri: ${cell.uri}, data: ${response}`); client.end(); const output: REvalOutput = JSON.parse(response); resolve(output); }); client.on('error', (err) => { + console.log(`uri: ${cell.uri}, error: ${err.name}, ${err.message}`); reject({ type: 'error', result: [ @@ -309,6 +312,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode cell.metadata.runStartTime = start; cell.metadata.executionOrder = ++this.runIndex; const output = await notebook.eval(cell); + console.log(`uri: ${cell.uri}, output.type: ${output.type}, output.result: ${output.result}`); switch (output.type) { case 'text': cell.outputs = [{ @@ -340,7 +344,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } }]; break; - case 'error': + case 'error': throw new Error(output.result); } cell.metadata.runState = vscode.NotebookCellRunState.Success; From abf9db8932ee0255fb9a14428632f631f4fd529a Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Wed, 26 Aug 2020 22:38:19 +0800 Subject: [PATCH 41/78] Fix request --- src/notebook.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/notebook.ts b/src/notebook.ts index 45f11a506..0f74b6f8f 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -67,7 +67,7 @@ class RKernel { const request = JSON.stringify({ time: Date.now(), expr: cell.document.getText(), - }); + }).concat('\n'); console.log(`uri: ${cell.uri}, write: ${request}`); client.write(request); }); From b45a89f3277b90db09689cc0f821794acd50af03 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Wed, 26 Aug 2020 23:46:41 +0800 Subject: [PATCH 42/78] Update notebook --- src/notebook.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/notebook.ts b/src/notebook.ts index 0f74b6f8f..4a0887218 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -324,7 +324,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode cell.outputs = [{ outputKind: vscode.CellOutputKind.Rich, data: { - 'image/svg+xml': fs.readFileSync(output.result).toString(), + 'image/svg+xml': (await vscode.workspace.fs.readFile(vscode.Uri.parse(output.result))).toString(), } }]; break; From 2c3ae3b37b0081307390d6aa8f9ca6575fd12ed5 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Thu, 27 Aug 2020 11:16:03 +0800 Subject: [PATCH 43/78] Update vscode.proposed.d.ts --- vscode.proposed.d.ts | 54 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/vscode.proposed.d.ts b/vscode.proposed.d.ts index 6ff3c4e25..ba6a5453a 100644 --- a/vscode.proposed.d.ts +++ b/vscode.proposed.d.ts @@ -1613,10 +1613,51 @@ declare module 'vscode' { resolveKernel?(kernel: T, document: NotebookDocument, webview: NotebookCommunication, token: CancellationToken): ProviderResult; } + /** + * Represents the alignment of status bar items. + */ + export enum NotebookCellStatusBarAlignment { + + /** + * Aligned to the left side. + */ + Left = 1, + + /** + * Aligned to the right side. + */ + Right = 2 + } + + export interface NotebookCellStatusBarItem { + readonly cell: NotebookCell; + readonly alignment: NotebookCellStatusBarAlignment; + readonly priority?: number; + text: string; + tooltip: string | undefined; + command: string | Command | undefined; + accessibilityInformation?: AccessibilityInformation; + show(): void; + hide(): void; + dispose(): void; + } + export namespace notebook { export function registerNotebookContentProvider( notebookType: string, - provider: NotebookContentProvider + provider: NotebookContentProvider, + options?: { + /** + * Controls if outputs change will trigger notebook document content change and if it will be used in the diff editor + * Default to false. If the content provider doesn't persisit the outputs in the file document, this should be set to true. + */ + transientOutputs: boolean; + /** + * Controls if a meetadata property change will trigger notebook document content change and if it will be used in the diff editor + * Default to false. If the content provider doesn't persisit a metadata property in the file document, it should be set to true. + */ + transientMetadata: { [K in keyof NotebookCellMetadata]?: boolean } + } ): Disposable; export function registerNotebookKernelProvider( @@ -1658,6 +1699,17 @@ declare module 'vscode' { export function createConcatTextDocument(notebook: NotebookDocument, selector?: DocumentSelector): NotebookConcatTextDocument; export const onDidChangeActiveNotebookKernel: Event<{ document: NotebookDocument, kernel: NotebookKernel | undefined }>; + + /** + * Creates a notebook cell status bar [item](#NotebookCellStatusBarItem). + * It will be disposed automatically when the notebook document is closed or the cell is deleted. + * + * @param cell The cell on which this item should be shown. + * @param alignment The alignment of the item. + * @param priority The priority of the item. Higher values mean the item should be shown more to the left. + * @return A new status bar item. + */ + export function createCellStatusBarItem(cell: NotebookCell, alignment?: NotebookCellStatusBarAlignment, priority?: number): NotebookCellStatusBarItem; } //#endregion From 6027f4bcc740d19ef928e56d69a139aec8cbcc14 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Thu, 27 Aug 2020 11:34:44 +0800 Subject: [PATCH 44/78] Update logging in notebook.R --- R/notebook.R | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index bd44d214a..254a8513d 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -13,6 +13,11 @@ local({ viewer_file <- NULL browser_url <- NULL + write_log <- function(...) { + cat("[", format(Sys.time(), "%Y-%m-%d %H:%M:%OS3"), "] ", + ..., "\n", sep = "") + } + options( device = function(...) { pdf(NULL, @@ -22,15 +27,15 @@ local({ dev.control(displaylist = "enable") }, viewer = function(url, ...) { - message("viewer: ", url) + write_log("viewer: ", url) viewer_file <<- url }, page_viewer = function(url, ...) { - message("page_viewer: ", url) + write_log("page_viewer: ", url) viewer_file <<- url }, browser = function(url, ...) { - message("browser: ", url) + write_log("browser: ", url) browser_url <<- url } ) @@ -42,6 +47,7 @@ local({ ls.str(env) while (TRUE) { + write_log("Listening on port: ", env$port) con <- try(socketConnection(host = "127.0.0.1", port = env$port, blocking = TRUE, server = TRUE, open = "r+"), silent = TRUE) @@ -50,8 +56,8 @@ local({ } else { tryCatch({ line <- readLines(con, n = 1) + write_log(line) request <- jsonlite::fromJSON(line) - cat(sprintf("[%s]\n%s\n", request$time, request$expr)) viewer_file <- NULL browser_url <- NULL str <- tryCatch({ From f483aa60133b45ed6b75382440cf9e3dab9340c7 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Fri, 28 Aug 2020 00:03:28 +0800 Subject: [PATCH 45/78] Register R kernel --- src/notebook.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/notebook.ts b/src/notebook.ts index 4a0887218..b1b094e54 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -124,7 +124,7 @@ class RNotebook implements vscode.Disposable { export class RNotebookProvider implements vscode.NotebookContentProvider, vscode.NotebookKernel { public label = 'R Kernel'; - public kernel = this; + // public kernel = this; private kernelScript: string; private disposables: vscode.Disposable[] = []; @@ -135,6 +135,13 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode constructor(kernelScript: string) { this.kernelScript = kernelScript; this.disposables.push( + vscode.notebook.registerNotebookKernelProvider({ + viewType: 'r' + }, { + provideKernels: () => { + return [this]; + } + }), vscode.notebook.onDidOpenNotebookDocument(document => { const docKey = document.uri.toString(); if (!this.notebooks.has(docKey)) { From c2a8afeeeb1080a658ce2f7add9cadf0e2fc3264 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Fri, 28 Aug 2020 00:14:55 +0800 Subject: [PATCH 46/78] Fix kernel viewType --- src/notebook.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/notebook.ts b/src/notebook.ts index b1b094e54..cad2adbba 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -136,7 +136,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode this.kernelScript = kernelScript; this.disposables.push( vscode.notebook.registerNotebookKernelProvider({ - viewType: 'r' + viewType: 'r-notebook' }, { provideKernels: () => { return [this]; From c9cd51c48eae9a69cc3851c414e201e4d31b45b0 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Sun, 30 Aug 2020 12:15:47 +0800 Subject: [PATCH 47/78] Fix reading cells from rmd --- src/notebook.ts | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index cad2adbba..a3875b46b 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -175,29 +175,33 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode cellType = 'yaml'; cellStartLine = line; } else if (lines[line].startsWith('```{r')) { - cells.push({ - cellKind: vscode.CellKind.Markdown, - source: lines.slice(cellStartLine, line).join('\n'), - language: 'markdown', - outputs: [], - metadata: { - editable: true, - runnable: false, - }, - }); + if (line > cellStartLine) { + cells.push({ + cellKind: vscode.CellKind.Markdown, + source: lines.slice(cellStartLine, line).join('\n'), + language: 'markdown', + outputs: [], + metadata: { + editable: true, + runnable: false, + }, + }); + } cellType = 'r'; cellStartLine = line; } else if (line === lines.length - 1) { - cells.push({ - cellKind: vscode.CellKind.Markdown, - source: lines.slice(cellStartLine, line).join('\n'), - language: 'markdown', - outputs: [], - metadata: { - editable: true, - runnable: false, - }, - }); + if (line > cellStartLine) { + cells.push({ + cellKind: vscode.CellKind.Markdown, + source: lines.slice(cellStartLine, line).join('\n'), + language: 'markdown', + outputs: [], + metadata: { + editable: true, + runnable: false, + }, + }); + } } } else if (cellType === 'yaml') { if (lines[line].startsWith('---')) { From c366b31c3b82eeb7fb1be4c20c8f3c56c8cdb315 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 14 Sep 2020 00:10:47 +0800 Subject: [PATCH 48/78] Experiment with callr session --- R/notebook2.R | 142 +++++++++++++++++++++++++ src/notebook.ts | 61 ++++++++--- vscode.proposed.d.ts | 239 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 390 insertions(+), 52 deletions(-) create mode 100644 R/notebook2.R diff --git a/R/notebook2.R b/R/notebook2.R new file mode 100644 index 000000000..125e34ce0 --- /dev/null +++ b/R/notebook2.R @@ -0,0 +1,142 @@ +requireNamespace("jsonlite") +requireNamespace("callr") + +args <- commandArgs(trailingOnly = TRUE) +exprs <- parse(text = args, keep.source = FALSE) +env <- new.env() +for (expr in exprs) { + eval(expr, env) +} + +# r <- callr::r_session$new( +# callr::r_session_options( +# system_profile = TRUE, user_profile = TRUE, supervise = TRUE), +# wait = TRUE +# ) + +# r$run(function() { +# requireNamespace("jsonlite") +# requireNamespace("svglite") + +# .vscNotebook <- local({ +# null_dev_id <- c(pdf = 2L) +# null_dev_size <- c(7 + pi, 7 + pi) +# viewer_file <- NULL +# browser_url <- NULL + +# options( +# device = function(...) { +# pdf(NULL, +# width = null_dev_size[[1L]], +# height = null_dev_size[[2L]], +# bg = "white") +# dev.control(displaylist = "enable") +# }, +# viewer = function(url, ...) { +# write_log("viewer: ", url) +# viewer_file <<- url +# }, +# page_viewer = function(url, ...) { +# write_log("page_viewer: ", url) +# viewer_file <<- url +# }, +# browser = function(url, ...) { +# write_log("browser: ", url) +# browser_url <<- url +# } +# ) + +# check_null_dev <- function() { +# identical(dev.cur(), null_dev_id) && +# identical(dev.size(), null_dev_size) +# } + +# evaluate <- function(expr) { +# tryCatch({ +# out <- withVisible(eval(expr, globalenv())) +# text <- utils::capture.output(print(out$value, view = TRUE)) +# if (check_null_dev()) { +# record <- recordPlot() +# plot_file <- tempfile(fileext = ".svg") +# svglite::svglite(plot_file, width = 12, height = 8) +# replayPlot(record) +# graphics.off() +# res <- list( +# type = "plot", +# result = plot_file +# ) +# } else if (!is.null(viewer_file)) { +# res <- list( +# type = "viewer", +# result = viewer_file +# ) +# } else if (!is.null(browser_url)) { +# res <- list( +# type = "browser", +# result = browser_url +# ) +# } else if (out$visible) { +# res <- list( +# type = "text", +# result = paste0(text, collapse = "\n") +# ) +# } else { +# res <- list( +# type = "text", +# result = "" +# ) +# } +# }) + +# res +# } + +# environment() +# }) + +# attach(environment(), name = "tools:vscNotebook") +# NULL +# }) + +con <- socketConnection(host = "127.0.0.1", port = env$port, open = "r+b") + +while (TRUE) { + if (socketSelect(list(con), timeout = 0)) { + header <- readLines(con, 1, encoding = "UTF-8") + n <- as.integer(gsub("^Content-Length: (\\d+)$", "\\1", header)) + content <- readChar(con, n, useBytes = TRUE) + Encoding(content) <- "UTF-8" + print(content) + } + Sys.sleep(0.1) +} + +# while (TRUE) { +# write_log("Listening on port: ", env$port) +# con <- try(socketConnection(host = "127.0.0.1", port = env$port, +# blocking = TRUE, server = TRUE, +# open = "r+"), silent = TRUE) +# if (inherits(con, "try-error")) { +# message(con) +# } else { +# tryCatch({ +# line <- readLines(con, n = 1) +# write_log(line) +# request <- jsonlite::fromJSON(line) + +# str <- tryCatch({ +# expr <- parse(text = request$expr) +# }, error = function(e) { +# list( +# type = "error", +# result = conditionMessage(e) +# ) +# } +# ) +# response <- jsonlite::toJSON(str, auto_unbox = TRUE, force = TRUE) +# writeLines(response, con) +# }, error = function(e) { +# message(e) +# }, finally = close(con)) +# } +# } diff --git a/src/notebook.ts b/src/notebook.ts index a3875b46b..d1ca0feda 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -2,7 +2,6 @@ import * as vscode from 'vscode'; import net = require('net'); import { spawn, ChildProcess } from 'child_process'; import { dirname } from 'path'; -import getPort = require('get-port'); import * as fs from 'fs'; interface REvalOutput { @@ -12,13 +11,23 @@ interface REvalOutput { class RKernel { private kernelScript: string; + private doc: vscode.NotebookDocument; private cwd: string; private process: ChildProcess; private port: number; + private socket: net.Socket; constructor(kernelScript: string, doc: vscode.NotebookDocument) { this.kernelScript = kernelScript; this.cwd = dirname(doc.uri.fsPath); + this.doc = doc; + } + + private request(obj: any) { + if (this.socket) { + const json = JSON.stringify(obj); + this.socket.write(`Content-Length: ${json.length}\n${json}\n`); + } } public async start() { @@ -29,21 +38,38 @@ class RKernel { const env = Object.create(process.env); env.LANG = 'en_US.UTF-8'; - this.port = await getPort(); - const childProcess = spawn('R', ['--quiet', '--slave', '-f', this.kernelScript, '--args', `port=${this.port}`], - { cwd: this.cwd, env: env }); - childProcess.stderr.on('data', (chunk: Buffer) => { - const str = chunk.toString(); - console.log(`R stderr (${childProcess.pid}): ${str}`); - }); - childProcess.stdout.on('data', (chunk: Buffer) => { - const str = chunk.toString(); - console.log(`R stdout (${childProcess.pid}): ${str}`); + const server = net.createServer(socket => { + console.log('socket started'); + this.socket = socket; + socket.on('data', (chunk: Buffer) => { + const str = chunk.toString(); + console.log(`socket (${socket.localAddress}:${socket.localPort}): ${str}`); + }); + socket.on('end', () => { + console.log('socket disconnected'); + this.socket = undefined; + }); + server.close(); }); - childProcess.on('exit', (code, signal) => { - console.log(`R exited with code ${code}`); + + server.listen(0, '127.0.0.1', () => { + this.port = (server.address() as net.AddressInfo).port; + const childProcess = spawn('R', ['--quiet', '--slave', '-f', this.kernelScript, '--args', `port=${this.port}`], + { cwd: this.cwd, env: env }); + childProcess.stderr.on('data', (chunk: Buffer) => { + const str = chunk.toString(); + console.log(`R stderr (${childProcess.pid}): ${str}`); + }); + childProcess.stdout.on('data', (chunk: Buffer) => { + const str = chunk.toString(); + console.log(`R stdout (${childProcess.pid}): ${str}`); + }); + childProcess.on('exit', (code, signal) => { + console.log(`R exited with code ${code}`); + }); + this.process = childProcess; + return childProcess; }); - this.process = childProcess; return new Promise((resolve) => setTimeout(resolve, 500)); } @@ -61,6 +87,13 @@ class RKernel { } public async eval(cell: vscode.NotebookCell): Promise { + if (this.socket) { + this.request({ + uri: cell.uri, + time: Date.now(), + expr: cell.document.getText(), + }); + } if (this.process) { const client = net.createConnection({ host: '127.0.0.1', port: this.port }, () => { console.log(`uri: ${cell.uri}, connect`); diff --git a/vscode.proposed.d.ts b/vscode.proposed.d.ts index ba6a5453a..a2811eec4 100644 --- a/vscode.proposed.d.ts +++ b/vscode.proposed.d.ts @@ -112,6 +112,7 @@ declare module 'vscode' { export function registerAuthenticationProvider(provider: AuthenticationProvider): Disposable; /** + * @deprecated - getSession should now trigger extension activation. * Fires with the provider id that was registered or unregistered. */ export const onDidChangeAuthenticationProviders: Event; @@ -716,16 +717,69 @@ declare module 'vscode' { //#region file-decorations: https://github.com/microsoft/vscode/issues/54938 + // TODO@jrieken FileDecoration, FileDecorationProvider etc. + // TODO@jrieken Add selector notion to limit decorations to a view. + // TODO@jrieken Rename `Decoration.letter` to `short` so that it could be used for coverage et al. + export class Decoration { + + /** + * A letter that represents this decoration. + */ letter?: string; + + /** + * The human-readable title for this decoration. + */ title?: string; + + /** + * The color of this decoration. + */ color?: ThemeColor; + + /** + * The priority of this decoration. + */ priority?: number; + + /** + * A flag expressing that this decoration should be + * propagted to its parents. + */ bubble?: boolean; + + /** + * Creates a new decoration. + * + * @param letter A letter that represents the decoration. + * @param title The title of the decoration. + * @param color The color of the decoration. + */ + constructor(letter?: string, title?: string, color?: ThemeColor); } + /** + * The decoration provider interfaces defines the contract between extensions and + * file decorations. + */ export interface DecorationProvider { + + /** + * An event to signal decorations for one or many files have changed. + * + * @see [EventEmitter](#EventEmitter + */ onDidChangeDecorations: Event; + + /** + * Provide decorations for a given uri. + * + * + * @param uri The uri of the file to provide a decoration for. + * @param token A cancellation token. + * @returns A decoration or a thenable that resolves to such. + */ provideDecoration(uri: Uri, token: CancellationToken): ProviderResult; } @@ -737,6 +791,22 @@ declare module 'vscode' { //#region debug + /** + * A DebugProtocolVariableContainer is an opaque stand-in type for the intersection of the Scope and Variable types defined in the Debug Adapter Protocol. + * See https://microsoft.github.io/debug-adapter-protocol/specification#Types_Scope and https://microsoft.github.io/debug-adapter-protocol/specification#Types_Variable. + */ + export interface DebugProtocolVariableContainer { + // Properties: the intersection of DAP's Scope and Variable types. + } + + /** + * A DebugProtocolVariable is an opaque stand-in type for the Variable type defined in the Debug Adapter Protocol. + * See https://microsoft.github.io/debug-adapter-protocol/specification#Types_Variable. + */ + export interface DebugProtocolVariable { + // Properties: see details [here](https://microsoft.github.io/debug-adapter-protocol/specification#Base_Protocol_Variable). + } + // deprecated debug API export interface DebugConfigurationProvider { @@ -963,13 +1033,6 @@ declare module 'vscode' { } //#endregion - /** - * A task to execute - */ - export class Task2 extends Task { - detail?: string; - } - //#region Task presentation group: https://github.com/microsoft/vscode/issues/47265 export interface TaskPresentationOptions { /** @@ -1186,7 +1249,7 @@ declare module 'vscode' { export interface NotebookCellMetadata { /** - * Controls if the content of a cell is editable or not. + * Controls whether a cell's editor is editable/readonly. */ editable?: boolean; @@ -1312,7 +1375,6 @@ declare module 'vscode' { readonly isUntitled: boolean; readonly cells: ReadonlyArray; languages: string[]; - displayOrder?: GlobPattern[]; metadata: NotebookDocumentMetadata; } @@ -1335,18 +1397,52 @@ declare module 'vscode' { contains(uri: Uri): boolean } - export interface NotebookEditorCellEdit { + export interface WorkspaceEdit { + replaceNotebookMetadata(uri: Uri, value: NotebookDocumentMetadata): void; + replaceCells(uri: Uri, start: number, end: number, cells: NotebookCellData[], metadata?: WorkspaceEditEntryMetadata): void; + replaceCellOutput(uri: Uri, index: number, outputs: CellOutput[], metadata?: WorkspaceEditEntryMetadata): void; + replaceCellMetadata(uri: Uri, index: number, cellMetadata: NotebookCellMetadata, metadata?: WorkspaceEditEntryMetadata): void; + } - replaceCells(from: number, to: number, cells: NotebookCellData[]): void; - replaceOutputs(index: number, outputs: CellOutput[]): void; - replaceMetadata(index: number, metadata: NotebookCellMetadata): void; + export interface NotebookEditorEdit { + replaceNotebookMetadata(value: NotebookDocumentMetadata): void; + + replaceCells(start: number, end: number, cells: NotebookCellData[]): void; + replaceCellOutput(index: number, outputs: CellOutput[]): void; + replaceCellMetadata(index: number, metadata: NotebookCellMetadata): void; + + /** @deprecated */ + replaceOutput(index: number, outputs: CellOutput[]): void; + /** @deprecated */ + replaceMetadata(index: number, metadata: NotebookCellMetadata): void; /** @deprecated */ insert(index: number, content: string | string[], language: string, type: CellKind, outputs: CellOutput[], metadata: NotebookCellMetadata | undefined): void; /** @deprecated */ delete(index: number): void; } + export interface NotebookCellRange { + readonly start: number; + readonly end: number; + } + + export enum NotebookEditorRevealType { + /** + * The range will be revealed with as little scrolling as possible. + */ + Default = 0, + /** + * The range will always be revealed in the center of the viewport. + */ + InCenter = 1, + /** + * If the range is outside the viewport, it will be revealed in the center of the viewport. + * Otherwise, it will be revealed with as little scrolling as possible. + */ + InCenterIfOutsideViewport = 2, + } + export interface NotebookEditor { /** * The document associated with this notebook editor. @@ -1358,6 +1454,12 @@ declare module 'vscode' { */ readonly selection?: NotebookCell; + + /** + * The current visible ranges in the editor (vertically). + */ + readonly visibleRanges: NotebookCellRange[]; + /** * The column in which this editor shows. */ @@ -1401,7 +1503,9 @@ declare module 'vscode' { */ asWebviewUri(localResource: Uri): Uri; - edit(callback: (editBuilder: NotebookEditorCellEdit) => void): Thenable; + edit(callback: (editBuilder: NotebookEditorEdit) => void): Thenable; + + revealRange(range: NotebookCellRange, revealType?: NotebookEditorRevealType): void; } export interface NotebookOutputSelector { @@ -1414,6 +1518,10 @@ declare module 'vscode' { outputId: string; } + export interface NotebookDocumentMetadataChangeEvent { + readonly document: NotebookDocument; + } + export interface NotebookCellsChangeData { readonly start: number; readonly deletedCount: number; @@ -1464,6 +1572,16 @@ declare module 'vscode' { readonly cell: NotebookCell; } + export interface NotebookEditorSelectionChangeEvent { + readonly notebookEditor: NotebookEditor; + readonly selection?: NotebookCell; + } + + export interface NotebookEditorVisibleRangesChangeEvent { + readonly notebookEditor: NotebookEditor; + readonly visibleRanges: ReadonlyArray; + } + export interface NotebookCellData { readonly cellKind: CellKind; readonly source: string; @@ -1593,6 +1711,7 @@ declare module 'vscode' { readonly id?: string; label: string; description?: string; + detail?: string; isPreferred?: boolean; preloads?: Uri[]; executeCell(document: NotebookDocument, cell: NotebookCell): void; @@ -1602,13 +1721,12 @@ declare module 'vscode' { } export interface NotebookDocumentFilter { - viewType?: string; - filenamePattern?: GlobPattern; - excludeFileNamePattern?: GlobPattern; + viewType?: string | string[]; + filenamePattern?: GlobPattern | { include: GlobPattern; exclude: GlobPattern }; } export interface NotebookKernelProvider { - onDidChangeKernels?: Event; + onDidChangeKernels?: Event; provideKernels(document: NotebookDocument, token: CancellationToken): ProviderResult; resolveKernel?(kernel: T, document: NotebookDocument, webview: NotebookCommunication, token: CancellationToken): ProviderResult; } @@ -1665,12 +1783,6 @@ declare module 'vscode' { provider: NotebookKernelProvider ): Disposable; - export function registerNotebookKernel( - id: string, - selectors: GlobPattern[], - kernel: NotebookKernel - ): Disposable; - export const onDidOpenNotebookDocument: Event; export const onDidCloseNotebookDocument: Event; export const onDidSaveNotebookDocument: Event; @@ -1680,11 +1792,14 @@ declare module 'vscode' { */ export const notebookDocuments: ReadonlyArray; - export let visibleNotebookEditors: NotebookEditor[]; + export const visibleNotebookEditors: NotebookEditor[]; export const onDidChangeVisibleNotebookEditors: Event; - export let activeNotebookEditor: NotebookEditor | undefined; + export const activeNotebookEditor: NotebookEditor | undefined; export const onDidChangeActiveNotebookEditor: Event; + export const onDidChangeNotebookEditorSelection: Event; + export const onDidChangeNotebookEditorVisibleRanges: Event; + export const onDidChangeNotebookDocumentMetadata: Event; export const onDidChangeNotebookCells: Event; export const onDidChangeCellOutputs: Event; export const onDidChangeCellLanguage: Event; @@ -2007,13 +2122,16 @@ declare module 'vscode' { */ title?: string; + /** + * Human-readable string which is rendered less prominently in the title. + */ + description?: string; + /** * Event fired when the view is disposed. * - * Views are disposed of in a few cases: - * - * - When a view is collapsed and `retainContextWhenHidden` has not been set. - * - When a view is hidden by a user. + * Views are disposed when they are explicitly hidden by a user (this happens when a user + * right clicks in a view and unchecks the webview view). * * Trying to use the view after it has been disposed throws an exception. */ @@ -2027,17 +2145,40 @@ declare module 'vscode' { readonly visible: boolean; /** - * Event fired when the visibility of the view changes + * Event fired when the visibility of the view changes. + * + * Actions that trigger a visibility change: + * + * - The view is collapsed or expanded. + * - The user switches to a different view group in the sidebar or panel. + * + * Note that hiding a view using the context menu instead disposes of the view and fires `onDidDispose`. */ readonly onDidChangeVisibility: Event; + + /** + * Reveal the view in the UI. + * + * If the view is collapsed, this will expand it. + * + * @param preserveFocus When `true` the view will not take focus. + */ + show(preserveFocus?: boolean): void; } + /** + * Additional information the webview view being resolved. + * + * @param T Type of the webview's state. + */ interface WebviewViewResolveContext { /** * Persisted state from the webview content. * - * To save resources, VS Code normally deallocates webview views that are not visible. For example, if the user - * collapse a view or switching to another top level activity, the underlying webview document is deallocates. + * To save resources, VS Code normally deallocates webview documents (the iframe content) that are not visible. + * For example, when the user collapse a view or switches to another top level activity in the sidebar, the + * `WebviewView` itself is kept alive but the webview's underlying document is deallocated. It is recreated when + * the view becomes visible again. * * You can prevent this behavior by setting `retainContextWhenHidden` in the `WebviewOptions`. However this * increases resource usage and should be avoided wherever possible. Instead, you can use persisted state to @@ -2073,7 +2214,7 @@ declare module 'vscode' { * `resolveWebviewView` is called when a view first becomes visible. This may happen when the view is * first loaded or when the user hides and then shows a view again. * - * @param webviewView Webview panel to restore. The serializer should take ownership of this panel. The + * @param webviewView Webview view to restore. The serializer should take ownership of this view. The * provider must set the webview's `.html` and hook up all webview events it is interested in. * @param context Additional metadata about the view being resolved. * @param token Cancellation token indicating that the view being provided is no longer needed. @@ -2099,24 +2240,46 @@ declare module 'vscode' { */ readonly webviewOptions?: { /** - * Controls if the webview panel's content (iframe) is kept around even when the panel + * Controls if the webview element itself (iframe) is kept around even when the view * is no longer visible. * - * Normally the webview's html context is created when the panel becomes visible + * Normally the webview's html context is created when the view becomes visible * and destroyed when it is hidden. Extensions that have complex state * or UI can set the `retainContextWhenHidden` to make VS Code keep the webview * context around, even when the webview moves to a background tab. When a webview using * `retainContextWhenHidden` becomes hidden, its scripts and other dynamic content are suspended. - * When the panel becomes visible again, the context is automatically restored + * When the view becomes visible again, the context is automatically restored * in the exact same state it was in originally. You cannot send messages to a * hidden webview, even with `retainContextWhenHidden` enabled. * * `retainContextWhenHidden` has a high memory overhead and should only be used if - * your panel's context cannot be quickly saved and restored. + * your view's context cannot be quickly saved and restored. */ readonly retainContextWhenHidden?: boolean; }; }): Disposable; } //#endregion + + //#region + + export interface FileSystem { + /** + * Check if a given file system supports writing files. + * + * Keep in mind that just because a file system supports writing, that does + * not mean that writes will always succeed. There may be permissions issues + * or other errors that prevent writing a file. + * + * @param scheme The scheme of the filesystem, for example `file` or `git`. + * + * @return `true` if the file system supports writing, `false` if it does not + * support writing (i.e. it is readonly), and `undefined` if VS Code does not + * know about the filesystem. + */ + isWritableFileSystem(scheme: string): boolean | undefined; + } + + + //#endregion } From 3d383d4bbed69706ee5b919f36cf951126140de9 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 14 Sep 2020 11:45:07 +0800 Subject: [PATCH 49/78] Update notebook2 --- R/notebook2.R | 6 ++-- src/notebook.ts | 78 ++++++++++++++++++++++++++----------------------- 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/R/notebook2.R b/R/notebook2.R index 125e34ce0..e3be05ce4 100644 --- a/R/notebook2.R +++ b/R/notebook2.R @@ -100,13 +100,15 @@ for (expr in exprs) { con <- socketConnection(host = "127.0.0.1", port = env$port, open = "r+b") +request_id <- 0L while (TRUE) { if (socketSelect(list(con), timeout = 0)) { header <- readLines(con, 1, encoding = "UTF-8") - n <- as.integer(gsub("^Content-Length: (\\d+)$", "\\1", header)) + n <- as.integer(gsub("^Content-Length\\: (\\d+)$", "\\1", header)) content <- readChar(con, n, useBytes = TRUE) Encoding(content) <- "UTF-8" - print(content) + cat("request ", request_id, ": ", content, "\n", sep = "") + request_id <- request_id + 1L } Sys.sleep(0.1) } diff --git a/src/notebook.ts b/src/notebook.ts index d1ca0feda..9a2f84f9c 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -26,7 +26,7 @@ class RKernel { private request(obj: any) { if (this.socket) { const json = JSON.stringify(obj); - this.socket.write(`Content-Length: ${json.length}\n${json}\n`); + this.socket.write(`Content-Length: ${json.length}\n${json}`); } } @@ -89,46 +89,50 @@ class RKernel { public async eval(cell: vscode.NotebookCell): Promise { if (this.socket) { this.request({ - uri: cell.uri, + uri: cell.uri.toString(), time: Date.now(), expr: cell.document.getText(), }); } - if (this.process) { - const client = net.createConnection({ host: '127.0.0.1', port: this.port }, () => { - console.log(`uri: ${cell.uri}, connect`); - const request = JSON.stringify({ - time: Date.now(), - expr: cell.document.getText(), - }).concat('\n'); - console.log(`uri: ${cell.uri}, write: ${request}`); - client.write(request); - }); - - client.on('end', () => { - console.log(`uri: ${cell.uri}, end`); - }); - - return new Promise((resolve, reject) => { - client.on('data', (data) => { - const response = data.toString(); - console.log(`uri: ${cell.uri}, data: ${response}`); - client.end(); - const output: REvalOutput = JSON.parse(response); - resolve(output); - }); - - client.on('error', (err) => { - console.log(`uri: ${cell.uri}, error: ${err.name}, ${err.message}`); - reject({ - type: 'error', - result: [ - err.message - ], - }); - }); - }); - } + return { + type: 'text', + result: 'test', + }; + // if (this.process) { + // const client = net.createConnection({ host: '127.0.0.1', port: this.port }, () => { + // console.log(`uri: ${cell.uri}, connect`); + // const request = JSON.stringify({ + // time: Date.now(), + // expr: cell.document.getText(), + // }).concat('\n'); + // console.log(`uri: ${cell.uri}, write: ${request}`); + // client.write(request); + // }); + + // client.on('end', () => { + // console.log(`uri: ${cell.uri}, end`); + // }); + + // return new Promise((resolve, reject) => { + // client.on('data', (data) => { + // const response = data.toString(); + // console.log(`uri: ${cell.uri}, data: ${response}`); + // client.end(); + // const output: REvalOutput = JSON.parse(response); + // resolve(output); + // }); + + // client.on('error', (err) => { + // console.log(`uri: ${cell.uri}, error: ${err.name}, ${err.message}`); + // reject({ + // type: 'error', + // result: [ + // err.message + // ], + // }); + // }); + // }); + // } } } From 3de3650e0c4ddb3c936782e1c2eab979be7f3a73 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 14 Sep 2020 12:33:43 +0800 Subject: [PATCH 50/78] Update notebook2 --- src/notebook.ts | 63 ++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index 9a2f84f9c..7b418f16d 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -38,40 +38,43 @@ class RKernel { const env = Object.create(process.env); env.LANG = 'en_US.UTF-8'; - const server = net.createServer(socket => { - console.log('socket started'); - this.socket = socket; - socket.on('data', (chunk: Buffer) => { - const str = chunk.toString(); - console.log(`socket (${socket.localAddress}:${socket.localPort}): ${str}`); + return new Promise((resolve, reject) => { + const server = net.createServer(socket => { + console.log('socket connected'); + this.socket = socket; + resolve(undefined); + + socket.on('data', (chunk: Buffer) => { + const str = chunk.toString(); + console.log(`socket (${socket.localAddress}:${socket.localPort}): ${str}`); + }); + socket.on('end', () => { + console.log('socket disconnected'); + this.socket = undefined; + reject(undefined); + }); + server.close(); }); - socket.on('end', () => { - console.log('socket disconnected'); - this.socket = undefined; - }); - server.close(); - }); - server.listen(0, '127.0.0.1', () => { - this.port = (server.address() as net.AddressInfo).port; - const childProcess = spawn('R', ['--quiet', '--slave', '-f', this.kernelScript, '--args', `port=${this.port}`], - { cwd: this.cwd, env: env }); - childProcess.stderr.on('data', (chunk: Buffer) => { - const str = chunk.toString(); - console.log(`R stderr (${childProcess.pid}): ${str}`); - }); - childProcess.stdout.on('data', (chunk: Buffer) => { - const str = chunk.toString(); - console.log(`R stdout (${childProcess.pid}): ${str}`); + server.listen(0, '127.0.0.1', () => { + this.port = (server.address() as net.AddressInfo).port; + const childProcess = spawn('R', ['--quiet', '--slave', '-f', this.kernelScript, '--args', `port=${this.port}`], + { cwd: this.cwd, env: env }); + childProcess.stderr.on('data', (chunk: Buffer) => { + const str = chunk.toString(); + console.log(`R stderr (${childProcess.pid}): ${str}`); + }); + childProcess.stdout.on('data', (chunk: Buffer) => { + const str = chunk.toString(); + console.log(`R stdout (${childProcess.pid}): ${str}`); + }); + childProcess.on('exit', (code, signal) => { + console.log(`R exited with code ${code}`); + }); + this.process = childProcess; + return childProcess; }); - childProcess.on('exit', (code, signal) => { - console.log(`R exited with code ${code}`); - }); - this.process = childProcess; - return childProcess; }); - - return new Promise((resolve) => setTimeout(resolve, 500)); } public stop() { From 1c1a87ee228cf7eb0cde2636e4632ee1d08c6d95 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 14 Sep 2020 13:55:29 +0800 Subject: [PATCH 51/78] Update notebook2 --- R/notebook2.R | 233 +++++++++++++++++++++++++----------------------- src/notebook.ts | 155 ++++++++++++++------------------ 2 files changed, 185 insertions(+), 203 deletions(-) diff --git a/R/notebook2.R b/R/notebook2.R index e3be05ce4..ef9018aae 100644 --- a/R/notebook2.R +++ b/R/notebook2.R @@ -8,137 +8,142 @@ for (expr in exprs) { eval(expr, env) } -# r <- callr::r_session$new( -# callr::r_session_options( -# system_profile = TRUE, user_profile = TRUE, supervise = TRUE), -# wait = TRUE -# ) +r <- callr::r_session$new( + callr::r_session_options( + system_profile = TRUE, user_profile = TRUE, supervise = TRUE), + wait = TRUE +) -# r$run(function() { -# requireNamespace("jsonlite") -# requireNamespace("svglite") +r$run(function() { + requireNamespace("jsonlite") + requireNamespace("svglite") -# .vscNotebook <- local({ -# null_dev_id <- c(pdf = 2L) -# null_dev_size <- c(7 + pi, 7 + pi) -# viewer_file <- NULL -# browser_url <- NULL + .vscNotebook <- local({ + null_dev_id <- c(pdf = 2L) + null_dev_size <- c(7 + pi, 7 + pi) + viewer_file <- NULL + browser_url <- NULL -# options( -# device = function(...) { -# pdf(NULL, -# width = null_dev_size[[1L]], -# height = null_dev_size[[2L]], -# bg = "white") -# dev.control(displaylist = "enable") -# }, -# viewer = function(url, ...) { -# write_log("viewer: ", url) -# viewer_file <<- url -# }, -# page_viewer = function(url, ...) { -# write_log("page_viewer: ", url) -# viewer_file <<- url -# }, -# browser = function(url, ...) { -# write_log("browser: ", url) -# browser_url <<- url -# } -# ) + options( + device = function(...) { + pdf(NULL, + width = null_dev_size[[1L]], + height = null_dev_size[[2L]], + bg = "white") + dev.control(displaylist = "enable") + }, + viewer = function(url, ...) { + write_log("viewer: ", url) + viewer_file <<- url + }, + page_viewer = function(url, ...) { + write_log("page_viewer: ", url) + viewer_file <<- url + }, + browser = function(url, ...) { + write_log("browser: ", url) + browser_url <<- url + } + ) -# check_null_dev <- function() { -# identical(dev.cur(), null_dev_id) && -# identical(dev.size(), null_dev_size) -# } + check_null_dev <- function() { + identical(dev.cur(), null_dev_id) && + identical(dev.size(), null_dev_size) + } -# evaluate <- function(expr) { -# tryCatch({ -# out <- withVisible(eval(expr, globalenv())) -# text <- utils::capture.output(print(out$value, view = TRUE)) -# if (check_null_dev()) { -# record <- recordPlot() -# plot_file <- tempfile(fileext = ".svg") -# svglite::svglite(plot_file, width = 12, height = 8) -# replayPlot(record) -# graphics.off() -# res <- list( -# type = "plot", -# result = plot_file -# ) -# } else if (!is.null(viewer_file)) { -# res <- list( -# type = "viewer", -# result = viewer_file -# ) -# } else if (!is.null(browser_url)) { -# res <- list( -# type = "browser", -# result = browser_url -# ) -# } else if (out$visible) { -# res <- list( -# type = "text", -# result = paste0(text, collapse = "\n") -# ) -# } else { -# res <- list( -# type = "text", -# result = "" -# ) -# } -# }) + evaluate <- function(id, uri, expr) { + tryCatch({ + expr <- parse(text = expr) + out <- withVisible(eval(expr, globalenv())) + text <- utils::capture.output(print(out$value, view = TRUE)) + if (check_null_dev()) { + record <- recordPlot() + plot_file <- tempfile(fileext = ".svg") + svglite::svglite(plot_file, width = 12, height = 8) + replayPlot(record) + graphics.off() + res <- list( + type = "plot", + result = plot_file + ) + } else if (!is.null(viewer_file)) { + res <- list( + type = "viewer", + result = viewer_file + ) + } else if (!is.null(browser_url)) { + res <- list( + type = "browser", + result = browser_url + ) + } else if (out$visible) { + res <- list( + type = "text", + result = paste0(text, collapse = "\n") + ) + } else { + res <- list( + type = "text", + result = "" + ) + } + }, error = function(e) { + res <- list( + type = "error", + result = conditionMessage(e) + ) + }) -# res -# } + c(id = id, uri = uri, res) + } -# environment() -# }) + environment() + }) -# attach(environment(), name = "tools:vscNotebook") -# NULL -# }) + attach(environment(), name = "tools:vscNotebook") + NULL +}) con <- socketConnection(host = "127.0.0.1", port = env$port, open = "r+b") -request_id <- 0L while (TRUE) { + response <- NULL if (socketSelect(list(con), timeout = 0)) { header <- readLines(con, 1, encoding = "UTF-8") n <- as.integer(gsub("^Content-Length\\: (\\d+)$", "\\1", header)) content <- readChar(con, n, useBytes = TRUE) Encoding(content) <- "UTF-8" - cat("request ", request_id, ": ", content, "\n", sep = "") - request_id <- request_id + 1L + cat(content, "\n", sep = "") + + request <- jsonlite::fromJSON(content, simplifyVector = FALSE) + response <- tryCatch({ + r$call(function(id, uri, expr) { + .vscNotebook$evaluate(id, uri, expr) + }, request) + NULL + }, error = function(e) { + list( + id = request$id, + uri = request$uri, + type = "error", + result = conditionMessage(e) + ) + }) } - Sys.sleep(0.1) -} -# while (TRUE) { -# write_log("Listening on port: ", env$port) -# con <- try(socketConnection(host = "127.0.0.1", port = env$port, -# blocking = TRUE, server = TRUE, -# open = "r+"), silent = TRUE) -# if (inherits(con, "try-error")) { -# message(con) -# } else { -# tryCatch({ -# line <- readLines(con, n = 1) -# write_log(line) -# request <- jsonlite::fromJSON(line) + result <- r$read() + if (!is.null(result)) { + if (is.list(result$result)) { + response <- result$result + } else if (!is.null(result$error)) { + message(result$error) + } + } -# str <- tryCatch({ -# expr <- parse(text = request$expr) -# }, error = function(e) { -# list( -# type = "error", -# result = conditionMessage(e) -# ) -# } -# ) -# response <- jsonlite::toJSON(str, auto_unbox = TRUE, force = TRUE) -# writeLines(response, con) -# }, error = function(e) { -# message(e) -# }, finally = close(con)) -# } -# } + if (!is.null(response)) { + response <- jsonlite::toJSON(result$result, + auto_unbox = TRUE, force = TRUE) + writeLines(response, con) + } + Sys.sleep(0.1) +} diff --git a/src/notebook.ts b/src/notebook.ts index 7b418f16d..230fc3b8b 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -5,7 +5,9 @@ import { dirname } from 'path'; import * as fs from 'fs'; interface REvalOutput { - type: 'text' | 'plot' | 'viewer' | 'browser' | 'error'; + id: number; + uri: string; + type: 'text' | 'plot' | 'viewer' | 'browser' | 'error' | 'cancelled'; result: string; } @@ -30,6 +32,57 @@ class RKernel { } } + private async handleResponse(response: REvalOutput) { + const cell = this.doc.cells.find((cell) => cell.metadata.executionOrder == response.id); + if (cell) { + cell.metadata.runnable = true; + cell.metadata.runState = vscode.NotebookCellRunState.Success; + cell.metadata.lastRunDuration = +new Date() - cell.metadata.runStartTime; + + console.log(`uri: ${cell.uri}, response.type: ${response.type}, response.result: ${response.result}`); + switch (response.type) { + case 'text': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Text, + text: response.result, + }]; + break; + case 'plot': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + 'image/svg+xml': (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(), + }, + }]; + break; + case 'viewer': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + 'application/json': response.result, + }, + }]; + break; + case 'browser': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + 'application/json': response.result, + }, + }]; + break; + case 'error': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Error, + evalue: response.result, + ename: '', + traceback: [], + }]; + break; + } + } + } + public async start() { if (this.process) { return; @@ -47,7 +100,10 @@ class RKernel { socket.on('data', (chunk: Buffer) => { const str = chunk.toString(); console.log(`socket (${socket.localAddress}:${socket.localPort}): ${str}`); + const response: REvalOutput = JSON.parse(str); + this.handleResponse(response); }); + socket.on('end', () => { console.log('socket disconnected'); this.socket = undefined; @@ -89,53 +145,14 @@ class RKernel { await this.start(); } - public async eval(cell: vscode.NotebookCell): Promise { + public async eval(cell: vscode.NotebookCell): Promise { if (this.socket) { this.request({ + id: cell.metadata.executionOrder, uri: cell.uri.toString(), - time: Date.now(), expr: cell.document.getText(), }); } - return { - type: 'text', - result: 'test', - }; - // if (this.process) { - // const client = net.createConnection({ host: '127.0.0.1', port: this.port }, () => { - // console.log(`uri: ${cell.uri}, connect`); - // const request = JSON.stringify({ - // time: Date.now(), - // expr: cell.document.getText(), - // }).concat('\n'); - // console.log(`uri: ${cell.uri}, write: ${request}`); - // client.write(request); - // }); - - // client.on('end', () => { - // console.log(`uri: ${cell.uri}, end`); - // }); - - // return new Promise((resolve, reject) => { - // client.on('data', (data) => { - // const response = data.toString(); - // console.log(`uri: ${cell.uri}, data: ${response}`); - // client.end(); - // const output: REvalOutput = JSON.parse(response); - // resolve(output); - // }); - - // client.on('error', (err) => { - // console.log(`uri: ${cell.uri}, error: ${err.name}, ${err.message}`); - // reject({ - // type: 'error', - // result: [ - // err.message - // ], - // }); - // }); - // }); - // } } } @@ -156,7 +173,7 @@ class RNotebook implements vscode.Disposable { this.kernel.restart(); } - public async eval(cell: vscode.NotebookCell): Promise { + public async eval(cell: vscode.NotebookCell): Promise { await this.kernel.start(); return this.kernel.eval(cell); } @@ -178,7 +195,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode vscode.notebook.registerNotebookKernelProvider({ viewType: 'r-notebook' }, { - provideKernels: () => { + provideKernels: () => { return [this]; } }), @@ -205,7 +222,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode const content = (await vscode.workspace.fs.readFile(uri)).toString(); const lines = content.split(/\r?\n/); const cells: vscode.NotebookCellData[] = []; - + let line = 0; let cellType = 'markdown'; let cellStartLine = 0; @@ -283,7 +300,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode return { languages: ['r'], - metadata: { }, + metadata: {}, cells: cells, }; } @@ -338,7 +355,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode async executeCell(document: vscode.NotebookDocument, cell: vscode.NotebookCell) { const notebook = this.notebooks.get(document.uri.toString()); - if (!cell) { + if (!cell) { if (notebook) { notebook.restartKernel(); } @@ -354,52 +371,12 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode if (notebook) { try { - if (cell.metadata === undefined) { - cell.metadata = {}; - } - + cell.metadata.runnable = false; cell.metadata.runState = vscode.NotebookCellRunState.Running; const start = +new Date(); cell.metadata.runStartTime = start; cell.metadata.executionOrder = ++this.runIndex; - const output = await notebook.eval(cell); - console.log(`uri: ${cell.uri}, output.type: ${output.type}, output.result: ${output.result}`); - switch (output.type) { - case 'text': - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Text, - text: output.result, - }]; - break; - case 'plot': - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - 'image/svg+xml': (await vscode.workspace.fs.readFile(vscode.Uri.parse(output.result))).toString(), - } - }]; - break; - case 'viewer': - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - 'application/json': output, - } - }]; - break; - case 'browser': - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - 'application/json': output, - } - }]; - break; - case 'error': - throw new Error(output.result); - } - cell.metadata.runState = vscode.NotebookCellRunState.Success; - cell.metadata.lastRunDuration = +new Date() - start; + await notebook.eval(cell); } catch (e) { cell.outputs = [{ outputKind: vscode.CellOutputKind.Error, From a08a53cfd68616aaeb8b007efac1852f8c69c2e9 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 14 Sep 2020 14:05:43 +0800 Subject: [PATCH 52/78] Update notebook2 --- R/notebook2.R | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/R/notebook2.R b/R/notebook2.R index ef9018aae..111ad83d4 100644 --- a/R/notebook2.R +++ b/R/notebook2.R @@ -33,15 +33,12 @@ r$run(function() { dev.control(displaylist = "enable") }, viewer = function(url, ...) { - write_log("viewer: ", url) viewer_file <<- url }, page_viewer = function(url, ...) { - write_log("page_viewer: ", url) viewer_file <<- url }, browser = function(url, ...) { - write_log("browser: ", url) browser_url <<- url } ) @@ -52,7 +49,9 @@ r$run(function() { } evaluate <- function(id, uri, expr) { - tryCatch({ + viewer_file <<- NULL + browser_url <<- NULL + res <- tryCatch({ expr <- parse(text = expr) out <- withVisible(eval(expr, globalenv())) text <- utils::capture.output(print(out$value, view = TRUE)) @@ -62,33 +61,33 @@ r$run(function() { svglite::svglite(plot_file, width = 12, height = 8) replayPlot(record) graphics.off() - res <- list( + list( type = "plot", result = plot_file ) } else if (!is.null(viewer_file)) { - res <- list( + list( type = "viewer", result = viewer_file ) } else if (!is.null(browser_url)) { - res <- list( + list( type = "browser", result = browser_url ) } else if (out$visible) { - res <- list( + list( type = "text", result = paste0(text, collapse = "\n") ) } else { - res <- list( + list( type = "text", result = "" ) } }, error = function(e) { - res <- list( + list( type = "error", result = conditionMessage(e) ) From 0283fb3e4246e0f3b01e9555623680d1c63aa81a Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 14 Sep 2020 18:46:38 +0800 Subject: [PATCH 53/78] Update notebook2 --- R/notebook2.R | 63 +++++++++++++++++++++++++++++++++++++++---------- src/notebook.ts | 35 +++++++++++++++++---------- 2 files changed, 72 insertions(+), 26 deletions(-) diff --git a/R/notebook2.R b/R/notebook2.R index 111ad83d4..1c63527c1 100644 --- a/R/notebook2.R +++ b/R/notebook2.R @@ -14,6 +14,30 @@ r <- callr::r_session$new( wait = TRUE ) +r$call(function() { + for (i in 1:1000) { + x <- rnorm(1000000) + y <- rnorm(1000000) + m <- lm(y ~ x) + summary(m) + } +}) +r$interrupt() + +while (TRUE) { + res <- r$read() + if (!is.null(res)) { + print(res) + break + } +} + + +r$call(function() print(1)) +r$read() +r$get_state() +r$get_status() + r$run(function() { requireNamespace("jsonlite") requireNamespace("svglite") @@ -115,19 +139,32 @@ while (TRUE) { cat(content, "\n", sep = "") request <- jsonlite::fromJSON(content, simplifyVector = FALSE) - response <- tryCatch({ - r$call(function(id, uri, expr) { - .vscNotebook$evaluate(id, uri, expr) - }, request) - NULL - }, error = function(e) { - list( - id = request$id, - uri = request$uri, - type = "error", - result = conditionMessage(e) - ) - }) + if (request$type == "eval") { + response <- tryCatch({ + r$call(function(id, uri, expr) { + .vscNotebook$evaluate(id, uri, expr) + }, request) + NULL + }, error = function(e) { + list( + id = request$id, + uri = request$uri, + type = "error", + result = conditionMessage(e) + ) + }) + } else if (request$type == "cancel") { + if (r$interrupt()) { + response <- list( + id = request$id, + uri = request$uri, + type = "cancel", + result = "cancelled" + ) + } else { + + } + } } result <- r$read() diff --git a/src/notebook.ts b/src/notebook.ts index 230fc3b8b..d02992807 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -4,10 +4,17 @@ import { spawn, ChildProcess } from 'child_process'; import { dirname } from 'path'; import * as fs from 'fs'; -interface REvalOutput { +interface RSessionRequest { id: number; uri: string; - type: 'text' | 'plot' | 'viewer' | 'browser' | 'error' | 'cancelled'; + type: 'eval' | 'cancel'; + args: any; +} + +interface RSessionResponse { + id: number; + uri: string; + type: 'text' | 'plot' | 'viewer' | 'browser' | 'error' | 'cancel'; result: string; } @@ -32,10 +39,9 @@ class RKernel { } } - private async handleResponse(response: REvalOutput) { + private async handleResponse(response: RSessionResponse) { const cell = this.doc.cells.find((cell) => cell.metadata.executionOrder == response.id); if (cell) { - cell.metadata.runnable = true; cell.metadata.runState = vscode.NotebookCellRunState.Success; cell.metadata.lastRunDuration = +new Date() - cell.metadata.runStartTime; @@ -97,13 +103,6 @@ class RKernel { this.socket = socket; resolve(undefined); - socket.on('data', (chunk: Buffer) => { - const str = chunk.toString(); - console.log(`socket (${socket.localAddress}:${socket.localPort}): ${str}`); - const response: REvalOutput = JSON.parse(str); - this.handleResponse(response); - }); - socket.on('end', () => { console.log('socket disconnected'); this.socket = undefined; @@ -150,10 +149,21 @@ class RKernel { this.request({ id: cell.metadata.executionOrder, uri: cell.uri.toString(), + type: 'eval', expr: cell.document.getText(), }); } } + + public async cancel(cell: vscode.NotebookCell): Promise { + if (this.socket && cell.metadata.runState === vscode.NotebookCellRunState.Running) { + this.request({ + id: cell.metadata.executionOrder, + uri: cell.uri.toString(), + type: 'cancel', + }) + } + } } class RNotebook implements vscode.Disposable { @@ -369,9 +379,8 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode return; } - if (notebook) { + if (notebook && cell.metadata.runState !== vscode.NotebookCellRunState.Running) { try { - cell.metadata.runnable = false; cell.metadata.runState = vscode.NotebookCellRunState.Running; const start = +new Date(); cell.metadata.runStartTime = start; From 24ed50ae1201f91b2e72c6d7c7fff229c244b175 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 14 Sep 2020 21:59:05 +0800 Subject: [PATCH 54/78] Support cancel --- R/notebook2.R | 79 +++++++++++++---------------- src/notebook.ts | 131 +++++++++++++++++++++++++----------------------- 2 files changed, 103 insertions(+), 107 deletions(-) diff --git a/R/notebook2.R b/R/notebook2.R index 1c63527c1..00b8a9397 100644 --- a/R/notebook2.R +++ b/R/notebook2.R @@ -14,30 +14,6 @@ r <- callr::r_session$new( wait = TRUE ) -r$call(function() { - for (i in 1:1000) { - x <- rnorm(1000000) - y <- rnorm(1000000) - m <- lm(y ~ x) - summary(m) - } -}) -r$interrupt() - -while (TRUE) { - res <- r$read() - if (!is.null(res)) { - print(res) - break - } -} - - -r$call(function() print(1)) -r$read() -r$get_state() -r$get_status() - r$run(function() { requireNamespace("jsonlite") requireNamespace("svglite") @@ -128,6 +104,7 @@ r$run(function() { }) con <- socketConnection(host = "127.0.0.1", port = env$port, open = "r+b") +running_request <- NULL while (TRUE) { response <- NULL @@ -143,7 +120,8 @@ while (TRUE) { response <- tryCatch({ r$call(function(id, uri, expr) { .vscNotebook$evaluate(id, uri, expr) - }, request) + }, list(id = request$id, uri = request$uri, expr = request$expr)) + running_request <- request NULL }, error = function(e) { list( @@ -154,32 +132,43 @@ while (TRUE) { ) }) } else if (request$type == "cancel") { - if (r$interrupt()) { - response <- list( - id = request$id, - uri = request$uri, - type = "cancel", - result = "cancelled" - ) - } else { + r$interrupt() + } + } + if (!is.null(running_request)) { + result <- r$read() + if (!is.null(result)) { + print(result) + if (is.list(result$result)) { + response <- result$result + } else { + if (is.null(result$error)) { + response <- list( + id = running_request$id, + uri = running_request$uri, + type = "text", + result = result$message + ) + } else { + response <- list( + id = running_request$id, + uri = running_request$uri, + type = "error", + result = conditionMessage(result$error) + ) + } } + running_request <- NULL } - } - result <- r$read() - if (!is.null(result)) { - if (is.list(result$result)) { - response <- result$result - } else if (!is.null(result$error)) { - message(result$error) + if (!is.null(response)) { + response <- jsonlite::toJSON(response, + auto_unbox = TRUE, force = TRUE) + cat("response: ", response, "\n") + writeLines(response, con) } } - if (!is.null(response)) { - response <- jsonlite::toJSON(result$result, - auto_unbox = TRUE, force = TRUE) - writeLines(response, con) - } Sys.sleep(0.1) } diff --git a/src/notebook.ts b/src/notebook.ts index d02992807..4219fd1e2 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -2,19 +2,18 @@ import * as vscode from 'vscode'; import net = require('net'); import { spawn, ChildProcess } from 'child_process'; import { dirname } from 'path'; -import * as fs from 'fs'; interface RSessionRequest { id: number; uri: string; type: 'eval' | 'cancel'; - args: any; + expr?: any; } interface RSessionResponse { id: number; uri: string; - type: 'text' | 'plot' | 'viewer' | 'browser' | 'error' | 'cancel'; + type: 'text' | 'plot' | 'viewer' | 'browser' | 'error'; result: string; } @@ -32,63 +31,13 @@ class RKernel { this.doc = doc; } - private request(obj: any) { + private request(request: RSessionRequest) { if (this.socket) { - const json = JSON.stringify(obj); + const json = JSON.stringify(request); this.socket.write(`Content-Length: ${json.length}\n${json}`); } } - private async handleResponse(response: RSessionResponse) { - const cell = this.doc.cells.find((cell) => cell.metadata.executionOrder == response.id); - if (cell) { - cell.metadata.runState = vscode.NotebookCellRunState.Success; - cell.metadata.lastRunDuration = +new Date() - cell.metadata.runStartTime; - - console.log(`uri: ${cell.uri}, response.type: ${response.type}, response.result: ${response.result}`); - switch (response.type) { - case 'text': - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Text, - text: response.result, - }]; - break; - case 'plot': - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - 'image/svg+xml': (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(), - }, - }]; - break; - case 'viewer': - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - 'application/json': response.result, - }, - }]; - break; - case 'browser': - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - 'application/json': response.result, - }, - }]; - break; - case 'error': - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Error, - evalue: response.result, - ename: '', - traceback: [], - }]; - break; - } - } - } - public async start() { if (this.process) { return; @@ -103,6 +52,58 @@ class RKernel { this.socket = socket; resolve(undefined); + socket.on('data', async (data) => { + const response: RSessionResponse = JSON.parse(data.toString()); + const cell = this.doc.cells.find(cell => cell.metadata.executionOrder === response.id); + if (cell) { + cell.metadata.runState = vscode.NotebookCellRunState.Success; + cell.metadata.lastRunDuration = +new Date() - cell.metadata.runStartTime; + + console.log(`id: ${response.id}, uri: ${response.uri}, type: ${response.type}, result: ${response.result}`); + switch (response.type) { + case 'text': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Text, + text: response.result, + }]; + break; + case 'plot': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + 'image/svg+xml': (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(), + }, + }]; + break; + case 'viewer': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + 'application/json': response.result, + }, + }]; + break; + case 'browser': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + 'application/json': response.result, + }, + }]; + break; + case 'error': + cell.metadata.runState = vscode.NotebookCellRunState.Error; + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Error, + evalue: response.result, + ename: '', + traceback: [], + }]; + break; + } + } + }); + socket.on('end', () => { console.log('socket disconnected'); this.socket = undefined; @@ -125,6 +126,7 @@ class RKernel { }); childProcess.on('exit', (code, signal) => { console.log(`R exited with code ${code}`); + reject(undefined); }); this.process = childProcess; return childProcess; @@ -144,7 +146,7 @@ class RKernel { await this.start(); } - public async eval(cell: vscode.NotebookCell): Promise { + public eval(cell: vscode.NotebookCell) { if (this.socket) { this.request({ id: cell.metadata.executionOrder, @@ -155,13 +157,13 @@ class RKernel { } } - public async cancel(cell: vscode.NotebookCell): Promise { - if (this.socket && cell.metadata.runState === vscode.NotebookCellRunState.Running) { + public cancel(cell: vscode.NotebookCell) { + if (this.socket) { this.request({ id: cell.metadata.executionOrder, uri: cell.uri.toString(), type: 'cancel', - }) + }); } } } @@ -187,12 +189,14 @@ class RNotebook implements vscode.Disposable { await this.kernel.start(); return this.kernel.eval(cell); } + + public async cancel(cell: vscode.NotebookCell): Promise { + return this.kernel.cancel(cell); + } } export class RNotebookProvider implements vscode.NotebookContentProvider, vscode.NotebookKernel { public label = 'R Kernel'; - // public kernel = this; - private kernelScript: string; private disposables: vscode.Disposable[] = []; private readonly notebooks = new Map(); @@ -406,7 +410,10 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } async cancelCellExecution(document: vscode.NotebookDocument, cell: vscode.NotebookCell) { - + if (cell.metadata.runState === vscode.NotebookCellRunState.Running) { + const notebook = this.notebooks.get(document.uri.toString()); + await notebook.cancel(cell); + } } async cancelAllCellsExecution(document: vscode.NotebookDocument) { From 241a728df4baf1341b81234f04c31f36827895a1 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 14 Sep 2020 22:02:36 +0800 Subject: [PATCH 55/78] Remove uri --- R/notebook2.R | 19 +++++++++++-------- src/notebook.ts | 6 +----- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/R/notebook2.R b/R/notebook2.R index 00b8a9397..ce1d9fe1c 100644 --- a/R/notebook2.R +++ b/R/notebook2.R @@ -48,7 +48,7 @@ r$run(function() { identical(dev.size(), null_dev_size) } - evaluate <- function(id, uri, expr) { + evaluate <- function(id, expr) { viewer_file <<- NULL browser_url <<- NULL res <- tryCatch({ @@ -62,38 +62,44 @@ r$run(function() { replayPlot(record) graphics.off() list( + id = id, type = "plot", result = plot_file ) } else if (!is.null(viewer_file)) { list( + id = id, type = "viewer", result = viewer_file ) } else if (!is.null(browser_url)) { list( + id = id, type = "browser", result = browser_url ) } else if (out$visible) { list( + id = id, type = "text", result = paste0(text, collapse = "\n") ) } else { list( + id = id, type = "text", result = "" ) } }, error = function(e) { list( + id = id, type = "error", result = conditionMessage(e) ) }) - c(id = id, uri = uri, res) + res } environment() @@ -118,15 +124,14 @@ while (TRUE) { request <- jsonlite::fromJSON(content, simplifyVector = FALSE) if (request$type == "eval") { response <- tryCatch({ - r$call(function(id, uri, expr) { - .vscNotebook$evaluate(id, uri, expr) - }, list(id = request$id, uri = request$uri, expr = request$expr)) + r$call(function(id, expr) { + .vscNotebook$evaluate(id, expr) + }, list(id = request$id, expr = request$expr)) running_request <- request NULL }, error = function(e) { list( id = request$id, - uri = request$uri, type = "error", result = conditionMessage(e) ) @@ -146,14 +151,12 @@ while (TRUE) { if (is.null(result$error)) { response <- list( id = running_request$id, - uri = running_request$uri, type = "text", result = result$message ) } else { response <- list( id = running_request$id, - uri = running_request$uri, type = "error", result = conditionMessage(result$error) ) diff --git a/src/notebook.ts b/src/notebook.ts index 4219fd1e2..80964f98f 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -5,14 +5,12 @@ import { dirname } from 'path'; interface RSessionRequest { id: number; - uri: string; type: 'eval' | 'cancel'; expr?: any; } interface RSessionResponse { id: number; - uri: string; type: 'text' | 'plot' | 'viewer' | 'browser' | 'error'; result: string; } @@ -59,7 +57,7 @@ class RKernel { cell.metadata.runState = vscode.NotebookCellRunState.Success; cell.metadata.lastRunDuration = +new Date() - cell.metadata.runStartTime; - console.log(`id: ${response.id}, uri: ${response.uri}, type: ${response.type}, result: ${response.result}`); + console.log(`uri: ${cell.uri}, id: ${response.id}, type: ${response.type}, result: ${response.result}`); switch (response.type) { case 'text': cell.outputs = [{ @@ -150,7 +148,6 @@ class RKernel { if (this.socket) { this.request({ id: cell.metadata.executionOrder, - uri: cell.uri.toString(), type: 'eval', expr: cell.document.getText(), }); @@ -161,7 +158,6 @@ class RKernel { if (this.socket) { this.request({ id: cell.metadata.executionOrder, - uri: cell.uri.toString(), type: 'cancel', }); } From ff5587ef457762dc97cb635f197c2aa33d860c3a Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 14 Sep 2020 22:06:07 +0800 Subject: [PATCH 56/78] Rename scripts --- R/notebook.R | 268 +++++++++++++++++++++++++++++++------------------- R/notebook2.R | 177 --------------------------------- 2 files changed, 166 insertions(+), 279 deletions(-) delete mode 100644 R/notebook2.R diff --git a/R/notebook.R b/R/notebook.R index 254a8513d..efd148459 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -1,113 +1,177 @@ -local({ +requireNamespace("jsonlite") +requireNamespace("callr") + +args <- commandArgs(trailingOnly = TRUE) +exprs <- parse(text = args, keep.source = FALSE) +env <- new.env() +for (expr in exprs) { + eval(expr, env) +} + +r <- callr::r_session$new( + callr::r_session_options( + system_profile = TRUE, user_profile = TRUE, supervise = TRUE), + wait = TRUE +) + +r$run(function() { requireNamespace("jsonlite") requireNamespace("svglite") - args <- commandArgs(trailingOnly = TRUE) - exprs <- parse(text = args, keep.source = FALSE) - env <- new.env() - for (expr in exprs) { - eval(expr, env) - } - null_dev_id <- c(pdf = 2L) - null_dev_size <- c(7 + pi, 7 + pi) - viewer_file <- NULL - browser_url <- NULL + .vscNotebook <- local({ + null_dev_id <- c(pdf = 2L) + null_dev_size <- c(7 + pi, 7 + pi) + viewer_file <- NULL + browser_url <- NULL - write_log <- function(...) { - cat("[", format(Sys.time(), "%Y-%m-%d %H:%M:%OS3"), "] ", - ..., "\n", sep = "") - } + options( + device = function(...) { + pdf(NULL, + width = null_dev_size[[1L]], + height = null_dev_size[[2L]], + bg = "white") + dev.control(displaylist = "enable") + }, + viewer = function(url, ...) { + viewer_file <<- url + }, + page_viewer = function(url, ...) { + viewer_file <<- url + }, + browser = function(url, ...) { + browser_url <<- url + } + ) - options( - device = function(...) { - pdf(NULL, - width = null_dev_size[[1L]], - height = null_dev_size[[2L]], - bg = "white") - dev.control(displaylist = "enable") - }, - viewer = function(url, ...) { - write_log("viewer: ", url) - viewer_file <<- url - }, - page_viewer = function(url, ...) { - write_log("page_viewer: ", url) - viewer_file <<- url - }, - browser = function(url, ...) { - write_log("browser: ", url) - browser_url <<- url + check_null_dev <- function() { + identical(dev.cur(), null_dev_id) && + identical(dev.size(), null_dev_size) } - ) - - check_null_dev <- function() { - identical(dev.cur(), null_dev_id) && - identical(dev.size(), null_dev_size) - } - ls.str(env) - while (TRUE) { - write_log("Listening on port: ", env$port) - con <- try(socketConnection(host = "127.0.0.1", port = env$port, - blocking = TRUE, server = TRUE, - open = "r+"), silent = TRUE) - if (inherits(con, "try-error")) { - message(con) - } else { - tryCatch({ - line <- readLines(con, n = 1) - write_log(line) - request <- jsonlite::fromJSON(line) - viewer_file <- NULL - browser_url <- NULL - str <- tryCatch({ - expr <- parse(text = request$expr) - out <- withVisible(eval(expr, globalenv())) - text <- utils::capture.output(print(out$value, view = TRUE)) - if (check_null_dev()) { - record <- recordPlot() - plot_file <- tempfile(fileext = ".svg") - svglite::svglite(plot_file, width = 12, height = 8) - replayPlot(record) - graphics.off() - res <- list( - type = "plot", - result = plot_file - ) - } else if (!is.null(viewer_file)) { - res <- list( - type = "viewer", - result = viewer_file - ) - } else if (!is.null(browser_url)) { - res <- list( - type = "browser", - result = browser_url - ) - } else if (out$visible) { - res <- list( - type = "text", - result = paste0(text, collapse = "\n") - ) - } else { - res <- list( - type = "text", - result = "" - ) - } - res - }, error = function(e) { - list( - type = "error", - result = conditionMessage(e) - ) - } + evaluate <- function(id, expr) { + viewer_file <<- NULL + browser_url <<- NULL + res <- tryCatch({ + expr <- parse(text = expr) + out <- withVisible(eval(expr, globalenv())) + text <- utils::capture.output(print(out$value, view = TRUE)) + if (check_null_dev()) { + record <- recordPlot() + plot_file <- tempfile(fileext = ".svg") + svglite::svglite(plot_file, width = 12, height = 8) + replayPlot(record) + graphics.off() + list( + id = id, + type = "plot", + result = plot_file + ) + } else if (!is.null(viewer_file)) { + list( + id = id, + type = "viewer", + result = viewer_file + ) + } else if (!is.null(browser_url)) { + list( + id = id, + type = "browser", + result = browser_url + ) + } else if (out$visible) { + list( + id = id, + type = "text", + result = paste0(text, collapse = "\n") + ) + } else { + list( + id = id, + type = "text", + result = "" + ) + } + }, error = function(e) { + list( + id = id, + type = "error", + result = conditionMessage(e) ) - response <- jsonlite::toJSON(str, auto_unbox = TRUE, force = TRUE) - writeLines(response, con) + }) + + res + } + + environment() + }) + + attach(environment(), name = "tools:vscNotebook") + NULL +}) + +con <- socketConnection(host = "127.0.0.1", port = env$port, open = "r+b") +running_request <- NULL + +while (TRUE) { + response <- NULL + if (socketSelect(list(con), timeout = 0)) { + header <- readLines(con, 1, encoding = "UTF-8") + n <- as.integer(gsub("^Content-Length\\: (\\d+)$", "\\1", header)) + content <- readChar(con, n, useBytes = TRUE) + Encoding(content) <- "UTF-8" + cat(content, "\n", sep = "") + + request <- jsonlite::fromJSON(content, simplifyVector = FALSE) + if (request$type == "eval") { + response <- tryCatch({ + r$call(function(id, expr) { + .vscNotebook$evaluate(id, expr) + }, list(id = request$id, expr = request$expr)) + running_request <- request + NULL }, error = function(e) { - message(e) - }, finally = close(con)) + list( + id = request$id, + type = "error", + result = conditionMessage(e) + ) + }) + } else if (request$type == "cancel") { + r$interrupt() } } -}) + + if (!is.null(running_request)) { + result <- r$read() + if (!is.null(result)) { + print(result) + if (is.list(result$result)) { + response <- result$result + } else { + if (is.null(result$error)) { + response <- list( + id = running_request$id, + type = "text", + result = result$message + ) + } else { + response <- list( + id = running_request$id, + type = "error", + result = conditionMessage(result$error) + ) + } + } + running_request <- NULL + } + + if (!is.null(response)) { + response <- jsonlite::toJSON(response, + auto_unbox = TRUE, force = TRUE) + cat("response: ", response, "\n") + writeLines(response, con) + } + } + + Sys.sleep(0.05) +} diff --git a/R/notebook2.R b/R/notebook2.R deleted file mode 100644 index ce1d9fe1c..000000000 --- a/R/notebook2.R +++ /dev/null @@ -1,177 +0,0 @@ -requireNamespace("jsonlite") -requireNamespace("callr") - -args <- commandArgs(trailingOnly = TRUE) -exprs <- parse(text = args, keep.source = FALSE) -env <- new.env() -for (expr in exprs) { - eval(expr, env) -} - -r <- callr::r_session$new( - callr::r_session_options( - system_profile = TRUE, user_profile = TRUE, supervise = TRUE), - wait = TRUE -) - -r$run(function() { - requireNamespace("jsonlite") - requireNamespace("svglite") - - .vscNotebook <- local({ - null_dev_id <- c(pdf = 2L) - null_dev_size <- c(7 + pi, 7 + pi) - viewer_file <- NULL - browser_url <- NULL - - options( - device = function(...) { - pdf(NULL, - width = null_dev_size[[1L]], - height = null_dev_size[[2L]], - bg = "white") - dev.control(displaylist = "enable") - }, - viewer = function(url, ...) { - viewer_file <<- url - }, - page_viewer = function(url, ...) { - viewer_file <<- url - }, - browser = function(url, ...) { - browser_url <<- url - } - ) - - check_null_dev <- function() { - identical(dev.cur(), null_dev_id) && - identical(dev.size(), null_dev_size) - } - - evaluate <- function(id, expr) { - viewer_file <<- NULL - browser_url <<- NULL - res <- tryCatch({ - expr <- parse(text = expr) - out <- withVisible(eval(expr, globalenv())) - text <- utils::capture.output(print(out$value, view = TRUE)) - if (check_null_dev()) { - record <- recordPlot() - plot_file <- tempfile(fileext = ".svg") - svglite::svglite(plot_file, width = 12, height = 8) - replayPlot(record) - graphics.off() - list( - id = id, - type = "plot", - result = plot_file - ) - } else if (!is.null(viewer_file)) { - list( - id = id, - type = "viewer", - result = viewer_file - ) - } else if (!is.null(browser_url)) { - list( - id = id, - type = "browser", - result = browser_url - ) - } else if (out$visible) { - list( - id = id, - type = "text", - result = paste0(text, collapse = "\n") - ) - } else { - list( - id = id, - type = "text", - result = "" - ) - } - }, error = function(e) { - list( - id = id, - type = "error", - result = conditionMessage(e) - ) - }) - - res - } - - environment() - }) - - attach(environment(), name = "tools:vscNotebook") - NULL -}) - -con <- socketConnection(host = "127.0.0.1", port = env$port, open = "r+b") -running_request <- NULL - -while (TRUE) { - response <- NULL - if (socketSelect(list(con), timeout = 0)) { - header <- readLines(con, 1, encoding = "UTF-8") - n <- as.integer(gsub("^Content-Length\\: (\\d+)$", "\\1", header)) - content <- readChar(con, n, useBytes = TRUE) - Encoding(content) <- "UTF-8" - cat(content, "\n", sep = "") - - request <- jsonlite::fromJSON(content, simplifyVector = FALSE) - if (request$type == "eval") { - response <- tryCatch({ - r$call(function(id, expr) { - .vscNotebook$evaluate(id, expr) - }, list(id = request$id, expr = request$expr)) - running_request <- request - NULL - }, error = function(e) { - list( - id = request$id, - type = "error", - result = conditionMessage(e) - ) - }) - } else if (request$type == "cancel") { - r$interrupt() - } - } - - if (!is.null(running_request)) { - result <- r$read() - if (!is.null(result)) { - print(result) - if (is.list(result$result)) { - response <- result$result - } else { - if (is.null(result$error)) { - response <- list( - id = running_request$id, - type = "text", - result = result$message - ) - } else { - response <- list( - id = running_request$id, - type = "error", - result = conditionMessage(result$error) - ) - } - } - running_request <- NULL - } - - if (!is.null(response)) { - response <- jsonlite::toJSON(response, - auto_unbox = TRUE, force = TRUE) - cat("response: ", response, "\n") - writeLines(response, con) - } - } - - Sys.sleep(0.1) -} From 7950418598c389a454d554637dfd0c8e70e775f2 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 14 Sep 2020 22:49:53 +0800 Subject: [PATCH 57/78] Update eval --- R/notebook.R | 2 +- src/notebook.ts | 126 +++++++++++++++++++++++++----------------------- 2 files changed, 66 insertions(+), 62 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index efd148459..ec5ebebb9 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -11,7 +11,7 @@ for (expr in exprs) { r <- callr::r_session$new( callr::r_session_options( system_profile = TRUE, user_profile = TRUE, supervise = TRUE), - wait = TRUE + wait = TRUE, wait_timeout = 3000 ) r$run(function() { diff --git a/src/notebook.ts b/src/notebook.ts index 80964f98f..63d522a89 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -50,58 +50,6 @@ class RKernel { this.socket = socket; resolve(undefined); - socket.on('data', async (data) => { - const response: RSessionResponse = JSON.parse(data.toString()); - const cell = this.doc.cells.find(cell => cell.metadata.executionOrder === response.id); - if (cell) { - cell.metadata.runState = vscode.NotebookCellRunState.Success; - cell.metadata.lastRunDuration = +new Date() - cell.metadata.runStartTime; - - console.log(`uri: ${cell.uri}, id: ${response.id}, type: ${response.type}, result: ${response.result}`); - switch (response.type) { - case 'text': - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Text, - text: response.result, - }]; - break; - case 'plot': - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - 'image/svg+xml': (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(), - }, - }]; - break; - case 'viewer': - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - 'application/json': response.result, - }, - }]; - break; - case 'browser': - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - 'application/json': response.result, - }, - }]; - break; - case 'error': - cell.metadata.runState = vscode.NotebookCellRunState.Error; - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Error, - evalue: response.result, - ename: '', - traceback: [], - }]; - break; - } - } - }); - socket.on('end', () => { console.log('socket disconnected'); this.socket = undefined; @@ -136,6 +84,7 @@ class RKernel { if (this.process) { this.process.kill(); this.process = undefined; + this.socket = undefined; } } @@ -144,12 +93,22 @@ class RKernel { await this.start(); } - public eval(cell: vscode.NotebookCell) { + public async eval(cell: vscode.NotebookCell): Promise { if (this.socket) { - this.request({ - id: cell.metadata.executionOrder, - type: 'eval', - expr: cell.document.getText(), + return new Promise((resolve, reject) => { + const handler = async (data: Buffer) => { + const response: RSessionResponse = JSON.parse(data.toString()); + resolve(response); + this.socket.removeListener('data', handler); + }; + + this.socket.on('data', handler); + + this.request({ + id: cell.metadata.executionOrder, + type: 'eval', + expr: cell.document.getText(), + }); }); } } @@ -157,7 +116,7 @@ class RKernel { public cancel(cell: vscode.NotebookCell) { if (this.socket) { this.request({ - id: cell.metadata.executionOrder, + id: cell ? cell.metadata.executionOrder : 0, type: 'cancel', }); } @@ -181,7 +140,7 @@ class RNotebook implements vscode.Disposable { this.kernel.restart(); } - public async eval(cell: vscode.NotebookCell): Promise { + public async eval(cell: vscode.NotebookCell): Promise { await this.kernel.start(); return this.kernel.eval(cell); } @@ -385,7 +344,51 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode const start = +new Date(); cell.metadata.runStartTime = start; cell.metadata.executionOrder = ++this.runIndex; - await notebook.eval(cell); + const response = await notebook.eval(cell); + cell.metadata.runState = vscode.NotebookCellRunState.Success; + cell.metadata.lastRunDuration = +new Date() - cell.metadata.runStartTime; + console.log(`uri: ${cell.uri}, id: ${response.id}, type: ${response.type}, result: ${response.result}`); + switch (response.type) { + case 'text': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Text, + text: response.result, + }]; + break; + case 'plot': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + 'image/svg+xml': (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(), + }, + }]; + break; + case 'viewer': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + 'application/json': response.result, + }, + }]; + break; + case 'browser': + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + 'application/json': response.result, + }, + }]; + break; + case 'error': + cell.metadata.runState = vscode.NotebookCellRunState.Error; + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Error, + evalue: response.result, + ename: '', + traceback: [], + }]; + break; + } } catch (e) { cell.outputs = [{ outputKind: vscode.CellOutputKind.Error, @@ -413,7 +416,8 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } async cancelAllCellsExecution(document: vscode.NotebookDocument) { - + const notebook = this.notebooks.get(document.uri.toString()); + await notebook.cancel(undefined); } public dispose() { From 70ae405401d7f5e2af1d9a661d600b3654c7c3e9 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 14 Sep 2020 23:03:47 +0800 Subject: [PATCH 58/78] Use onNotebook:r-notebook --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index d88334980..1b5e6cfd8 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "onLanguage:debian-control.r", "workspaceContains:*.{rproj,Rproj,r,R,rd,Rd,rmd,Rmd}", "onNotebookEditor:r-notebook", + "onNotebook:r-notebook", "onCommand:r.createRTerm", "onCommand:r.runSource", "onCommand:r.knitRmd", From cb06e7c5cf5ec5f668cc201d65bc2f7adb2260a5 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 14 Sep 2020 23:27:58 +0800 Subject: [PATCH 59/78] Update src/notebook.ts --- src/notebook.ts | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index 63d522a89..7bebf661e 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -349,45 +349,51 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode cell.metadata.lastRunDuration = +new Date() - cell.metadata.runStartTime; console.log(`uri: ${cell.uri}, id: ${response.id}, type: ${response.type}, result: ${response.result}`); switch (response.type) { - case 'text': + case 'text': { cell.outputs = [{ outputKind: vscode.CellOutputKind.Text, text: response.result, }]; break; - case 'plot': + } + case 'plot': { + const content = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(); cell.outputs = [{ outputKind: vscode.CellOutputKind.Rich, data: { - 'image/svg+xml': (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(), + 'image/svg+xml': content, }, }]; break; - case 'viewer': + } + case 'viewer': { cell.outputs = [{ outputKind: vscode.CellOutputKind.Rich, data: { - 'application/json': response.result, + 'text/plain': response.result, }, }]; break; - case 'browser': + } + case 'browser': { cell.outputs = [{ outputKind: vscode.CellOutputKind.Rich, data: { - 'application/json': response.result, + 'text/plain': response.result, }, }]; break; - case 'error': + } + case 'error': { cell.metadata.runState = vscode.NotebookCellRunState.Error; cell.outputs = [{ outputKind: vscode.CellOutputKind.Error, evalue: response.result, - ename: '', + ename: 'Error', traceback: [], }]; break; + } } } catch (e) { cell.outputs = [{ From 9e2a72d77cb5e63af47a42ffd85601c21ba72c87 Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Sat, 19 Sep 2020 18:10:52 +0800 Subject: [PATCH 60/78] Update vscode.proposed.d.ts --- vscode.proposed.d.ts | 317 ++++++++++++++----------------------------- 1 file changed, 103 insertions(+), 214 deletions(-) diff --git a/vscode.proposed.d.ts b/vscode.proposed.d.ts index a2811eec4..d08e52225 100644 --- a/vscode.proposed.d.ts +++ b/vscode.proposed.d.ts @@ -16,6 +16,30 @@ declare module 'vscode' { + //#region https://github.com/microsoft/vscode/issues/106410 + + export interface CodeActionProvider { + + /** + * Given a code action fill in its [`edit`](#CodeAction.edit)-property, changes to + * all other properties, like title, are ignored. A code action that has an edit + * will not be resolved. + * + * *Note* that a code action provider that returns commands, not code actions, cannot successfully + * implement this function. Returning commands is deprecated and instead code actions should be + * returned. + * + * @param codeAction A code action. + * @param token A cancellation token. + * @return The resolved code action or a thenable that resolve to such. It is OK to return the given + * `item`. When no result is returned, the given `item` will be used. + */ + resolveCodeAction?(codeAction: T, token: CancellationToken): ProviderResult; + } + + //#endregion + + // #region auth provider: https://github.com/microsoft/vscode/issues/88309 /** @@ -1313,6 +1337,7 @@ declare module 'vscode' { } export interface NotebookCell { + readonly index: number; readonly notebook: NotebookDocument; readonly uri: Uri; readonly cellKind: CellKind; @@ -1366,6 +1391,20 @@ declare module 'vscode' { runState?: NotebookRunState; } + export interface NotebookDocumentContentOptions { + /** + * Controls if outputs change will trigger notebook document content change and if it will be used in the diff editor + * Default to false. If the content provider doesn't persisit the outputs in the file document, this should be set to true. + */ + transientOutputs: boolean; + + /** + * Controls if a meetadata property change will trigger notebook document content change and if it will be used in the diff editor + * Default to false. If the content provider doesn't persisit a metadata property in the file document, it should be set to true. + */ + transientMetadata: { [K in keyof NotebookCellMetadata]?: boolean }; + } + export interface NotebookDocument { readonly uri: Uri; readonly version: number; @@ -1374,6 +1413,7 @@ declare module 'vscode' { readonly isDirty: boolean; readonly isUntitled: boolean; readonly cells: ReadonlyArray; + readonly contentOptions: NotebookDocumentContentOptions; languages: string[]; metadata: NotebookDocumentMetadata; } @@ -1399,31 +1439,23 @@ declare module 'vscode' { export interface WorkspaceEdit { replaceNotebookMetadata(uri: Uri, value: NotebookDocumentMetadata): void; - replaceCells(uri: Uri, start: number, end: number, cells: NotebookCellData[], metadata?: WorkspaceEditEntryMetadata): void; - replaceCellOutput(uri: Uri, index: number, outputs: CellOutput[], metadata?: WorkspaceEditEntryMetadata): void; - replaceCellMetadata(uri: Uri, index: number, cellMetadata: NotebookCellMetadata, metadata?: WorkspaceEditEntryMetadata): void; + replaceNotebookCells(uri: Uri, start: number, end: number, cells: NotebookCellData[], metadata?: WorkspaceEditEntryMetadata): void; + replaceNotebookCellOutput(uri: Uri, index: number, outputs: CellOutput[], metadata?: WorkspaceEditEntryMetadata): void; + replaceNotebookCellMetadata(uri: Uri, index: number, cellMetadata: NotebookCellMetadata, metadata?: WorkspaceEditEntryMetadata): void; } export interface NotebookEditorEdit { - - replaceNotebookMetadata(value: NotebookDocumentMetadata): void; - + replaceMetadata(value: NotebookDocumentMetadata): void; replaceCells(start: number, end: number, cells: NotebookCellData[]): void; replaceCellOutput(index: number, outputs: CellOutput[]): void; replaceCellMetadata(index: number, metadata: NotebookCellMetadata): void; - - /** @deprecated */ - replaceOutput(index: number, outputs: CellOutput[]): void; - /** @deprecated */ - replaceMetadata(index: number, metadata: NotebookCellMetadata): void; - /** @deprecated */ - insert(index: number, content: string | string[], language: string, type: CellKind, outputs: CellOutput[], metadata: NotebookCellMetadata | undefined): void; - /** @deprecated */ - delete(index: number): void; } export interface NotebookCellRange { readonly start: number; + /** + * exclusive + */ readonly end: number; } @@ -1503,8 +1535,20 @@ declare module 'vscode' { */ asWebviewUri(localResource: Uri): Uri; + /** + * Perform an edit on the notebook associated with this notebook editor. + * + * The given callback-function is invoked with an [edit-builder](#NotebookEditorEdit) which must + * be used to make edits. Note that the edit-builder is only valid while the + * callback executes. + * + * @param callback A function which can create edits using an [edit-builder](#NotebookEditorEdit). + * @return A promise that resolves with a value indicating if the edits could be applied. + */ edit(callback: (editBuilder: NotebookEditorEdit) => void): Thenable; + setDecorations(decorationType: NotebookEditorDecorationType, range: NotebookCellRange): void; + revealRange(range: NotebookCellRange, revealType?: NotebookEditorRevealType): void; } @@ -1720,9 +1764,11 @@ declare module 'vscode' { cancelAllCellsExecution(document: NotebookDocument): void; } + export type NotebookFilenamePattern = GlobPattern | { include: GlobPattern; exclude: GlobPattern }; + export interface NotebookDocumentFilter { viewType?: string | string[]; - filenamePattern?: GlobPattern | { include: GlobPattern; exclude: GlobPattern }; + filenamePattern?: NotebookFilenamePattern; } export interface NotebookKernelProvider { @@ -1760,21 +1806,31 @@ declare module 'vscode' { dispose(): void; } + export interface NotebookDecorationRenderOptions { + backgroundColor?: string | ThemeColor; + borderColor?: string | ThemeColor; + top: ThemableDecorationAttachmentRenderOptions; + } + + export interface NotebookEditorDecorationType { + readonly key: string; + dispose(): void; + } + + export namespace notebook { export function registerNotebookContentProvider( notebookType: string, provider: NotebookContentProvider, - options?: { + options?: NotebookDocumentContentOptions & { /** - * Controls if outputs change will trigger notebook document content change and if it will be used in the diff editor - * Default to false. If the content provider doesn't persisit the outputs in the file document, this should be set to true. + * Not ready for production or development use yet. */ - transientOutputs: boolean; - /** - * Controls if a meetadata property change will trigger notebook document content change and if it will be used in the diff editor - * Default to false. If the content provider doesn't persisit a metadata property in the file document, it should be set to true. - */ - transientMetadata: { [K in keyof NotebookCellMetadata]?: boolean } + viewOptions?: { + displayName: string; + filenamePattern: NotebookFilenamePattern[]; + exclusive?: boolean; + }; } ): Disposable; @@ -1783,6 +1839,7 @@ declare module 'vscode' { provider: NotebookKernelProvider ): Disposable; + export function createNotebookEditorDecorationType(options: NotebookDecorationRenderOptions): NotebookEditorDecorationType; export const onDidOpenNotebookDocument: Event; export const onDidCloseNotebookDocument: Event; export const onDidSaveNotebookDocument: Event; @@ -2040,32 +2097,6 @@ declare module 'vscode' { //#endregion - //#region Support `scmResourceState` in `when` clauses #86180 https://github.com/microsoft/vscode/issues/86180 - - export interface SourceControlResourceState { - /** - * Context value of the resource state. This can be used to contribute resource specific actions. - * For example, if a resource is given a context value as `diffable`. When contributing actions to `scm/resourceState/context` - * using `menus` extension point, you can specify context value for key `scmResourceState` in `when` expressions, like `scmResourceState == diffable`. - * ``` - * "contributes": { - * "menus": { - * "scm/resourceState/context": [ - * { - * "command": "extension.diff", - * "when": "scmResourceState == diffable" - * } - * ] - * } - * } - * ``` - * This will show action `extension.diff` only for resources with `contextValue` is `diffable`. - */ - readonly contextValue?: string; - } - - //#endregion - //#region https://github.com/microsoft/vscode/issues/104436 export enum ExtensionRuntime { @@ -2098,169 +2129,6 @@ declare module 'vscode' { } //#endregion - - //#region https://github.com/microsoft/vscode/issues/46585 - - /** - * A webview based view. - */ - export interface WebviewView { - /** - * Identifies the type of the webview view, such as `'hexEditor.dataView'`. - */ - readonly viewType: string; - - /** - * The underlying webview for the view. - */ - readonly webview: Webview; - - /** - * View title displayed in the UI. - * - * The view title is initially taken from the extension `package.json` contribution. - */ - title?: string; - - /** - * Human-readable string which is rendered less prominently in the title. - */ - description?: string; - - /** - * Event fired when the view is disposed. - * - * Views are disposed when they are explicitly hidden by a user (this happens when a user - * right clicks in a view and unchecks the webview view). - * - * Trying to use the view after it has been disposed throws an exception. - */ - readonly onDidDispose: Event; - - /** - * Tracks if the webview is currently visible. - * - * Views are visible when they are on the screen and expanded. - */ - readonly visible: boolean; - - /** - * Event fired when the visibility of the view changes. - * - * Actions that trigger a visibility change: - * - * - The view is collapsed or expanded. - * - The user switches to a different view group in the sidebar or panel. - * - * Note that hiding a view using the context menu instead disposes of the view and fires `onDidDispose`. - */ - readonly onDidChangeVisibility: Event; - - /** - * Reveal the view in the UI. - * - * If the view is collapsed, this will expand it. - * - * @param preserveFocus When `true` the view will not take focus. - */ - show(preserveFocus?: boolean): void; - } - - /** - * Additional information the webview view being resolved. - * - * @param T Type of the webview's state. - */ - interface WebviewViewResolveContext { - /** - * Persisted state from the webview content. - * - * To save resources, VS Code normally deallocates webview documents (the iframe content) that are not visible. - * For example, when the user collapse a view or switches to another top level activity in the sidebar, the - * `WebviewView` itself is kept alive but the webview's underlying document is deallocated. It is recreated when - * the view becomes visible again. - * - * You can prevent this behavior by setting `retainContextWhenHidden` in the `WebviewOptions`. However this - * increases resource usage and should be avoided wherever possible. Instead, you can use persisted state to - * save off a webview's state so that it can be quickly recreated as needed. - * - * To save off a persisted state, inside the webview call `acquireVsCodeApi().setState()` with - * any json serializable object. To restore the state again, call `getState()`. For example: - * - * ```js - * // Within the webview - * const vscode = acquireVsCodeApi(); - * - * // Get existing state - * const oldState = vscode.getState() || { value: 0 }; - * - * // Update state - * setState({ value: oldState.value + 1 }) - * ``` - * - * VS Code ensures that the persisted state is saved correctly when a webview is hidden and across - * editor restarts. - */ - readonly state: T | undefined; - } - - /** - * Provider for creating `WebviewView` elements. - */ - export interface WebviewViewProvider { - /** - * Revolves a webview view. - * - * `resolveWebviewView` is called when a view first becomes visible. This may happen when the view is - * first loaded or when the user hides and then shows a view again. - * - * @param webviewView Webview view to restore. The serializer should take ownership of this view. The - * provider must set the webview's `.html` and hook up all webview events it is interested in. - * @param context Additional metadata about the view being resolved. - * @param token Cancellation token indicating that the view being provided is no longer needed. - * - * @return Optional thenable indicating that the view has been fully resolved. - */ - resolveWebviewView(webviewView: WebviewView, context: WebviewViewResolveContext, token: CancellationToken): Thenable | void; - } - - namespace window { - /** - * Register a new provider for webview views. - * - * @param viewId Unique id of the view. This should match the `id` from the - * `views` contribution in the package.json. - * @param provider Provider for the webview views. - * - * @return Disposable that unregisters the provider. - */ - export function registerWebviewViewProvider(viewId: string, provider: WebviewViewProvider, options?: { - /** - * Content settings for the webview created for this view. - */ - readonly webviewOptions?: { - /** - * Controls if the webview element itself (iframe) is kept around even when the view - * is no longer visible. - * - * Normally the webview's html context is created when the view becomes visible - * and destroyed when it is hidden. Extensions that have complex state - * or UI can set the `retainContextWhenHidden` to make VS Code keep the webview - * context around, even when the webview moves to a background tab. When a webview using - * `retainContextWhenHidden` becomes hidden, its scripts and other dynamic content are suspended. - * When the view becomes visible again, the context is automatically restored - * in the exact same state it was in originally. You cannot send messages to a - * hidden webview, even with `retainContextWhenHidden` enabled. - * - * `retainContextWhenHidden` has a high memory overhead and should only be used if - * your view's context cannot be quickly saved and restored. - */ - readonly retainContextWhenHidden?: boolean; - }; - }): Disposable; - } - //#endregion - //#region export interface FileSystem { @@ -2282,4 +2150,25 @@ declare module 'vscode' { //#endregion + + //#region https://github.com/microsoft/vscode/issues/105667 + + export interface TreeView { + /** + * An optional human-readable description that will be rendered in the title of the view. + * Setting the title description to null, undefined, or empty string will remove the title description from the view. + */ + description?: string | undefined; + } + //#endregion + + //#region https://github.com/microsoft/vscode/issues/103120 @alexr00 + export class ThemeIcon2 extends ThemeIcon { + /** + * Returns a new `ThemeIcon` that will use the specified `ThemeColor` + * @param color The `ThemeColor` to use for the icon. + */ + with(color: ThemeColor): ThemeIcon2; + } + //#endregion } From 77b4c01b1fe83b2a33c682a5a28238405f1c489e Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 12 Oct 2020 16:11:44 +0800 Subject: [PATCH 61/78] Update vscode.proposed.d.ts --- vscode.proposed.d.ts | 174 +++++++++++++++++++++++-------------------- 1 file changed, 94 insertions(+), 80 deletions(-) diff --git a/vscode.proposed.d.ts b/vscode.proposed.d.ts index d08e52225..a3ad64e0d 100644 --- a/vscode.proposed.d.ts +++ b/vscode.proposed.d.ts @@ -16,30 +16,6 @@ declare module 'vscode' { - //#region https://github.com/microsoft/vscode/issues/106410 - - export interface CodeActionProvider { - - /** - * Given a code action fill in its [`edit`](#CodeAction.edit)-property, changes to - * all other properties, like title, are ignored. A code action that has an edit - * will not be resolved. - * - * *Note* that a code action provider that returns commands, not code actions, cannot successfully - * implement this function. Returning commands is deprecated and instead code actions should be - * returned. - * - * @param codeAction A code action. - * @param token A cancellation token. - * @return The resolved code action or a thenable that resolve to such. It is OK to return the given - * `item`. When no result is returned, the given `item` will be used. - */ - resolveCodeAction?(codeAction: T, token: CancellationToken): ProviderResult; - } - - //#endregion - - // #region auth provider: https://github.com/microsoft/vscode/issues/88309 /** @@ -167,6 +143,31 @@ declare module 'vscode' { * provider */ export function logout(providerId: string, sessionId: string): Thenable; + + /** + * Retrieve a password that was stored with key. Returns undefined if there + * is no password matching that key. + * @param key The key the password was stored under. + */ + export function getPassword(key: string): Thenable; + + /** + * Store a password under a given key. + * @param key The key to store the password under + * @param value The password + */ + export function setPassword(key: string, value: string): Thenable; + + /** + * Remove a password from storage. + * @param key The key the password was stored under. + */ + export function deletePassword(key: string): Thenable; + + /** + * Fires when a password is set or deleted. + */ + export const onDidChangePassword: Event; } //#endregion @@ -741,74 +742,65 @@ declare module 'vscode' { //#region file-decorations: https://github.com/microsoft/vscode/issues/54938 - // TODO@jrieken FileDecoration, FileDecorationProvider etc. - // TODO@jrieken Add selector notion to limit decorations to a view. - // TODO@jrieken Rename `Decoration.letter` to `short` so that it could be used for coverage et al. - export class Decoration { + export class FileDecoration { /** - * A letter that represents this decoration. + * A very short string that represents this decoration. */ - letter?: string; + badge?: string; /** - * The human-readable title for this decoration. + * A human-readable tooltip for this decoration. */ - title?: string; + tooltip?: string; /** * The color of this decoration. */ color?: ThemeColor; - /** - * The priority of this decoration. - */ - priority?: number; - /** * A flag expressing that this decoration should be - * propagted to its parents. + * propagated to its parents. */ - bubble?: boolean; + propagate?: boolean; /** * Creates a new decoration. * - * @param letter A letter that represents the decoration. - * @param title The title of the decoration. + * @param badge A letter that represents the decoration. + * @param tooltip The tooltip of the decoration. * @param color The color of the decoration. */ - constructor(letter?: string, title?: string, color?: ThemeColor); + constructor(badge?: string, tooltip?: string, color?: ThemeColor); } /** * The decoration provider interfaces defines the contract between extensions and * file decorations. */ - export interface DecorationProvider { + export interface FileDecorationProvider { /** * An event to signal decorations for one or many files have changed. * * @see [EventEmitter](#EventEmitter */ - onDidChangeDecorations: Event; + onDidChange: Event; /** * Provide decorations for a given uri. * - * * @param uri The uri of the file to provide a decoration for. * @param token A cancellation token. * @returns A decoration or a thenable that resolves to such. */ - provideDecoration(uri: Uri, token: CancellationToken): ProviderResult; + provideFileDecoration(uri: Uri, token: CancellationToken): ProviderResult; } export namespace window { - export function registerDecorationProvider(provider: DecorationProvider): Disposable; + export function registerDecorationProvider(provider: FileDecorationProvider): Disposable; } //#endregion @@ -1259,6 +1251,27 @@ declare module 'vscode' { export type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput; + export class NotebookCellOutputItem { + + readonly mime: string; + readonly value: unknown; + readonly metadata?: Record; + + constructor(mime: string, value: unknown, metadata?: Record); + } + + //TODO@jrieken add id? + export class NotebookCellOutput { + + readonly outputs: NotebookCellOutputItem[]; + readonly metadata?: Record; + + constructor(outputs: NotebookCellOutputItem[], metadata?: Record); + + //TODO@jrieken HACK to workaround dependency issues... + toJSON(): any; + } + export enum NotebookCellRunState { Running = 1, Idle = 2, @@ -1440,14 +1453,14 @@ declare module 'vscode' { export interface WorkspaceEdit { replaceNotebookMetadata(uri: Uri, value: NotebookDocumentMetadata): void; replaceNotebookCells(uri: Uri, start: number, end: number, cells: NotebookCellData[], metadata?: WorkspaceEditEntryMetadata): void; - replaceNotebookCellOutput(uri: Uri, index: number, outputs: CellOutput[], metadata?: WorkspaceEditEntryMetadata): void; + replaceNotebookCellOutput(uri: Uri, index: number, outputs: (NotebookCellOutput | CellOutput)[], metadata?: WorkspaceEditEntryMetadata): void; replaceNotebookCellMetadata(uri: Uri, index: number, cellMetadata: NotebookCellMetadata, metadata?: WorkspaceEditEntryMetadata): void; } export interface NotebookEditorEdit { replaceMetadata(value: NotebookDocumentMetadata): void; replaceCells(start: number, end: number, cells: NotebookCellData[]): void; - replaceCellOutput(index: number, outputs: CellOutput[]): void; + replaceCellOutput(index: number, outputs: (NotebookCellOutput | CellOutput)[]): void; replaceCellMetadata(index: number, metadata: NotebookCellMetadata): void; } @@ -1497,16 +1510,6 @@ declare module 'vscode' { */ readonly viewColumn?: ViewColumn; - /** - * Whether the panel is active (focused by the user). - */ - readonly active: boolean; - - /** - * Whether the panel is visible. - */ - readonly visible: boolean; - /** * Fired when the panel is disposed. */ @@ -1685,7 +1688,7 @@ declare module 'vscode' { /** * Unique identifier for the backup. * - * This id is passed back to your extension in `openCustomDocument` when opening a notebook editor from a backup. + * This id is passed back to your extension in `openNotebook` when opening a notebook editor from a backup. */ readonly id: string; @@ -1739,6 +1742,10 @@ declare module 'vscode' { } export interface NotebookContentProvider { + readonly options?: NotebookDocumentContentOptions; + readonly onDidChangeNotebookContentOptions?: Event; + readonly onDidChangeNotebook: Event; + /** * Content providers should always use [file system providers](#FileSystemProvider) to * resolve the raw content for `uri` as the resouce is not necessarily a file on disk. @@ -1747,7 +1754,6 @@ declare module 'vscode' { resolveNotebook(document: NotebookDocument, webview: NotebookCommunication): Promise; saveNotebook(document: NotebookDocument, cancellation: CancellationToken): Promise; saveNotebookAs(targetResource: Uri, document: NotebookDocument, cancellation: CancellationToken): Promise; - readonly onDidChangeNotebook: Event; backupNotebook(document: NotebookDocument, context: NotebookDocumentBackupContext, cancellation: CancellationToken): Promise; } @@ -1840,6 +1846,7 @@ declare module 'vscode' { ): Disposable; export function createNotebookEditorDecorationType(options: NotebookDecorationRenderOptions): NotebookEditorDecorationType; + export function openNotebookDocument(uri: Uri, viewType?: string): Promise; export const onDidOpenNotebookDocument: Event; export const onDidCloseNotebookDocument: Event; export const onDidSaveNotebookDocument: Event; @@ -1848,14 +1855,6 @@ declare module 'vscode' { * All currently known notebook documents. */ export const notebookDocuments: ReadonlyArray; - - export const visibleNotebookEditors: NotebookEditor[]; - export const onDidChangeVisibleNotebookEditors: Event; - - export const activeNotebookEditor: NotebookEditor | undefined; - export const onDidChangeActiveNotebookEditor: Event; - export const onDidChangeNotebookEditorSelection: Event; - export const onDidChangeNotebookEditorVisibleRanges: Event; export const onDidChangeNotebookDocumentMetadata: Event; export const onDidChangeNotebookCells: Event; export const onDidChangeCellOutputs: Event; @@ -1884,6 +1883,15 @@ declare module 'vscode' { export function createCellStatusBarItem(cell: NotebookCell, alignment?: NotebookCellStatusBarAlignment, priority?: number): NotebookCellStatusBarItem; } + export namespace window { + export const visibleNotebookEditors: NotebookEditor[]; + export const onDidChangeVisibleNotebookEditors: Event; + export const activeNotebookEditor: NotebookEditor | undefined; + export const onDidChangeActiveNotebookEditor: Event; + export const onDidChangeNotebookEditorSelection: Event; + export const onDidChangeNotebookEditorVisibleRanges: Event; + } + //#endregion //#region https://github.com/microsoft/vscode/issues/39441 @@ -2129,7 +2137,7 @@ declare module 'vscode' { } //#endregion - //#region + //#region https://github.com/microsoft/vscode/issues/91697 export interface FileSystem { /** @@ -2151,24 +2159,30 @@ declare module 'vscode' { //#endregion - //#region https://github.com/microsoft/vscode/issues/105667 + //#region https://github.com/microsoft/vscode/issues/103120 @alexr00 + export class ThemeIcon2 extends ThemeIcon { + + /** + * The id of the icon. The available icons are listed in https://microsoft.github.io/vscode-codicons/dist/codicon.html. + */ + public readonly id: string; - export interface TreeView { /** - * An optional human-readable description that will be rendered in the title of the view. - * Setting the title description to null, undefined, or empty string will remove the title description from the view. + * Creates a reference to a theme icon. + * @param id id of the icon. The available icons are listed in https://microsoft.github.io/vscode-codicons/dist/codicon.html. + * @param color optional `ThemeColor` for the icon. */ - description?: string | undefined; + constructor(id: string, color?: ThemeColor); } //#endregion - //#region https://github.com/microsoft/vscode/issues/103120 @alexr00 - export class ThemeIcon2 extends ThemeIcon { + //#region https://github.com/microsoft/vscode/issues/102665 Comment API @rebornix + export interface CommentThread { /** - * Returns a new `ThemeIcon` that will use the specified `ThemeColor` - * @param color The `ThemeColor` to use for the icon. + * Whether the thread supports reply. + * Defaults to true. */ - with(color: ThemeColor): ThemeIcon2; + canReply: boolean; } //#endregion } From 87a4c8a4f57fc3c4ba42de2f492a983e9daad97d Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Mon, 12 Oct 2020 16:11:52 +0800 Subject: [PATCH 62/78] Rename interface --- src/notebook.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/notebook.ts b/src/notebook.ts index 7bebf661e..7bf6eb9c0 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -3,13 +3,13 @@ import net = require('net'); import { spawn, ChildProcess } from 'child_process'; import { dirname } from 'path'; -interface RSessionRequest { +interface RKernelRequest { id: number; type: 'eval' | 'cancel'; expr?: any; } -interface RSessionResponse { +interface RKernelResponse { id: number; type: 'text' | 'plot' | 'viewer' | 'browser' | 'error'; result: string; @@ -29,7 +29,7 @@ class RKernel { this.doc = doc; } - private request(request: RSessionRequest) { + private request(request: RKernelRequest) { if (this.socket) { const json = JSON.stringify(request); this.socket.write(`Content-Length: ${json.length}\n${json}`); @@ -93,11 +93,11 @@ class RKernel { await this.start(); } - public async eval(cell: vscode.NotebookCell): Promise { + public async eval(cell: vscode.NotebookCell): Promise { if (this.socket) { return new Promise((resolve, reject) => { const handler = async (data: Buffer) => { - const response: RSessionResponse = JSON.parse(data.toString()); + const response: RKernelResponse = JSON.parse(data.toString()); resolve(response); this.socket.removeListener('data', handler); }; @@ -140,7 +140,7 @@ class RNotebook implements vscode.Disposable { this.kernel.restart(); } - public async eval(cell: vscode.NotebookCell): Promise { + public async eval(cell: vscode.NotebookCell): Promise { await this.kernel.start(); return this.kernel.eval(cell); } From 8e73f03a07cf256766aa234685447dca3c1de787 Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Wed, 3 Feb 2021 10:57:07 +0100 Subject: [PATCH 63/78] updates vscode proposed --- vscode.proposed.d.ts | 1961 +++++++++++++++++++++++++----------------- 1 file changed, 1190 insertions(+), 771 deletions(-) diff --git a/vscode.proposed.d.ts b/vscode.proposed.d.ts index a3ad64e0d..ee5d812bc 100644 --- a/vscode.proposed.d.ts +++ b/vscode.proposed.d.ts @@ -16,7 +16,7 @@ declare module 'vscode' { - // #region auth provider: https://github.com/microsoft/vscode/issues/88309 + //#region auth provider: https://github.com/microsoft/vscode/issues/88309 /** * An [event](#Event) which fires when an [AuthenticationProvider](#AuthenticationProvider) is added or removed. @@ -54,28 +54,9 @@ declare module 'vscode' { } /** - * **WARNING** When writing an AuthenticationProvider, `id` should be treated as part of your extension's - * API, changing it is a breaking change for all extensions relying on the provider. The id is - * treated case-sensitively. + * A provider for performing authentication to a service. */ export interface AuthenticationProvider { - /** - * Used as an identifier for extensions trying to work with a particular - * provider: 'microsoft', 'github', etc. id must be unique, registering - * another provider with the same id will fail. - */ - readonly id: string; - - /** - * The human-readable name of the provider. - */ - readonly label: string; - - /** - * Whether it is possible to be signed into multiple accounts at once with this provider - */ - readonly supportsMultipleAccounts: boolean; - /** * An [event](#Event) which fires when the array of sessions has changed, or data * within a session has changed. @@ -85,31 +66,48 @@ declare module 'vscode' { /** * Returns an array of current sessions. */ + // eslint-disable-next-line vscode-dts-provider-naming getSessions(): Thenable>; /** * Prompts a user to login. */ + // eslint-disable-next-line vscode-dts-provider-naming login(scopes: string[]): Thenable; /** * Removes the session corresponding to session id. * @param sessionId The session id to log out of */ + // eslint-disable-next-line vscode-dts-provider-naming logout(sessionId: string): Thenable; } + /** + * Options for creating an [AuthenticationProvider](#AuthentcationProvider). + */ + export interface AuthenticationProviderOptions { + /** + * Whether it is possible to be signed into multiple accounts at once with this provider. + * If not specified, will default to false. + */ + readonly supportsMultipleAccounts?: boolean; + } + export namespace authentication { /** * Register an authentication provider. * * There can only be one provider per id and an error is being thrown when an id - * has already been used by another provider. + * has already been used by another provider. Ids are case-sensitive. * + * @param id The unique identifier of the provider. + * @param label The human-readable name of the provider. * @param provider The authentication provider provider. + * @params options Additional options for the provider. * @return A [disposable](#Disposable) that unregisters this provider when being disposed. */ - export function registerAuthenticationProvider(provider: AuthenticationProvider): Disposable; + export function registerAuthenticationProvider(id: string, label: string, provider: AuthenticationProvider, options?: AuthenticationProviderOptions): Disposable; /** * @deprecated - getSession should now trigger extension activation. @@ -117,63 +115,32 @@ declare module 'vscode' { */ export const onDidChangeAuthenticationProviders: Event; - /** - * @deprecated - * The ids of the currently registered authentication providers. - * @returns An array of the ids of authentication providers that are currently registered. - */ - export function getProviderIds(): Thenable>; - - /** - * @deprecated - * An array of the ids of authentication providers that are currently registered. - */ - export const providerIds: ReadonlyArray; - /** * An array of the information of authentication providers that are currently registered. */ export const providers: ReadonlyArray; /** - * @deprecated * Logout of a specific session. * @param providerId The id of the provider to use * @param sessionId The session id to remove * provider */ export function logout(providerId: string, sessionId: string): Thenable; + } - /** - * Retrieve a password that was stored with key. Returns undefined if there - * is no password matching that key. - * @param key The key the password was stored under. - */ - export function getPassword(key: string): Thenable; - - /** - * Store a password under a given key. - * @param key The key to store the password under - * @param value The password - */ - export function setPassword(key: string, value: string): Thenable; + //#endregion - /** - * Remove a password from storage. - * @param key The key the password was stored under. - */ - export function deletePassword(key: string): Thenable; + // eslint-disable-next-line vscode-dts-region-comments + //#region @alexdima - resolvers + export interface MessageOptions { /** - * Fires when a password is set or deleted. + * Do not render a native message box. */ - export const onDidChangePassword: Event; + useCustom?: boolean; } - //#endregion - - //#region @alexdima - resolvers - export interface RemoteAuthorityResolverContext { resolveAttempt: number; } @@ -181,8 +148,9 @@ declare module 'vscode' { export class ResolvedAuthority { readonly host: string; readonly port: number; + readonly connectionToken: string | undefined; - constructor(host: string, port: number); + constructor(host: string, port: number, connectionToken?: string); } export interface ResolvedOptions { @@ -194,18 +162,20 @@ declare module 'vscode' { // The desired local port. If this port can't be used, then another will be chosen. localAddressPort?: number; label?: string; + public?: boolean; } export interface TunnelDescription { remoteAddress: { port: number, host: string; }; //The complete local address(ex. localhost:1234) localAddress: { port: number, host: string; } | string; + public?: boolean; } export interface Tunnel extends TunnelDescription { // Implementers of Tunnel should fire onDidDispose when dispose is called. onDidDispose: Event; - dispose(): void; + dispose(): void | Thenable; } /** @@ -222,6 +192,13 @@ declare module 'vscode' { } + export interface TunnelCreationOptions { + /** + * True when the local operating system will require elevation to use the requested local port. + */ + elevationRequired?: boolean; + } + export type ResolverResult = ResolvedAuthority & ResolvedOptions & TunnelInformation; export class RemoteAuthorityResolverError extends Error { @@ -237,13 +214,25 @@ declare module 'vscode' { * Can be optionally implemented if the extension can forward ports better than the core. * When not implemented, the core will use its default forwarding logic. * When implemented, the core will use this to forward ports. + * + * To enable the "Change Local Port" action on forwarded ports, make sure to set the `localAddress` of + * the returned `Tunnel` to a `{ port: number, host: string; }` and not a string. */ - tunnelFactory?: (tunnelOptions: TunnelOptions) => Thenable | undefined; + tunnelFactory?: (tunnelOptions: TunnelOptions, tunnelCreationOptions: TunnelCreationOptions) => Thenable | undefined; - /** + /**p * Provides filtering for candidate ports. */ showCandidatePort?: (host: string, port: number, detail: string) => Thenable; + + /** + * Lets the resolver declare which tunnel factory features it supports. + * UNDER DISCUSSION! MAY CHANGE SOON. + */ + tunnelFeatures?: { + elevation: boolean; + public: boolean; + }; } export namespace workspace { @@ -740,71 +729,7 @@ declare module 'vscode' { //#endregion - //#region file-decorations: https://github.com/microsoft/vscode/issues/54938 - - - export class FileDecoration { - - /** - * A very short string that represents this decoration. - */ - badge?: string; - - /** - * A human-readable tooltip for this decoration. - */ - tooltip?: string; - - /** - * The color of this decoration. - */ - color?: ThemeColor; - - /** - * A flag expressing that this decoration should be - * propagated to its parents. - */ - propagate?: boolean; - - /** - * Creates a new decoration. - * - * @param badge A letter that represents the decoration. - * @param tooltip The tooltip of the decoration. - * @param color The color of the decoration. - */ - constructor(badge?: string, tooltip?: string, color?: ThemeColor); - } - - /** - * The decoration provider interfaces defines the contract between extensions and - * file decorations. - */ - export interface FileDecorationProvider { - - /** - * An event to signal decorations for one or many files have changed. - * - * @see [EventEmitter](#EventEmitter - */ - onDidChange: Event; - - /** - * Provide decorations for a given uri. - * - * @param uri The uri of the file to provide a decoration for. - * @param token A cancellation token. - * @returns A decoration or a thenable that resolves to such. - */ - provideFileDecoration(uri: Uri, token: CancellationToken): ProviderResult; - } - - export namespace window { - export function registerDecorationProvider(provider: FileDecorationProvider): Disposable; - } - - //#endregion - + // eslint-disable-next-line vscode-dts-region-comments //#region debug /** @@ -823,47 +748,9 @@ declare module 'vscode' { // Properties: see details [here](https://microsoft.github.io/debug-adapter-protocol/specification#Base_Protocol_Variable). } - // deprecated debug API - - export interface DebugConfigurationProvider { - /** - * Deprecated, use DebugAdapterDescriptorFactory.provideDebugAdapter instead. - * @deprecated Use DebugAdapterDescriptorFactory.createDebugAdapterDescriptor instead - */ - debugAdapterExecutable?(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult; - } - - //#endregion - - //#region LogLevel: https://github.com/microsoft/vscode/issues/85992 - - /** - * @deprecated DO NOT USE, will be removed - */ - export enum LogLevel { - Trace = 1, - Debug = 2, - Info = 3, - Warning = 4, - Error = 5, - Critical = 6, - Off = 7 - } - - export namespace env { - /** - * @deprecated DO NOT USE, will be removed - */ - export const logLevel: LogLevel; - - /** - * @deprecated DO NOT USE, will be removed - */ - export const onDidChangeLogLevel: Event; - } - //#endregion + // eslint-disable-next-line vscode-dts-region-comments //#region @joaomoreno: SCM validation /** @@ -914,6 +801,7 @@ declare module 'vscode' { //#endregion + // eslint-disable-next-line vscode-dts-region-comments //#region @joaomoreno: SCM selected provider export interface SourceControl { @@ -989,63 +877,18 @@ declare module 'vscode' { //#endregion + // eslint-disable-next-line vscode-dts-region-comments //#region @jrieken -> exclusive document filters export interface DocumentFilter { - exclusive?: boolean; + readonly exclusive?: boolean; } //#endregion - //#region @alexdima - OnEnter enhancement - export interface OnEnterRule { - /** - * This rule will only execute if the text above the this line matches this regular expression. - */ - oneLineAboveText?: RegExp; - } - //#endregion - - //#region Tree View: https://github.com/microsoft/vscode/issues/61313 - /** - * Label describing the [Tree item](#TreeItem) - */ - export interface TreeItemLabel { - - /** - * A human-readable string describing the [Tree item](#TreeItem). - */ - label: string; - - /** - * Ranges in the label to highlight. A range is defined as a tuple of two number where the - * first is the inclusive start index and the second the exclusive end index - */ - highlights?: [number, number][]; - - } - - // https://github.com/microsoft/vscode/issues/100741 - export interface TreeDataProvider { - resolveTreeItem?(element: T, item: TreeItem2): TreeItem2 | Thenable; - } - - export class TreeItem2 extends TreeItem { - /** - * Label describing this item. When `falsy`, it is derived from [resourceUri](#TreeItem.resourceUri). - */ - label?: string | TreeItemLabel | /* for compilation */ any; - - /** - * Content to be shown when you hover over the tree item. - */ - tooltip?: string | MarkdownString | /* for compilation */ any; - - /** - * @param label Label describing this item - * @param collapsibleState [TreeItemCollapsibleState](#TreeItemCollapsibleState) of the tree item. Default is [TreeItemCollapsibleState.None](#TreeItemCollapsibleState.None) - */ - constructor(label: TreeItemLabel, collapsibleState?: TreeItemCollapsibleState); + //#region Tree View: https://github.com/microsoft/vscode/issues/61313 @alexr00 + export interface TreeView extends Disposable { + reveal(element: T | undefined, options?: { select?: boolean, focus?: boolean, expand?: boolean | number; }): Thenable; } //#endregion @@ -1111,45 +954,6 @@ declare module 'vscode' { //#endregion - //#region OnTypeRename: https://github.com/microsoft/vscode/issues/88424 - - /** - * The rename provider interface defines the contract between extensions and - * the live-rename feature. - */ - export interface OnTypeRenameProvider { - /** - * Provide a list of ranges that can be live renamed together. - * - * @param document The document in which the command was invoked. - * @param position The position at which the command was invoked. - * @param token A cancellation token. - * @return A list of ranges that can be live-renamed togehter. The ranges must have - * identical length and contain identical text content. The ranges cannot overlap. Optional a word pattern - * that overrides the word pattern defined when registering the provider. Live rename stops as soon as the renamed content - * no longer matches the word pattern. - */ - provideOnTypeRenameRanges(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<{ ranges: Range[]; wordPattern?: RegExp; }>; - } - - namespace languages { - /** - * Register a rename provider that works on type. - * - * Multiple providers can be registered for a language. In that case providers are sorted - * by their [score](#languages.match) and the best-matching provider is used. Failure - * of the selected provider will cause a failure of the whole operation. - * - * @param selector A selector that defines the documents this provider is applicable to. - * @param provider An on type rename provider. - * @param wordPattern Word pattern for this provider. - * @return A [disposable](#Disposable) that unregisters this provider when being disposed. - */ - export function registerOnTypeRenameProvider(selector: DocumentSelector, provider: OnTypeRenameProvider, wordPattern?: RegExp): Disposable; - } - - //#endregion - //#region Custom editor move https://github.com/microsoft/vscode/issues/86146 // TODO: Also for custom editor @@ -1168,6 +972,7 @@ declare module 'vscode' { * * @return Thenable indicating that the webview editor has been moved. */ + // eslint-disable-next-line vscode-dts-provider-naming moveCustomTextEditor?(newDocument: TextDocument, existingWebviewPanel: WebviewPanel, token: CancellationToken): Thenable; } @@ -1184,94 +989,13 @@ declare module 'vscode' { //#endregion - //#region @rebornix: Notebook + //#region https://github.com/microsoft/vscode/issues/106744, Notebooks (misc) export enum CellKind { Markdown = 1, Code = 2 } - export enum CellOutputKind { - Text = 1, - Error = 2, - Rich = 3 - } - - export interface CellStreamOutput { - outputKind: CellOutputKind.Text; - text: string; - } - - export interface CellErrorOutput { - outputKind: CellOutputKind.Error; - /** - * Exception Name - */ - ename: string; - /** - * Exception Value - */ - evalue: string; - /** - * Exception call stack - */ - traceback: string[]; - } - - export interface NotebookCellOutputMetadata { - /** - * Additional attributes of a cell metadata. - */ - custom?: { [key: string]: any }; - } - - export interface CellDisplayOutput { - outputKind: CellOutputKind.Rich; - /** - * { mime_type: value } - * - * Example: - * ```json - * { - * "outputKind": vscode.CellOutputKind.Rich, - * "data": { - * "text/html": [ - * "

Hello

" - * ], - * "text/plain": [ - * "" - * ] - * } - * } - */ - data: { [key: string]: any; }; - - readonly metadata?: NotebookCellOutputMetadata; - } - - export type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput; - - export class NotebookCellOutputItem { - - readonly mime: string; - readonly value: unknown; - readonly metadata?: Record; - - constructor(mime: string, value: unknown, metadata?: Record); - } - - //TODO@jrieken add id? - export class NotebookCellOutput { - - readonly outputs: NotebookCellOutputItem[]; - readonly metadata?: Record; - - constructor(outputs: NotebookCellOutputItem[], metadata?: Record); - - //TODO@jrieken HACK to workaround dependency issues... - toJSON(): any; - } - export enum NotebookCellRunState { Running = 1, Idle = 2, @@ -1346,7 +1070,7 @@ declare module 'vscode' { /** * Additional attributes of a cell metadata. */ - custom?: { [key: string]: any }; + custom?: { [key: string]: any; }; } export interface NotebookCell { @@ -1356,7 +1080,9 @@ declare module 'vscode' { readonly cellKind: CellKind; readonly document: TextDocument; readonly language: string; + /** @deprecated use WorkspaceEdit.replaceCellOutput */ outputs: CellOutput[]; + /** @deprecated use WorkspaceEdit.replaceCellMetadata */ metadata: NotebookCellMetadata; } @@ -1396,12 +1122,23 @@ declare module 'vscode' { /** * Additional attributes of the document metadata. */ - custom?: { [key: string]: any }; + custom?: { [key: string]: any; }; /** * The document's current run state */ runState?: NotebookRunState; + + /** + * Whether the document is trusted, default to true + * When false, insecure outputs like HTML, JavaScript, SVG will not be rendered. + */ + trusted?: boolean; + + /** + * Languages the document supports + */ + languages?: string[]; } export interface NotebookDocumentContentOptions { @@ -1431,46 +1168,13 @@ declare module 'vscode' { metadata: NotebookDocumentMetadata; } - export interface NotebookConcatTextDocument { - uri: Uri; - isClosed: boolean; - dispose(): void; - onDidChange: Event; - version: number; - getText(): string; - getText(range: Range): string; - - offsetAt(position: Position): number; - positionAt(offset: number): Position; - validateRange(range: Range): Range; - validatePosition(position: Position): Position; - - locationAt(positionOrRange: Position | Range): Location; - positionAt(location: Location): Position; - contains(uri: Uri): boolean - } - - export interface WorkspaceEdit { - replaceNotebookMetadata(uri: Uri, value: NotebookDocumentMetadata): void; - replaceNotebookCells(uri: Uri, start: number, end: number, cells: NotebookCellData[], metadata?: WorkspaceEditEntryMetadata): void; - replaceNotebookCellOutput(uri: Uri, index: number, outputs: (NotebookCellOutput | CellOutput)[], metadata?: WorkspaceEditEntryMetadata): void; - replaceNotebookCellMetadata(uri: Uri, index: number, cellMetadata: NotebookCellMetadata, metadata?: WorkspaceEditEntryMetadata): void; - } - - export interface NotebookEditorEdit { - replaceMetadata(value: NotebookDocumentMetadata): void; - replaceCells(start: number, end: number, cells: NotebookCellData[]): void; - replaceCellOutput(index: number, outputs: (NotebookCellOutput | CellOutput)[]): void; - replaceCellMetadata(index: number, metadata: NotebookCellMetadata): void; - } - - export interface NotebookCellRange { - readonly start: number; - /** - * exclusive - */ - readonly end: number; - } + export interface NotebookCellRange { + readonly start: number; + /** + * exclusive + */ + readonly end: number; + } export enum NotebookEditorRevealType { /** @@ -1481,11 +1185,17 @@ declare module 'vscode' { * The range will always be revealed in the center of the viewport. */ InCenter = 1, + /** * If the range is outside the viewport, it will be revealed in the center of the viewport. * Otherwise, it will be revealed with as little scrolling as possible. */ InCenterIfOutsideViewport = 2, + + /** + * The range will always be revealed at the top of the viewport. + */ + AtTop = 3 } export interface NotebookEditor { @@ -1497,68 +1207,44 @@ declare module 'vscode' { /** * The primary selected cell on this notebook editor. */ + // todo@API should not be undefined, rather a default readonly selection?: NotebookCell; + // @rebornix + // todo@API should replace selection + // never empty! + // primary/secondary selections + // readonly selections: NotebookCellRange[]; /** * The current visible ranges in the editor (vertically). */ readonly visibleRanges: NotebookCellRange[]; + revealRange(range: NotebookCellRange, revealType?: NotebookEditorRevealType): void; + /** * The column in which this editor shows. */ + // @jrieken + // todo@API maybe never undefined because notebooks always show in the editor area (unlike text editors) + // maybe for notebook diff editor readonly viewColumn?: ViewColumn; /** * Fired when the panel is disposed. */ + // @rebornix REMOVE/REplace NotebookCommunication + // todo@API fishy? notebooks are public objects, there should be a "global" events for this readonly onDidDispose: Event; - - /** - * Active kernel used in the editor - */ - readonly kernel?: NotebookKernel; - - /** - * Fired when the output hosting webview posts a message. - */ - readonly onDidReceiveMessage: Event; - /** - * Post a message to the output hosting webview. - * - * Messages are only delivered if the editor is live. - * - * @param message Body of the message. This must be a string or other json serilizable object. - */ - postMessage(message: any): Thenable; - - /** - * Convert a uri for the local file system to one that can be used inside outputs webview. - */ - asWebviewUri(localResource: Uri): Uri; - - /** - * Perform an edit on the notebook associated with this notebook editor. - * - * The given callback-function is invoked with an [edit-builder](#NotebookEditorEdit) which must - * be used to make edits. Note that the edit-builder is only valid while the - * callback executes. - * - * @param callback A function which can create edits using an [edit-builder](#NotebookEditorEdit). - * @return A promise that resolves with a value indicating if the edits could be applied. - */ - edit(callback: (editBuilder: NotebookEditorEdit) => void): Thenable; - - setDecorations(decorationType: NotebookEditorDecorationType, range: NotebookCellRange): void; - - revealRange(range: NotebookCellRange, revealType?: NotebookEditorRevealType): void; } + // todo@API stale? export interface NotebookOutputSelector { mimeTypes?: string[]; } + // todo@API stale? export interface NotebookRenderRequest { output: CellDisplayOutput; mimeType: string; @@ -1585,6 +1271,7 @@ declare module 'vscode' { readonly changes: ReadonlyArray; } + // todo@API stale? export interface NotebookCellMoveEvent { /** @@ -1621,6 +1308,8 @@ declare module 'vscode' { export interface NotebookEditorSelectionChangeEvent { readonly notebookEditor: NotebookEditor; + // @rebornix + // todo@API show NotebookCellRange[] instead readonly selection?: NotebookCell; } @@ -1633,6 +1322,7 @@ declare module 'vscode' { readonly cellKind: CellKind; readonly source: string; readonly language: string; + // todo@API maybe use a separate data type? readonly outputs: CellOutput[]; readonly metadata: NotebookCellMetadata | undefined; } @@ -1643,71 +1333,6 @@ declare module 'vscode' { readonly metadata: NotebookDocumentMetadata; } - interface NotebookDocumentContentChangeEvent { - - /** - * The document that the edit is for. - */ - readonly document: NotebookDocument; - } - - interface NotebookDocumentEditEvent { - - /** - * The document that the edit is for. - */ - readonly document: NotebookDocument; - - /** - * Undo the edit operation. - * - * This is invoked by VS Code when the user undoes this edit. To implement `undo`, your - * extension should restore the document and editor to the state they were in just before this - * edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`. - */ - undo(): Thenable | void; - - /** - * Redo the edit operation. - * - * This is invoked by VS Code when the user redoes this edit. To implement `redo`, your - * extension should restore the document and editor to the state they were in just after this - * edit was added to VS Code's internal edit stack by `onDidChangeCustomDocument`. - */ - redo(): Thenable | void; - - /** - * Display name describing the edit. - * - * This will be shown to users in the UI for undo/redo operations. - */ - readonly label?: string; - } - - interface NotebookDocumentBackup { - /** - * Unique identifier for the backup. - * - * This id is passed back to your extension in `openNotebook` when opening a notebook editor from a backup. - */ - readonly id: string; - - /** - * Delete the current backup. - * - * This is called by VS Code when it is clear the current backup is no longer needed, such as when a new backup - * is made or when the file is saved. - */ - delete(): void; - } - - interface NotebookDocumentBackupContext { - readonly destination: Uri; - } - - interface NotebookDocumentOpenContext { - readonly backupId?: string; - } /** * Communication object passed to the {@link NotebookContentProvider} and @@ -1731,7 +1356,7 @@ declare module 'vscode' { * * Messages are only delivered if the editor is live. * - * @param message Body of the message. This must be a string or other json serilizable object. + * @param message Body of the message. This must be a string or other json serializable object. */ postMessage(message: any): Thenable; @@ -1739,116 +1364,28 @@ declare module 'vscode' { * Convert a uri for the local file system to one that can be used inside outputs webview. */ asWebviewUri(localResource: Uri): Uri; - } - - export interface NotebookContentProvider { - readonly options?: NotebookDocumentContentOptions; - readonly onDidChangeNotebookContentOptions?: Event; - readonly onDidChangeNotebook: Event; - - /** - * Content providers should always use [file system providers](#FileSystemProvider) to - * resolve the raw content for `uri` as the resouce is not necessarily a file on disk. - */ - openNotebook(uri: Uri, openContext: NotebookDocumentOpenContext): NotebookData | Promise; - resolveNotebook(document: NotebookDocument, webview: NotebookCommunication): Promise; - saveNotebook(document: NotebookDocument, cancellation: CancellationToken): Promise; - saveNotebookAs(targetResource: Uri, document: NotebookDocument, cancellation: CancellationToken): Promise; - backupNotebook(document: NotebookDocument, context: NotebookDocumentBackupContext, cancellation: CancellationToken): Promise; - } - - export interface NotebookKernel { - readonly id?: string; - label: string; - description?: string; - detail?: string; - isPreferred?: boolean; - preloads?: Uri[]; - executeCell(document: NotebookDocument, cell: NotebookCell): void; - cancelCellExecution(document: NotebookDocument, cell: NotebookCell): void; - executeAllCells(document: NotebookDocument): void; - cancelAllCellsExecution(document: NotebookDocument): void; - } - - export type NotebookFilenamePattern = GlobPattern | { include: GlobPattern; exclude: GlobPattern }; - - export interface NotebookDocumentFilter { - viewType?: string | string[]; - filenamePattern?: NotebookFilenamePattern; - } - - export interface NotebookKernelProvider { - onDidChangeKernels?: Event; - provideKernels(document: NotebookDocument, token: CancellationToken): ProviderResult; - resolveKernel?(kernel: T, document: NotebookDocument, webview: NotebookCommunication, token: CancellationToken): ProviderResult; - } - - /** - * Represents the alignment of status bar items. - */ - export enum NotebookCellStatusBarAlignment { - /** - * Aligned to the left side. - */ - Left = 1, - - /** - * Aligned to the right side. - */ - Right = 2 + // @rebornix + // readonly onDidDispose: Event; } - export interface NotebookCellStatusBarItem { - readonly cell: NotebookCell; - readonly alignment: NotebookCellStatusBarAlignment; - readonly priority?: number; - text: string; - tooltip: string | undefined; - command: string | Command | undefined; - accessibilityInformation?: AccessibilityInformation; - show(): void; - hide(): void; - dispose(): void; - } + // export function registerNotebookKernel(selector: string, kernel: NotebookKernel): Disposable; - export interface NotebookDecorationRenderOptions { - backgroundColor?: string | ThemeColor; - borderColor?: string | ThemeColor; - top: ThemableDecorationAttachmentRenderOptions; - } - export interface NotebookEditorDecorationType { - readonly key: string; - dispose(): void; + export interface NotebookDocumentShowOptions { + viewColumn?: ViewColumn; + preserveFocus?: boolean; + preview?: boolean; + selection?: NotebookCellRange; } - export namespace notebook { - export function registerNotebookContentProvider( - notebookType: string, - provider: NotebookContentProvider, - options?: NotebookDocumentContentOptions & { - /** - * Not ready for production or development use yet. - */ - viewOptions?: { - displayName: string; - filenamePattern: NotebookFilenamePattern[]; - exclusive?: boolean; - }; - } - ): Disposable; - - export function registerNotebookKernelProvider( - selector: NotebookDocumentFilter, - provider: NotebookKernelProvider - ): Disposable; - export function createNotebookEditorDecorationType(options: NotebookDecorationRenderOptions): NotebookEditorDecorationType; - export function openNotebookDocument(uri: Uri, viewType?: string): Promise; + export function openNotebookDocument(uri: Uri, viewType?: string): Thenable; export const onDidOpenNotebookDocument: Event; export const onDidCloseNotebookDocument: Event; + + // todo@API really needed? export const onDidSaveNotebookDocument: Event; /** @@ -1860,27 +1397,6 @@ declare module 'vscode' { export const onDidChangeCellOutputs: Event; export const onDidChangeCellLanguage: Event; export const onDidChangeCellMetadata: Event; - /** - * Create a document that is the concatenation of all notebook cells. By default all code-cells are included - * but a selector can be provided to narrow to down the set of cells. - * - * @param notebook - * @param selector - */ - export function createConcatTextDocument(notebook: NotebookDocument, selector?: DocumentSelector): NotebookConcatTextDocument; - - export const onDidChangeActiveNotebookKernel: Event<{ document: NotebookDocument, kernel: NotebookKernel | undefined }>; - - /** - * Creates a notebook cell status bar [item](#NotebookCellStatusBarItem). - * It will be disposed automatically when the notebook document is closed or the cell is deleted. - * - * @param cell The cell on which this item should be shown. - * @param alignment The alignment of the item. - * @param priority The priority of the item. Higher values mean the item should be shown more to the left. - * @return A new status bar item. - */ - export function createCellStatusBarItem(cell: NotebookCell, alignment?: NotebookCellStatusBarAlignment, priority?: number): NotebookCellStatusBarItem; } export namespace window { @@ -1890,299 +1406,1202 @@ declare module 'vscode' { export const onDidChangeActiveNotebookEditor: Event; export const onDidChangeNotebookEditorSelection: Event; export const onDidChangeNotebookEditorVisibleRanges: Event; + export function showNotebookDocument(document: NotebookDocument, options?: NotebookDocumentShowOptions): Thenable; } //#endregion - //#region https://github.com/microsoft/vscode/issues/39441 + //#region https://github.com/microsoft/vscode/issues/106744, NotebookCellOutput - export interface CompletionItem { - /** - * Will be merged into CompletionItem#label - */ - label2?: CompletionItemLabel; + export enum CellOutputKind { + Text = 1, + Error = 2, + Rich = 3 } - export interface CompletionItemLabel { - /** - * The function or variable. Rendered leftmost. - */ - name: string; + export interface CellStreamOutput { + outputKind: CellOutputKind.Text; + text: string; + } + export interface CellErrorOutput { + outputKind: CellOutputKind.Error; /** - * The parameters without the return type. Render after `name`. + * Exception Name */ - parameters?: string; - + ename: string; /** - * The fully qualified name, like package name or file path. Rendered after `signature`. + * Exception Value */ - qualifier?: string; - + evalue: string; + /** + * Exception call stack + */ + traceback: string[]; + } + + export interface NotebookCellOutputMetadata { + /** + * Additional attributes of a cell metadata. + */ + custom?: { [key: string]: any; }; + } + + export interface CellDisplayOutput { + outputKind: CellOutputKind.Rich; + /** + * { mime_type: value } + * + * Example: + * ```json + * { + * "outputKind": vscode.CellOutputKind.Rich, + * "data": { + * "text/html": [ + * "

Hello

" + * ], + * "text/plain": [ + * "" + * ] + * } + * } + */ + data: { [key: string]: any; }; + + readonly metadata?: NotebookCellOutputMetadata; + } + + export type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput; + + export class NotebookCellOutputItem { + + readonly mime: string; + readonly value: unknown; + readonly metadata?: Record; + + constructor(mime: string, value: unknown, metadata?: Record); + } + + //TODO@jrieken add id? + export class NotebookCellOutput { + + readonly outputs: NotebookCellOutputItem[]; + readonly metadata?: Record; + + constructor(outputs: NotebookCellOutputItem[], metadata?: Record); + + //TODO@jrieken HACK to workaround dependency issues... + toJSON(): any; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/106744, NotebookEditorEdit + + export interface WorkspaceEdit { + replaceNotebookMetadata(uri: Uri, value: NotebookDocumentMetadata): void; + replaceNotebookCells(uri: Uri, start: number, end: number, cells: NotebookCellData[], metadata?: WorkspaceEditEntryMetadata): void; + replaceNotebookCellOutput(uri: Uri, index: number, outputs: (NotebookCellOutput | CellOutput)[], metadata?: WorkspaceEditEntryMetadata): void; + replaceNotebookCellMetadata(uri: Uri, index: number, cellMetadata: NotebookCellMetadata, metadata?: WorkspaceEditEntryMetadata): void; + } + + export interface NotebookEditorEdit { + replaceMetadata(value: NotebookDocumentMetadata): void; + replaceCells(start: number, end: number, cells: NotebookCellData[]): void; + replaceCellOutput(index: number, outputs: (NotebookCellOutput | CellOutput)[]): void; + replaceCellMetadata(index: number, metadata: NotebookCellMetadata): void; + } + + export interface NotebookEditor { + /** + * Perform an edit on the notebook associated with this notebook editor. + * + * The given callback-function is invoked with an [edit-builder](#NotebookEditorEdit) which must + * be used to make edits. Note that the edit-builder is only valid while the + * callback executes. + * + * @param callback A function which can create edits using an [edit-builder](#NotebookEditorEdit). + * @return A promise that resolves with a value indicating if the edits could be applied. + */ + // @jrieken REMOVE maybe + edit(callback: (editBuilder: NotebookEditorEdit) => void): Thenable; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/106744, NotebookContentProvider + + interface NotebookDocumentBackup { + /** + * Unique identifier for the backup. + * + * This id is passed back to your extension in `openNotebook` when opening a notebook editor from a backup. + */ + readonly id: string; + + /** + * Delete the current backup. + * + * This is called by VS Code when it is clear the current backup is no longer needed, such as when a new backup + * is made or when the file is saved. + */ + delete(): void; + } + + interface NotebookDocumentBackupContext { + readonly destination: Uri; + } + + interface NotebookDocumentOpenContext { + readonly backupId?: string; + } + + export interface NotebookContentProvider { + readonly options?: NotebookDocumentContentOptions; + readonly onDidChangeNotebookContentOptions?: Event; + /** + * Content providers should always use [file system providers](#FileSystemProvider) to + * resolve the raw content for `uri` as the resouce is not necessarily a file on disk. + */ + // eslint-disable-next-line vscode-dts-provider-naming + openNotebook(uri: Uri, openContext: NotebookDocumentOpenContext): NotebookData | Thenable; + // eslint-disable-next-line vscode-dts-provider-naming + // eslint-disable-next-line vscode-dts-cancellation + resolveNotebook(document: NotebookDocument, webview: NotebookCommunication): Thenable; + // eslint-disable-next-line vscode-dts-provider-naming + saveNotebook(document: NotebookDocument, cancellation: CancellationToken): Thenable; + // eslint-disable-next-line vscode-dts-provider-naming + saveNotebookAs(targetResource: Uri, document: NotebookDocument, cancellation: CancellationToken): Thenable; + // eslint-disable-next-line vscode-dts-provider-naming + backupNotebook(document: NotebookDocument, context: NotebookDocumentBackupContext, cancellation: CancellationToken): Thenable; + + // ??? + // provideKernels(document: NotebookDocument, token: CancellationToken): ProviderResult; + } + + export namespace notebook { + + // TODO@api use NotebookDocumentFilter instead of just notebookType:string? + // TODO@API options duplicates the more powerful variant on NotebookContentProvider + export function registerNotebookContentProvider(notebookType: string, provider: NotebookContentProvider, + options?: NotebookDocumentContentOptions & { + /** + * Not ready for production or development use yet. + */ + viewOptions?: { + displayName: string; + filenamePattern: NotebookFilenamePattern[]; + exclusive?: boolean; + }; + } + ): Disposable; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/106744, NotebookKernel + + export interface NotebookKernel { + readonly id?: string; + label: string; + description?: string; + detail?: string; + isPreferred?: boolean; + preloads?: Uri[]; + // @roblourens + // todo@API change to `executeCells(document: NotebookDocument, cells: NotebookCellRange[], context:{isWholeNotebooke: boolean}, token: CancelationToken): void;` + // todo@API interrupt vs cancellation, https://github.com/microsoft/vscode/issues/106741 + // interrupt?():void; + executeCell(document: NotebookDocument, cell: NotebookCell): void; + cancelCellExecution(document: NotebookDocument, cell: NotebookCell): void; + executeAllCells(document: NotebookDocument): void; + cancelAllCellsExecution(document: NotebookDocument): void; + } + + export type NotebookFilenamePattern = GlobPattern | { include: GlobPattern; exclude: GlobPattern; }; + + // todo@API why not for NotebookContentProvider? + export interface NotebookDocumentFilter { + viewType?: string | string[]; + filenamePattern?: NotebookFilenamePattern; + } + + // todo@API very unclear, provider MUST not return alive object but only data object + // todo@API unclear how the flow goes + export interface NotebookKernelProvider { + onDidChangeKernels?: Event; + provideKernels(document: NotebookDocument, token: CancellationToken): ProviderResult; + resolveKernel?(kernel: T, document: NotebookDocument, webview: NotebookCommunication, token: CancellationToken): ProviderResult; + } + + export interface NotebookEditor { + /** + * Active kernel used in the editor + */ + // todo@API unsure about that + // kernel, kernel selection, kernel provider + readonly kernel?: NotebookKernel; + } + + export namespace notebook { + export const onDidChangeActiveNotebookKernel: Event<{ document: NotebookDocument, kernel: NotebookKernel | undefined; }>; + + export function registerNotebookKernelProvider(selector: NotebookDocumentFilter, provider: NotebookKernelProvider): Disposable; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/106744, NotebookEditorDecorationType + + export interface NotebookEditor { + setDecorations(decorationType: NotebookEditorDecorationType, range: NotebookCellRange): void; + } + + export interface NotebookDecorationRenderOptions { + backgroundColor?: string | ThemeColor; + borderColor?: string | ThemeColor; + top: ThemableDecorationAttachmentRenderOptions; + } + + export interface NotebookEditorDecorationType { + readonly key: string; + dispose(): void; + } + + export namespace notebook { + export function createNotebookEditorDecorationType(options: NotebookDecorationRenderOptions): NotebookEditorDecorationType; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/106744, NotebookCellStatusBarItem + + /** + * Represents the alignment of status bar items. + */ + export enum NotebookCellStatusBarAlignment { + + /** + * Aligned to the left side. + */ + Left = 1, + + /** + * Aligned to the right side. + */ + Right = 2 + } + + export interface NotebookCellStatusBarItem { + readonly cell: NotebookCell; + readonly alignment: NotebookCellStatusBarAlignment; + readonly priority?: number; + text: string; + tooltip: string | undefined; + command: string | Command | undefined; + accessibilityInformation?: AccessibilityInformation; + show(): void; + hide(): void; + dispose(): void; + } + + export namespace notebook { + /** + * Creates a notebook cell status bar [item](#NotebookCellStatusBarItem). + * It will be disposed automatically when the notebook document is closed or the cell is deleted. + * + * @param cell The cell on which this item should be shown. + * @param alignment The alignment of the item. + * @param priority The priority of the item. Higher values mean the item should be shown more to the left. + * @return A new status bar item. + */ + // @roblourens + // todo@API this should be a provider, https://github.com/microsoft/vscode/issues/105809 + export function createCellStatusBarItem(cell: NotebookCell, alignment?: NotebookCellStatusBarAlignment, priority?: number): NotebookCellStatusBarItem; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/106744, NotebookConcatTextDocument + + export namespace notebook { + /** + * Create a document that is the concatenation of all notebook cells. By default all code-cells are included + * but a selector can be provided to narrow to down the set of cells. + * + * @param notebook + * @param selector + */ + // @jrieken REMOVE. p_never + // todo@API really needed? we didn't find a user here + export function createConcatTextDocument(notebook: NotebookDocument, selector?: DocumentSelector): NotebookConcatTextDocument; + } + + export interface NotebookConcatTextDocument { + uri: Uri; + isClosed: boolean; + dispose(): void; + onDidChange: Event; + version: number; + getText(): string; + getText(range: Range): string; + + offsetAt(position: Position): number; + positionAt(offset: number): Position; + validateRange(range: Range): Range; + validatePosition(position: Position): Position; + + locationAt(positionOrRange: Position | Range): Location; + positionAt(location: Location): Position; + contains(uri: Uri): boolean; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/39441 + + export interface CompletionItem { + /** + * Will be merged into CompletionItem#label + */ + label2?: CompletionItemLabel; + } + + export interface CompletionItemLabel { + /** + * The function or variable. Rendered leftmost. + */ + name: string; + + /** + * The parameters without the return type. Render after `name`. + */ + parameters?: string; + + /** + * The fully qualified name, like package name or file path. Rendered after `signature`. + */ + qualifier?: string; + /** * The return-type of a function or type of a property/variable. Rendered rightmost. */ - type?: string; - } + type?: string; + } + + //#endregion + + //#region @eamodio - timeline: https://github.com/microsoft/vscode/issues/84297 + + export class TimelineItem { + /** + * A timestamp (in milliseconds since 1 January 1970 00:00:00) for when the timeline item occurred. + */ + timestamp: number; + + /** + * A human-readable string describing the timeline item. + */ + label: string; + + /** + * Optional id for the timeline item. It must be unique across all the timeline items provided by this source. + * + * If not provided, an id is generated using the timeline item's timestamp. + */ + id?: string; + + /** + * The icon path or [ThemeIcon](#ThemeIcon) for the timeline item. + */ + iconPath?: Uri | { light: Uri; dark: Uri; } | ThemeIcon; + + /** + * A human readable string describing less prominent details of the timeline item. + */ + description?: string; + + /** + * The tooltip text when you hover over the timeline item. + */ + detail?: string; + + /** + * The [command](#Command) that should be executed when the timeline item is selected. + */ + command?: Command; + + /** + * Context value of the timeline item. This can be used to contribute specific actions to the item. + * For example, a timeline item is given a context value as `commit`. When contributing actions to `timeline/item/context` + * using `menus` extension point, you can specify context value for key `timelineItem` in `when` expression like `timelineItem == commit`. + * ``` + * "contributes": { + * "menus": { + * "timeline/item/context": [ + * { + * "command": "extension.copyCommitId", + * "when": "timelineItem == commit" + * } + * ] + * } + * } + * ``` + * This will show the `extension.copyCommitId` action only for items where `contextValue` is `commit`. + */ + contextValue?: string; + + /** + * Accessibility information used when screen reader interacts with this timeline item. + */ + accessibilityInformation?: AccessibilityInformation; + + /** + * @param label A human-readable string describing the timeline item + * @param timestamp A timestamp (in milliseconds since 1 January 1970 00:00:00) for when the timeline item occurred + */ + constructor(label: string, timestamp: number); + } + + export interface TimelineChangeEvent { + /** + * The [uri](#Uri) of the resource for which the timeline changed. + */ + uri: Uri; + + /** + * A flag which indicates whether the entire timeline should be reset. + */ + reset?: boolean; + } + + export interface Timeline { + readonly paging?: { + /** + * A provider-defined cursor specifying the starting point of timeline items which are after the ones returned. + * Use `undefined` to signal that there are no more items to be returned. + */ + readonly cursor: string | undefined; + }; + + /** + * An array of [timeline items](#TimelineItem). + */ + readonly items: readonly TimelineItem[]; + } + + export interface TimelineOptions { + /** + * A provider-defined cursor specifying the starting point of the timeline items that should be returned. + */ + cursor?: string; + + /** + * An optional maximum number timeline items or the all timeline items newer (inclusive) than the timestamp or id that should be returned. + * If `undefined` all timeline items should be returned. + */ + limit?: number | { timestamp: number; id?: string; }; + } + + export interface TimelineProvider { + /** + * An optional event to signal that the timeline for a source has changed. + * To signal that the timeline for all resources (uris) has changed, do not pass any argument or pass `undefined`. + */ + onDidChange?: Event; + + /** + * An identifier of the source of the timeline items. This can be used to filter sources. + */ + readonly id: string; + + /** + * A human-readable string describing the source of the timeline items. This can be used as the display label when filtering sources. + */ + readonly label: string; + + /** + * Provide [timeline items](#TimelineItem) for a [Uri](#Uri). + * + * @param uri The [uri](#Uri) of the file to provide the timeline for. + * @param options A set of options to determine how results should be returned. + * @param token A cancellation token. + * @return The [timeline result](#TimelineResult) or a thenable that resolves to such. The lack of a result + * can be signaled by returning `undefined`, `null`, or an empty array. + */ + provideTimeline(uri: Uri, options: TimelineOptions, token: CancellationToken): ProviderResult; + } + + export namespace workspace { + /** + * Register a timeline provider. + * + * Multiple providers can be registered. In that case, providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param scheme A scheme or schemes that defines which documents this provider is applicable to. Can be `*` to target all documents. + * @param provider A timeline provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerTimelineProvider(scheme: string | string[], provider: TimelineProvider): Disposable; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/91555 + + export enum StandardTokenType { + Other = 0, + Comment = 1, + String = 2, + RegEx = 4 + } + + export interface TokenInformation { + type: StandardTokenType; + range: Range; + } + + export namespace languages { + export function getTokenInformationAtPosition(document: TextDocument, position: Position): Thenable; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/16221 + + export namespace languages { + /** + * Register a inline hints provider. + * + * Multiple providers can be registered for a language. In that case providers are asked in + * parallel and the results are merged. A failing provider (rejected promise or exception) will + * not cause a failure of the whole operation. + * + * @param selector A selector that defines the documents this provider is applicable to. + * @param provider An inline hints provider. + * @return A [disposable](#Disposable) that unregisters this provider when being disposed. + */ + export function registerInlineHintsProvider(selector: DocumentSelector, provider: InlineHintsProvider): Disposable; + } + + /** + * Inline hint information. + */ + export class InlineHint { + /** + * The text of the hint. + */ + text: string; + /** + * The range of the hint. + */ + range: Range; + /** + * Tooltip when hover on the hint. + */ + description?: string | MarkdownString; + /** + * Whitespace before the hint. + */ + whitespaceBefore?: boolean; + /** + * Whitespace after the hint. + */ + whitespaceAfter?: boolean; + + /** + * Creates a new inline hint information object. + * + * @param text The text of the hint. + * @param range The range of the hint. + * @param hoverMessage Tooltip when hover on the hint. + * @param whitespaceBefore Whitespace before the hint. + * @param whitespaceAfter TWhitespace after the hint. + */ + constructor(text: string, range: Range, description?: string | MarkdownString, whitespaceBefore?: boolean, whitespaceAfter?: boolean); + } + + /** + * The inline hints provider interface defines the contract between extensions and + * the inline hints feature. + */ + export interface InlineHintsProvider { + + /** + * An optional event to signal that inline hints have changed. + * @see [EventEmitter](#EventEmitter) + */ + onDidChangeInlineHints?: Event; + + /** + * @param model The document in which the command was invoked. + * @param range The range for which line hints should be computed. + * @param token A cancellation token. + * + * @return A list of arguments labels or a thenable that resolves to such. + */ + provideInlineHints(model: TextDocument, range: Range, token: CancellationToken): ProviderResult; + } + //#endregion + + //#region https://github.com/microsoft/vscode/issues/104436 + + export enum ExtensionRuntime { + /** + * The extension is running in a NodeJS extension host. Runtime access to NodeJS APIs is available. + */ + Node = 1, + /** + * The extension is running in a Webworker extension host. Runtime access is limited to Webworker APIs. + */ + Webworker = 2 + } + + export interface ExtensionContext { + readonly extensionRuntime: ExtensionRuntime; + } + + //#endregion + + //#region https://github.com/microsoft/vscode/issues/102091 + + export interface TextDocument { + + /** + * The [notebook](#NotebookDocument) that contains this document as a notebook cell or `undefined` when + * the document is not contained by a notebook (this should be the more frequent case). + */ + notebook: NotebookDocument | undefined; + } + //#endregion + + //#region https://github.com/microsoft/vscode/issues/107467 + /* + General activation events: + - `onLanguage:*` most test extensions will want to activate when their + language is opened to provide code lenses. + - `onTests:*` new activation event very simiular to `workspaceContains`, + but only fired when the user wants to run tests or opens the test explorer. + */ + export namespace test { + /** + * Registers a provider that discovers tests for the given document + * selectors. It is activated when either tests need to be enumerated, or + * a document matching the selector is opened. + */ + export function registerTestProvider(testProvider: TestProvider): Disposable; + + /** + * Runs tests with the given options. If no options are given, then + * all tests are run. Returns the resulting test run. + */ + export function runTests(options: TestRunOptions, cancellationToken?: CancellationToken): Thenable; + + /** + * Returns an observer that retrieves tests in the given workspace folder. + */ + export function createWorkspaceTestObserver(workspaceFolder: WorkspaceFolder): TestObserver; - //#endregion + /** + * Returns an observer that retrieves tests in the given text document. + */ + export function createDocumentTestObserver(document: TextDocument): TestObserver; - //#region @eamodio - timeline: https://github.com/microsoft/vscode/issues/84297 + /** + * The last or selected test run. Cleared when a new test run starts. + */ + export const testResults: TestResults | undefined; - export class TimelineItem { /** - * A timestamp (in milliseconds since 1 January 1970 00:00:00) for when the timeline item occurred. + * Event that fires when the testResults are updated. */ - timestamp: number; + export const onDidChangeTestResults: Event; + } + export interface TestResults { /** - * A human-readable string describing the timeline item. + * The results from the latest test run. The array contains a snapshot of + * all tests involved in the run at the moment when it completed. */ - label: string; + readonly tests: ReadonlyArray | undefined; + } + export interface TestObserver { /** - * Optional id for the timeline item. It must be unique across all the timeline items provided by this source. - * - * If not provided, an id is generated using the timeline item's timestamp. + * List of tests returned by test provider for files in the workspace. */ - id?: string; + readonly tests: ReadonlyArray; /** - * The icon path or [ThemeIcon](#ThemeIcon) for the timeline item. + * An event that fires when an existing test in the collection changes, or + * null if a top-level test was added or removed. When fired, the consumer + * should check the test item and all its children for changes. */ - iconPath?: Uri | { light: Uri; dark: Uri; } | ThemeIcon; + readonly onDidChangeTest: Event; /** - * A human readable string describing less prominent details of the timeline item. + * An event the fires when all test providers have signalled that the tests + * the observer references have been discovered. Providers may continue to + * watch for changes and cause {@link onDidChangeTest} to fire as files + * change, until the observer is disposed. + * + * @todo as below */ - description?: string; + readonly onDidDiscoverInitialTests: Event; /** - * The tooltip text when you hover over the timeline item. + * Dispose of the observer, allowing VS Code to eventually tell test + * providers that they no longer need to update tests. */ - detail?: string; + dispose(): void; + } + export interface TestChangeEvent { /** - * The [command](#Command) that should be executed when the timeline item is selected. + * List of all tests that are newly added. */ - command?: Command; + readonly added: ReadonlyArray; /** - * Context value of the timeline item. This can be used to contribute specific actions to the item. - * For example, a timeline item is given a context value as `commit`. When contributing actions to `timeline/item/context` - * using `menus` extension point, you can specify context value for key `timelineItem` in `when` expression like `timelineItem == commit`. - * ``` - * "contributes": { - * "menus": { - * "timeline/item/context": [ - * { - * "command": "extension.copyCommitId", - * "when": "timelineItem == commit" - * } - * ] - * } - * } - * ``` - * This will show the `extension.copyCommitId` action only for items where `contextValue` is `commit`. + * List of existing tests that have updated. */ - contextValue?: string; + readonly updated: ReadonlyArray; /** - * Accessibility information used when screen reader interacts with this timeline item. + * List of existing tests that have been removed. */ - accessibilityInformation?: AccessibilityInformation; + readonly removed: ReadonlyArray; /** - * @param label A human-readable string describing the timeline item - * @param timestamp A timestamp (in milliseconds since 1 January 1970 00:00:00) for when the timeline item occurred + * Highest node in the test tree under which changes were made. This can + * be easily plugged into events like the TreeDataProvider update event. */ - constructor(label: string, timestamp: number); + readonly commonChangeAncestor: RequiredTestItem | null; } - export interface TimelineChangeEvent { + /** + * Tree of tests returned from the provide methods in the {@link TestProvider}. + */ + export interface TestHierarchy { /** - * The [uri](#Uri) of the resource for which the timeline changed. + * Root node for tests. The `testRoot` instance must not be replaced over + * the lifespan of the TestHierarchy, since you will need to reference it + * in `onDidChangeTest` when a test is added or removed. */ - uri: Uri; + readonly root: T; /** - * A flag which indicates whether the entire timeline should be reset. + * An event that fires when an existing test under the `root` changes. + * This can be a result of a state change in a test run, a property update, + * or an update to its children. Changes made to tests will not be visible + * to {@link TestObserver} instances until this event is fired. + * + * This will signal a change recursively to all children of the given node. + * For example, firing the event with the {@link testRoot} will refresh + * all tests. */ - reset?: boolean; - } + readonly onDidChangeTest: Event; - export interface Timeline { - readonly paging?: { - /** - * A provider-defined cursor specifying the starting point of timeline items which are after the ones returned. - * Use `undefined` to signal that there are no more items to be returned. - */ - readonly cursor: string | undefined; - }; + /** + * Promise that should be resolved when all tests that are initially + * defined have been discovered. The provider should continue to watch for + * changes and fire `onDidChangeTest` until the hierarchy is disposed. + */ + readonly discoveredInitialTests?: Thenable; /** - * An array of [timeline items](#TimelineItem). + * Dispose will be called when there are no longer observers interested + * in the hierarchy. */ - readonly items: readonly TimelineItem[]; + dispose(): void; } - export interface TimelineOptions { + /** + * Discovers and provides tests. It's expected that the TestProvider will + * ambiently listen to {@link vscode.window.onDidChangeVisibleTextEditors} to + * provide test information about the open files for use in code lenses and + * other file-specific UI. + * + * Additionally, the UI may request it to discover tests for the workspace + * via `addWorkspaceTests`. + * + * @todo rename from provider + */ + export interface TestProvider { /** - * A provider-defined cursor specifying the starting point of the timeline items that should be returned. + * Requests that tests be provided for the given workspace. This will + * generally be called when tests need to be enumerated for the + * workspace. + * + * It's guaranteed that this method will not be called again while + * there is a previous undisposed watcher for the given workspace folder. */ - cursor?: string; + // eslint-disable-next-line vscode-dts-provider-naming + createWorkspaceTestHierarchy?(workspace: WorkspaceFolder): TestHierarchy | undefined; /** - * An optional maximum number timeline items or the all timeline items newer (inclusive) than the timestamp or id that should be returned. - * If `undefined` all timeline items should be returned. + * Requests that tests be provided for the given document. This will + * be called when tests need to be enumerated for a single open file, + * for instance by code lens UI. */ - limit?: number | { timestamp: number; id?: string; }; + // eslint-disable-next-line vscode-dts-provider-naming + createDocumentTestHierarchy?(document: TextDocument): TestHierarchy | undefined; + + /** + * Starts a test run. This should cause {@link onDidChangeTest} to + * fire with update test states during the run. + * @todo this will eventually need to be able to return a summary report, coverage for example. + */ + // eslint-disable-next-line vscode-dts-provider-naming + runTests?(options: TestRunOptions, cancellationToken: CancellationToken): ProviderResult; } - export interface TimelineProvider { + /** + * Options given to `TestProvider.runTests` + */ + export interface TestRunOptions { /** - * An optional event to signal that the timeline for a source has changed. - * To signal that the timeline for all resources (uris) has changed, do not pass any argument or pass `undefined`. + * Array of specific tests to run. The {@link TestProvider.testRoot} may + * be provided as an indication to run all tests. */ - onDidChange?: Event; + tests: T[]; /** - * An identifier of the source of the timeline items. This can be used to filter sources. + * Whether or not tests in this run should be debugged. */ - readonly id: string; + debug: boolean; + } + /** + * A test item is an item shown in the "test explorer" view. It encompasses + * both a suite and a test, since they have almost or identical capabilities. + */ + export interface TestItem { /** - * A human-readable string describing the source of the timeline items. This can be used as the display label when filtering sources. + * Display name describing the test case. */ - readonly label: string; + label: string; /** - * Provide [timeline items](#TimelineItem) for a [Uri](#Uri). + * Optional unique identifier for the TestItem. This is used to correlate + * test results and tests in the document with those in the workspace + * (test explorer). This must not change for the lifetime of a test item. * - * @param uri The [uri](#Uri) of the file to provide the timeline for. - * @param options A set of options to determine how results should be returned. - * @param token A cancellation token. - * @return The [timeline result](#TimelineResult) or a thenable that resolves to such. The lack of a result - * can be signaled by returning `undefined`, `null`, or an empty array. + * If the ID is not provided, it defaults to the concatenation of the + * item's label and its parent's ID, if any. */ - provideTimeline(uri: Uri, options: TimelineOptions, token: CancellationToken): ProviderResult; - } + readonly id?: string; - export namespace workspace { /** - * Register a timeline provider. - * - * Multiple providers can be registered. In that case, providers are asked in - * parallel and the results are merged. A failing provider (rejected promise or exception) will - * not cause a failure of the whole operation. + * Optional description that appears next to the label. + */ + description?: string; + + /** + * Whether this test item can be run individually, defaults to `true` + * if not provided. * - * @param scheme A scheme or schemes that defines which documents this provider is applicable to. Can be `*` to target all documents. - * @param provider A timeline provider. - * @return A [disposable](#Disposable) that unregisters this provider when being disposed. - */ - export function registerTimelineProvider(scheme: string | string[], provider: TimelineProvider): Disposable; - } + * In some cases, like Go's tests, test can have children but these + * children cannot be run independently. + */ + runnable?: boolean; - //#endregion + /** + * Whether this test item can be debugged. Defaults to `false` if not provided. + */ + debuggable?: boolean; - //#region https://github.com/microsoft/vscode/issues/91555 + /** + * VS Code location. + */ + location?: Location; - export enum StandardTokenType { - Other = 0, - Comment = 1, - String = 2, - RegEx = 4 - } + /** + * Optional list of nested tests for this item. + */ + children?: TestItem[]; - export interface TokenInformation { - type: StandardTokenType; - range: Range; + /** + * Test run state. Will generally be {@link TestRunState.Unset} by + * default. + */ + state: TestState; } - export namespace languages { - export function getTokenInformationAtPosition(document: TextDocument, position: Position): Promise; + /** + * A {@link TestItem} with its defaults filled in. + */ + export type RequiredTestItem = { + [K in keyof Required]: K extends 'children' + ? RequiredTestItem[] + : (K extends 'description' | 'location' ? TestItem[K] : Required[K]) + }; + + export enum TestRunState { + // Initial state + Unset = 0, + // Test will be run, but is not currently running. + Queued = 1, + // Test is currently running + Running = 2, + // Test run has passed + Passed = 3, + // Test run has failed (on an assertion) + Failed = 4, + // Test run has been skipped + Skipped = 5, + // Test run failed for some other reason (compilation error, timeout, etc) + Errored = 6 } - //#endregion + /** + * TestState includes a test and its run state. This is included in the + * {@link TestItem} and is immutable; it should be replaced in th TestItem + * in order to update it. This allows consumers to quickly and easily check + * for changes via object identity. + */ + export class TestState { + /** + * Current state of the test. + */ + readonly runState: TestRunState; - //#region https://github.com/microsoft/vscode/issues/104436 + /** + * Optional duration of the test run, in milliseconds. + */ + readonly duration?: number; - export enum ExtensionRuntime { /** - * The extension is running in a NodeJS extension host. Runtime access to NodeJS APIs is available. + * Associated test run message. Can, for example, contain assertion + * failure information if the test fails. */ - Node = 1, + readonly messages: ReadonlyArray>; + /** - * The extension is running in a Webworker extension host. Runtime access is limited to Webworker APIs. + * @param state Run state to hold in the test state + * @param messages List of associated messages for the test + * @param duration Length of time the test run took, if appropriate. */ - Webworker = 2 + constructor(runState: TestRunState, messages?: TestMessage[], duration?: number); } - export interface ExtensionContext { - readonly extensionRuntime: ExtensionRuntime; + /** + * Represents the severity of test messages. + */ + export enum TestMessageSeverity { + Error = 0, + Warning = 1, + Information = 2, + Hint = 3 } - //#endregion + /** + * Message associated with the test state. Can be linked to a specific + * source range -- useful for assertion failures, for example. + */ + export interface TestMessage { + /** + * Human-readable message text to display. + */ + message: string | MarkdownString; + /** + * Message severity. Defaults to "Error", if not provided. + */ + severity?: TestMessageSeverity; - //#region https://github.com/microsoft/vscode/issues/102091 + /** + * Expected test output. If given with `actual`, a diff view will be shown. + */ + expectedOutput?: string; - export interface TextDocument { + /** + * Actual test output. If given with `actual`, a diff view will be shown. + */ + actualOutput?: string; /** - * The [notebook](#NotebookDocument) that contains this document as a notebook cell or `undefined` when - * the document is not contained by a notebook (this should be the more frequent case). + * Associated file location. */ - notebook: NotebookDocument | undefined; + location?: Location; } + //#endregion - //#region https://github.com/microsoft/vscode/issues/91697 + //#region Opener service (https://github.com/microsoft/vscode/issues/109277) - export interface FileSystem { + /** + * Details if an `ExternalUriOpener` can open a uri. + * + * The priority is also used to rank multiple openers against each other and determine + * if an opener should be selected automatically or if the user should be prompted to + * select an opener. + * + * VS Code will try to use the best available opener, as sorted by `ExternalUriOpenerPriority`. + * If there are multiple potential "best" openers for a URI, then the user will be prompted + * to select an opener. + */ + export enum ExternalUriOpenerPriority { /** - * Check if a given file system supports writing files. + * The opener is disabled and will never be shown to users. * - * Keep in mind that just because a file system supports writing, that does - * not mean that writes will always succeed. There may be permissions issues - * or other errors that prevent writing a file. + * Note that the opener can still be used if the user specifically + * configures it in their settings. + */ + None = 0, + + /** + * The opener can open the uri but will not cause a prompt on its own + * since VS Code always contributes a built-in `Default` opener. + */ + Option = 1, + + /** + * The opener can open the uri. * - * @param scheme The scheme of the filesystem, for example `file` or `git`. + * VS Code's built-in opener has `Default` priority. This means that any additional `Default` + * openers will cause the user to be prompted to select from a list of all potential openers. + */ + Default = 2, + + /** + * The opener can open the uri and should be automatically selected over any + * default openers, include the built-in one from VS Code. * - * @return `true` if the file system supports writing, `false` if it does not - * support writing (i.e. it is readonly), and `undefined` if VS Code does not - * know about the filesystem. + * A preferred opener will be automatically selected if no other preferred openers + * are available. If multiple preferred openers are available, then the user + * is shown a prompt with all potential openers (not just preferred openers). */ - isWritableFileSystem(scheme: string): boolean | undefined; + Preferred = 3, } + /** + * Handles opening uris to external resources, such as http(s) links. + * + * Extensions can implement an `ExternalUriOpener` to open `http` links to a webserver + * inside of VS Code instead of having the link be opened by the web browser. + * + * Currently openers may only be registered for `http` and `https` uris. + */ + export interface ExternalUriOpener { - //#endregion + /** + * Check if the opener can open a uri. + * + * @param uri The uri being opened. This is the uri that the user clicked on. It has + * not yet gone through port forwarding. + * @param token Cancellation token indicating that the result is no longer needed. + * + * @return Priority indicating if the opener can open the external uri. + */ + canOpenExternalUri(uri: Uri, token: CancellationToken): ExternalUriOpenerPriority | Thenable; + + /** + * Open a uri. + * + * This is invoked when: + * + * - The user clicks a link which does not have an assigned opener. In this case, first `canOpenExternalUri` + * is called and if the user selects this opener, then `openExternalUri` is called. + * - The user sets the default opener for a link in their settings and then visits a link. + * + * @param resolvedUri The uri to open. This uri may have been transformed by port forwarding, so it + * may not match the original uri passed to `canOpenExternalUri`. Use `ctx.originalUri` to check the + * original uri. + * @param ctx Additional information about the uri being opened. + * @param token Cancellation token indicating that opening has been canceled. + * + * @return Thenable indicating that the opening has completed. + */ + openExternalUri(resolvedUri: Uri, ctx: OpenExternalUriContext, token: CancellationToken): Thenable | void; + } + + /** + * Additional information about the uri being opened. + */ + interface OpenExternalUriContext { + /** + * The uri that triggered the open. + * + * This is the original uri that the user clicked on or that was passed to `openExternal.` + * Due to port forwarding, this may not match the `resolvedUri` passed to `openExternalUri`. + */ + readonly sourceUri: Uri; + } - //#region https://github.com/microsoft/vscode/issues/103120 @alexr00 - export class ThemeIcon2 extends ThemeIcon { + /** + * Additional metadata about a registered `ExternalUriOpener`. + */ + interface ExternalUriOpenerMetadata { /** - * The id of the icon. The available icons are listed in https://microsoft.github.io/vscode-codicons/dist/codicon.html. + * List of uri schemes the opener is triggered for. + * + * Currently only `http` and `https` are supported. */ - public readonly id: string; + readonly schemes: readonly string[] /** - * Creates a reference to a theme icon. - * @param id id of the icon. The available icons are listed in https://microsoft.github.io/vscode-codicons/dist/codicon.html. - * @param color optional `ThemeColor` for the icon. + * Text displayed to the user that explains what the opener does. + * + * For example, 'Open in browser preview' */ - constructor(id: string, color?: ThemeColor); + readonly label: string; } - //#endregion - //#region https://github.com/microsoft/vscode/issues/102665 Comment API @rebornix - export interface CommentThread { + namespace window { /** - * Whether the thread supports reply. - * Defaults to true. + * Register a new `ExternalUriOpener`. + * + * When a uri is about to be opened, an `onOpenExternalUri:SCHEME` activation event is fired. + * + * @param id Unique id of the opener, such as `myExtension.browserPreview`. This is used in settings + * and commands to identify the opener. + * @param opener Opener to register. + * @param metadata Additional information about the opener. + * + * @returns Disposable that unregisters the opener. + */ + export function registerExternalUriOpener(id: string, opener: ExternalUriOpener, metadata: ExternalUriOpenerMetadata): Disposable; + } + + interface OpenExternalOptions { + /** + * Allows using openers contributed by extensions through `registerExternalUriOpener` + * when opening the resource. + * + * If `true`, VS Code will check if any contributed openers can handle the + * uri, and fallback to the default opener behavior. + * + * If it is string, this specifies the id of the `ExternalUriOpener` + * that should be used if it is available. Use `'default'` to force VS Code's + * standard external opener to be used. */ - canReply: boolean; + readonly allowContributedOpeners?: boolean | string; + } + + namespace env { + export function openExternal(target: Uri, options?: OpenExternalOptions): Thenable; + } + + //#endregion + + //#region https://github.com/Microsoft/vscode/issues/15178 + + // TODO@API must be a class + export interface OpenEditorInfo { + name: string; + resource: Uri; + } + + export namespace window { + export const openEditors: ReadonlyArray; + + // todo@API proper event type + export const onDidChangeOpenEditors: Event; } + //#endregion } From 8c35e7932738a0d55b2a8c21d63b9e52348103ba Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Wed, 3 Feb 2021 14:25:11 +0100 Subject: [PATCH 64/78] missing some things after rebase --- src/extension.ts | 3 ++- vscode.proposed.d.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 02b4fd5bd..5dd8f6723 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -3,6 +3,7 @@ // interfaces, functions, etc. provided by vscode import * as vscode from 'vscode'; +import * as path from 'path'; // functions etc. implemented in this extension import * as preview from './preview'; @@ -171,7 +172,7 @@ export async function activate(context: vscode.ExtensionContext): Promise Date: Wed, 3 Feb 2021 16:50:39 +0100 Subject: [PATCH 65/78] allows output tables --- R/notebook.R | 7 ++- src/notebook.ts | 125 ++++++++++++++++++++++++++++++------------------ 2 files changed, 84 insertions(+), 48 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index ec5ebebb9..5b05455c7 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -54,7 +54,6 @@ r$run(function() { res <- tryCatch({ expr <- parse(text = expr) out <- withVisible(eval(expr, globalenv())) - text <- utils::capture.output(print(out$value, view = TRUE)) if (check_null_dev()) { record <- recordPlot() plot_file <- tempfile(fileext = ".svg") @@ -79,6 +78,12 @@ r$run(function() { result = browser_url ) } else if (out$visible) { + if (inherits(out$value, "data.frame")) { + text <- utils::capture.output(knitr::kable(out$value, format = "html")) + } else { + text <- utils::capture.output(print(out$value, view = TRUE)) + } + list( id = id, type = "text", diff --git a/src/notebook.ts b/src/notebook.ts index 7bf6eb9c0..150b3da29 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -60,6 +60,7 @@ class RKernel { server.listen(0, '127.0.0.1', () => { this.port = (server.address() as net.AddressInfo).port; + // FIXME: grab R path from settings const childProcess = spawn('R', ['--quiet', '--slave', '-f', this.kernelScript, '--args', `port=${this.port}`], { cwd: this.cwd, env: env }); childProcess.stderr.on('data', (chunk: Buffer) => { @@ -301,6 +302,80 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode await vscode.workspace.fs.writeFile(targetResource, Buffer.from(content)); } + async renderPlotOutput(response) { + const content = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(); + + return { + outputKind: vscode.CellOutputKind.Rich, + data: { + 'image/svg+xml': content, + }, + }; + } + + async renderTextOutput(response) { + // Text may contain html, so render as such. + const isXml = response.result.match(/^<.+>$/gms) != null + + if (isXml) { + return { + outputKind: vscode.CellOutputKind.Rich, + data: { + 'text/html': response.result + } + } + } else { + return { + outputKind: vscode.CellOutputKind.Text, + text: response.result, + } + } + } + + async renderOutput(cell, response) { + + switch (response.type) { + case 'text': { + cell.outputs = [await this.renderTextOutput(response)]; + break; + } + case 'plot': { + cell.outputs = [await this.renderPlotOutput(response)] + break; + } + case 'viewer': { + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + // 'text/html': `Here`, + // `, + }, + }]; + break; + } + case 'browser': { + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Rich, + data: { + 'text/plain': response.result, + }, + }]; + break; + } + case 'error': { + cell.metadata.runState = vscode.NotebookCellRunState.Error; + cell.outputs = [{ + outputKind: vscode.CellOutputKind.Error, + evalue: response.result, + ename: 'Error', + traceback: [], + }]; + break; + } + } + } + onDidChangeNotebook = new vscode.EventEmitter().event; async resolveNotebook(): Promise { } @@ -347,54 +422,10 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode const response = await notebook.eval(cell); cell.metadata.runState = vscode.NotebookCellRunState.Success; cell.metadata.lastRunDuration = +new Date() - cell.metadata.runStartTime; + console.log(`uri: ${cell.uri}, id: ${response.id}, type: ${response.type}, result: ${response.result}`); - switch (response.type) { - case 'text': { - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Text, - text: response.result, - }]; - break; - } - case 'plot': { - const content = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(); - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - 'image/svg+xml': content, - }, - }]; - break; - } - case 'viewer': { - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - 'text/plain': response.result, - }, - }]; - break; - } - case 'browser': { - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - 'text/plain': response.result, - }, - }]; - break; - } - case 'error': { - cell.metadata.runState = vscode.NotebookCellRunState.Error; - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Error, - evalue: response.result, - ename: 'Error', - traceback: [], - }]; - break; - } - } + + await this.renderOutput(cell, response) } catch (e) { cell.outputs = [{ outputKind: vscode.CellOutputKind.Error, From 03490104067d782f2adf8bdf9b5e1799b1dfd767 Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Thu, 4 Feb 2021 20:50:44 +0100 Subject: [PATCH 66/78] adds command for restarting kernel --- package.json | 8 +++++++- src/extension.ts | 32 ++++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 1b5e6cfd8..18cc75666 100644 --- a/package.json +++ b/package.json @@ -616,7 +616,13 @@ "title": "Open help for selection", "category": "R", "command": "r.helpPanel.openForSelection" - } + }, + { + "title": "Restart Kernel", + "command": "r.notebook.restartKernel", + "icon": "$(refresh)", + "category": "R" + } ], "keybindings": [ { diff --git a/src/extension.ts b/src/extension.ts index 5dd8f6723..f3cd0ba0d 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -32,6 +32,15 @@ export async function activate(context: vscode.ExtensionContext): Promise { + if (vscode.window.activeNotebookEditor) { + const { document } = vscode.window.activeNotebookEditor; + const notebook = rNotebook.lookupNotebook(document.uri); + if (notebook) { + notebook.restartKernel(); + } + } + } + } + for(const key in commands){ context.subscriptions.push(vscode.commands.registerCommand(key, commands[key])); } @@ -169,12 +190,7 @@ export async function activate(context: vscode.ExtensionContext): Promise Date: Thu, 4 Feb 2021 20:52:41 +0100 Subject: [PATCH 67/78] fixes plots not being displayed and adding cleaner solution for plots. --- .gitignore | 1 + R/notebook.R | 53 ++++++++++++++++++++++++----------------------- samples/test1.rmd | 30 +++++++++++++++++++++++++++ src/notebook.ts | 4 ++++ 4 files changed, 62 insertions(+), 26 deletions(-) create mode 100644 samples/test1.rmd diff --git a/.gitignore b/.gitignore index ece89ebb1..f781a72a9 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ tmp.* temp.* tmp temp +.Rhistory diff --git a/R/notebook.R b/R/notebook.R index 5b05455c7..66aded6b0 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -16,22 +16,19 @@ r <- callr::r_session$new( r$run(function() { requireNamespace("jsonlite") - requireNamespace("svglite") .vscNotebook <- local({ - null_dev_id <- c(pdf = 2L) - null_dev_size <- c(7 + pi, 7 + pi) viewer_file <- NULL browser_url <- NULL + plot.new.called <- F + + set_plot_new <- function() { + plot.new.called <<- T + } + setHook("before.plot.new", set_plot_new) + setHook("before.grid.newpage", set_plot_new) options( - device = function(...) { - pdf(NULL, - width = null_dev_size[[1L]], - height = null_dev_size[[2L]], - bg = "white") - dev.control(displaylist = "enable") - }, viewer = function(url, ...) { viewer_file <<- url }, @@ -43,27 +40,31 @@ r$run(function() { } ) - check_null_dev <- function() { - identical(dev.cur(), null_dev_id) && - identical(dev.size(), null_dev_size) - } - evaluate <- function(id, expr) { + plot_dir <- tempdir() + plot_file <- file.path(plot_dir, "plot%03d.svg") + + svg(plot_file, width = 12, height = 8) + viewer_file <<- NULL browser_url <<- NULL + res <- tryCatch({ expr <- parse(text = expr) out <- withVisible(eval(expr, globalenv())) - if (check_null_dev()) { - record <- recordPlot() - plot_file <- tempfile(fileext = ".svg") - svglite::svglite(plot_file, width = 12, height = 8) - replayPlot(record) - graphics.off() + + text <- utils::capture.output(print(out$value, view = TRUE)) + + dev.off() + graphics.off() + + if (plot.new.called) { + plot.new.called <<- F + list( id = id, type = "plot", - result = plot_file + result = list.files(plot_dir, pattern = ".*\\.svg", full.names = T) ) } else if (!is.null(viewer_file)) { list( @@ -80,20 +81,20 @@ r$run(function() { } else if (out$visible) { if (inherits(out$value, "data.frame")) { text <- utils::capture.output(knitr::kable(out$value, format = "html")) - } else { - text <- utils::capture.output(print(out$value, view = TRUE)) } list( id = id, type = "text", - result = paste0(text, collapse = "\n") + result = paste0(text, collapse = "\n"), + tempdir = plot_dir ) } else { list( id = id, type = "text", - result = "" + result = "", + tempdir = plot_dir ) } }, error = function(e) { diff --git a/samples/test1.rmd b/samples/test1.rmd new file mode 100644 index 000000000..703747dec --- /dev/null +++ b/samples/test1.rmd @@ -0,0 +1,30 @@ +Somehow we need to render a external index.html +```{r} +library(tibble) + +df = data.frame(a = c(1,2,3,4), b = c(10, 20, 13, 1)) + + +library(ggplot2) +library(plotly) + + +``` +```{r} +ggplot(df, aes(a, b)) + geom_point() + +``` +```{r} +plot(df) + +``` +Something goes wrong here internally with paged_table +```{r} +rmarkdown::paged_table(df) +``` +```{r} +knitr::kable(df, format = "html") +``` +```{r} +df +``` diff --git a/src/notebook.ts b/src/notebook.ts index 150b3da29..90f4daab5 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -188,6 +188,10 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode ); } + lookupNotebook(uri: vscode.Uri): RNotebook { + return this.notebooks.get(uri.toString()) + } + async openNotebook(uri: vscode.Uri): Promise { const content = (await vscode.workspace.fs.readFile(uri)).toString(); const lines = content.split(/\r?\n/); From 84f57df24769e71cbbfbfa9aca697546e8c3a768 Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Fri, 5 Feb 2021 13:09:21 +0100 Subject: [PATCH 68/78] allows viewer output --- src/inlineScripts.ts | 75 ++++++++++++++++++++++++++++++++++++++++++++ src/notebook.ts | 31 +++++++++++++----- 2 files changed, 98 insertions(+), 8 deletions(-) create mode 100644 src/inlineScripts.ts diff --git a/src/inlineScripts.ts b/src/inlineScripts.ts new file mode 100644 index 000000000..120801ad7 --- /dev/null +++ b/src/inlineScripts.ts @@ -0,0 +1,75 @@ +import * as path from 'path'; +import {promises as fs} from "fs"; + +function getMimeType(ext: string): string { + switch (ext) { + case 'jpg': + case 'jpeg': + return 'image/jpeg'; + case 'svg': + return 'image/svg+xml'; + case 'gif': + case 'png': + case 'webp': + return `image/${ext}`; + default: + return 'application/octet-stream'; + } +}; + +export async function inlineImages(html: string, htmlDir: string): Promise { + const imgTagRegex = //; + let matches = html.match(new RegExp(imgTagRegex, 'g')); + if (!matches) + return html; + let imgPromises = matches + .map(imgTag => imgTag.match(imgTagRegex)[2]) + .map(relImgPath => path.resolve(htmlDir, relImgPath)) + .map(imgPath => fs.readFile(imgPath)); + let i = 0; + return Promise.all(imgPromises).then(images => + html.replace(new RegExp(imgTagRegex, 'g'), (_match, p1, p2, p3) => + `` + )); +} + +export async function inlineHtmlScripts(html: string, htmlDir: string): Promise { + const scriptTagRegex = /`)); +} + +export async function inlineHtmlStyles(html: string, htmlDir: string): Promise { + const linkTagRegex = /|/; + let matches = html.match(new RegExp(linkTagRegex, 'g')); + if (!matches) + return html; + let stylesheetPromises = matches + .map(linkTag => { + let m = linkTag.match(linkTagRegex); + return m[1] || m[2]; + }) + .map(relPath => path.resolve(htmlDir, relPath)) + .map(stylesheetPath => fs.readFile(stylesheetPath, 'utf8')); + let i = 0; + return Promise.all(stylesheetPromises).then(stylesheets => + html.replace(new RegExp(linkTagRegex, 'g'), () => + ``)); +} + +export async function inlineAll(html: string, htmlDir: string): Promise { + return await inlineHtmlStyles( + await inlineImages( + await inlineHtmlScripts(html, htmlDir), + htmlDir), + htmlDir) +} \ No newline at end of file diff --git a/src/notebook.ts b/src/notebook.ts index 90f4daab5..bc40ab8e7 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -2,6 +2,8 @@ import * as vscode from 'vscode'; import net = require('net'); import { spawn, ChildProcess } from 'child_process'; import { dirname } from 'path'; +import { inlineAll } from './inlineScripts'; + interface RKernelRequest { id: number; @@ -336,6 +338,26 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } } + async renderHtmlOutput(response) { + + const html = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(); + const htmlDir = dirname(response.result) + const htmlInline = await inlineAll(html, htmlDir) + const htmlWrapped = ` + + + ` + return { + outputKind: vscode.CellOutputKind.Rich, + data: { + 'text/html': htmlWrapped + }, + } + } + async renderOutput(cell, response) { switch (response.type) { @@ -348,14 +370,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode break; } case 'viewer': { - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - // 'text/html': `Here`, - // `, - }, - }]; + cell.outputs = [await this.renderHtmlOutput(response)]; break; } case 'browser': { From 9f9e8cdbdf06c3f2b78cdfa64851fbab690a922a Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Fri, 5 Feb 2021 21:14:29 +0100 Subject: [PATCH 69/78] prettier output tables --- R/notebook.R | 26 ++++++++++++++++---------- src/notebook.ts | 26 ++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index 66aded6b0..c155ed5be 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -80,21 +80,27 @@ r$run(function() { ) } else if (out$visible) { if (inherits(out$value, "data.frame")) { - text <- utils::capture.output(knitr::kable(out$value, format = "html")) + table <- head(out$value, 10) + list( + id = id, + type = "table", + result = list( + html = knitr::kable(table, format = "html"), + markdown = paste0(knitr::kable(table, format = "markdown"), collapse = "\n") + ) + ) + } else { + list( + id = id, + type = "text", + result = paste0(text, collapse = "\n") + ) } - - list( - id = id, - type = "text", - result = paste0(text, collapse = "\n"), - tempdir = plot_dir - ) } else { list( id = id, type = "text", - result = "", - tempdir = plot_dir + result = "" ) } }, error = function(e) { diff --git a/src/notebook.ts b/src/notebook.ts index bc40ab8e7..daef4d356 100644 --- a/src/notebook.ts +++ b/src/notebook.ts @@ -4,7 +4,6 @@ import { spawn, ChildProcess } from 'child_process'; import { dirname } from 'path'; import { inlineAll } from './inlineScripts'; - interface RKernelRequest { id: number; type: 'eval' | 'cancel'; @@ -339,7 +338,6 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } async renderHtmlOutput(response) { - const html = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(); const htmlDir = dirname(response.result) const htmlInline = await inlineAll(html, htmlDir) @@ -358,6 +356,26 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } } + async renderTableOutput(response) { + const html = ` +
+ + ` + + return { + outputKind: vscode.CellOutputKind.Rich, + data: { + 'text/html': response.result.html, + 'text/markdown': response.result.markdown, + 'text/plain': response.result.markdown + }, + } + } + async renderOutput(cell, response) { switch (response.type) { @@ -382,6 +400,10 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode }]; break; } + case 'table': { + cell.outputs = [await this.renderTableOutput(response)]; + break; + } case 'error': { cell.metadata.runState = vscode.NotebookCellRunState.Error; cell.outputs = [{ From fc4781721a7c80889213835855b22c6a328cea43 Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Tue, 9 Feb 2021 14:04:56 +0100 Subject: [PATCH 70/78] implements table renderer --- R/notebook.R | 3 +- package-lock.json | 3909 ++++++++++++++++- package.json | 37 +- samples/test1.rmd | 2 +- src/client/renderers/tableRenderer.tsx | 33 + src/client/renderers/viewerRenderer.tsx | 7 + src/client/tsconfig.json | 12 + src/{ => extension}/api.d.ts | 0 src/{ => extension}/apiImplementation.ts | 0 src/{ => extension}/completions.ts | 0 src/{ => extension}/extension.ts | 0 src/{ => extension}/inlineScripts.ts | 0 src/{ => extension}/lineCache.ts | 0 src/{ => extension}/notebook.ts | 13 +- src/{ => extension}/preview.ts | 0 src/{ => extension}/rGitignore.ts | 0 src/{ => extension}/rHelp.ts | 0 src/{ => extension}/rHelpPackages.ts | 0 src/{ => extension}/rHelpPanel.ts | 0 src/{ => extension}/rHelpProvider.ts | 0 src/{ => extension}/rHelpTree.ts | 0 src/{ => extension}/rTerminal.ts | 0 src/{ => extension}/rmarkdown.ts | 0 src/{ => extension}/rstudioapi.ts | 0 src/{ => extension}/selection.ts | 0 src/{ => extension}/session.ts | 0 src/{ => extension}/test/runTest.ts | 0 .../test/suite/extension.test.ts | 0 src/{ => extension}/test/suite/index.ts | 0 src/extension/tsconfig.json | 6 + src/{ => extension}/util.ts | 0 .../extension/vscode.proposed.d.ts | 0 src/{ => extension}/workspaceViewer.ts | 0 src/tsconfig.base.json | 19 + tsconfig.json | 26 +- webpack.config.js | 88 +- 36 files changed, 3930 insertions(+), 225 deletions(-) create mode 100644 src/client/renderers/tableRenderer.tsx create mode 100644 src/client/renderers/viewerRenderer.tsx create mode 100644 src/client/tsconfig.json rename src/{ => extension}/api.d.ts (100%) rename src/{ => extension}/apiImplementation.ts (100%) rename src/{ => extension}/completions.ts (100%) rename src/{ => extension}/extension.ts (100%) rename src/{ => extension}/inlineScripts.ts (100%) rename src/{ => extension}/lineCache.ts (100%) rename src/{ => extension}/notebook.ts (97%) rename src/{ => extension}/preview.ts (100%) rename src/{ => extension}/rGitignore.ts (100%) rename src/{ => extension}/rHelp.ts (100%) rename src/{ => extension}/rHelpPackages.ts (100%) rename src/{ => extension}/rHelpPanel.ts (100%) rename src/{ => extension}/rHelpProvider.ts (100%) rename src/{ => extension}/rHelpTree.ts (100%) rename src/{ => extension}/rTerminal.ts (100%) rename src/{ => extension}/rmarkdown.ts (100%) rename src/{ => extension}/rstudioapi.ts (100%) rename src/{ => extension}/selection.ts (100%) rename src/{ => extension}/session.ts (100%) rename src/{ => extension}/test/runTest.ts (100%) rename src/{ => extension}/test/suite/extension.test.ts (100%) rename src/{ => extension}/test/suite/index.ts (100%) create mode 100644 src/extension/tsconfig.json rename src/{ => extension}/util.ts (100%) rename vscode.proposed.d.ts => src/extension/vscode.proposed.d.ts (100%) rename src/{ => extension}/workspaceViewer.ts (100%) create mode 100644 src/tsconfig.base.json diff --git a/R/notebook.R b/R/notebook.R index c155ed5be..5077deeae 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -86,7 +86,8 @@ r$run(function() { type = "table", result = list( html = knitr::kable(table, format = "html"), - markdown = paste0(knitr::kable(table, format = "markdown"), collapse = "\n") + markdown = paste0(knitr::kable(table, format = "markdown"), collapse = "\n"), + data = head(out$value, 1000) ) ) } else { diff --git a/package-lock.json b/package-lock.json index 221ca320c..6362f7472 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "r", - "version": "1.6.3", + "version": "1.6.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -43,6 +43,19 @@ } } }, + "@babel/runtime": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.13.tgz", + "integrity": "sha512-8+3UMPBrjFa/6TtKi/7sehPKqfAm4g6K+YQjyyFOLUTxzOngcRZTlAVY8sc2CORJYqdHQY8gRPHmn+qo15rCBw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@date-io/moment": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@date-io/moment/-/moment-1.3.5.tgz", + "integrity": "sha512-b0JQb10Lie07iW2/9uKCQSrXif262d6zfYBstCLLJUk0JVA+7o/yLDg5p2+GkjgJbmodjHozIXs4Bi34RRhL8Q==" + }, "@discoveryjs/json-ext": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", @@ -75,6 +88,11 @@ } } }, + "@fortawesome/fontawesome-free": { + "version": "5.15.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.2.tgz", + "integrity": "sha512-7l/AX41m609L/EXI9EKH3Vs3v0iA8tKlIOGtw+kgcoanI7p+e4I4GYLqW3UXWiTnjSFymKSmTTPKYrivzbxxqA==" + }, "@kwsites/file-exists": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", @@ -90,6 +108,74 @@ "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", "dev": true }, + "@material-ui/core": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-3.9.3.tgz", + "integrity": "sha512-REIj62+zEvTgI/C//YL4fZxrCVIySygmpZglsu/Nl5jPqy3CDjZv1F9ubBYorHqmRgeVPh64EghMMWqk4egmfg==", + "requires": { + "@babel/runtime": "^7.2.0", + "@material-ui/system": "^3.0.0-alpha.0", + "@material-ui/utils": "^3.0.0-alpha.2", + "@types/jss": "^9.5.6", + "@types/react-transition-group": "^2.0.8", + "brcast": "^3.0.1", + "classnames": "^2.2.5", + "csstype": "^2.5.2", + "debounce": "^1.1.0", + "deepmerge": "^3.0.0", + "dom-helpers": "^3.2.1", + "hoist-non-react-statics": "^3.2.1", + "is-plain-object": "^2.0.4", + "jss": "^9.8.7", + "jss-camel-case": "^6.0.0", + "jss-default-unit": "^8.0.2", + "jss-global": "^3.0.0", + "jss-nested": "^6.0.1", + "jss-props-sort": "^6.0.0", + "jss-vendor-prefixer": "^7.0.0", + "normalize-scroll-left": "^0.1.2", + "popper.js": "^1.14.1", + "prop-types": "^15.6.0", + "react-event-listener": "^0.6.2", + "react-transition-group": "^2.2.1", + "recompose": "0.28.0 - 0.30.0", + "warning": "^4.0.1" + }, + "dependencies": { + "react-transition-group": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", + "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", + "requires": { + "dom-helpers": "^3.4.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2", + "react-lifecycles-compat": "^3.0.4" + } + } + } + }, + "@material-ui/system": { + "version": "3.0.0-alpha.2", + "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-3.0.0-alpha.2.tgz", + "integrity": "sha512-odmxQ0peKpP7RQBQ8koly06YhsPzcoVib1vByVPBH4QhwqBXuYoqlCjt02846fYspAqkrWzjxnWUD311EBbxOA==", + "requires": { + "@babel/runtime": "^7.2.0", + "deepmerge": "^3.0.0", + "prop-types": "^15.6.0", + "warning": "^4.0.1" + } + }, + "@material-ui/utils": { + "version": "3.0.0-alpha.3", + "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-3.0.0-alpha.3.tgz", + "integrity": "sha512-rwMdMZptX0DivkqBuC+Jdq7BYTXwqKai5G5ejPpuEDKpWzi1Oxp+LygGw329FrKpuKeiqpcymlqJTjmy+quWng==", + "requires": { + "@babel/runtime": "^7.2.0", + "prop-types": "^15.6.0", + "react-is": "^16.6.3" + } + }, "@nodelib/fs.scandir": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", @@ -150,6 +236,14 @@ "@types/node": "*" } }, + "@types/datatables.net": { + "version": "1.10.19", + "resolved": "https://registry.npmjs.org/@types/datatables.net/-/datatables.net-1.10.19.tgz", + "integrity": "sha512-WuzgytEmsIpVYZbkce+EvK1UqBI7/cwcC/WgYeAtXdq2zi+yWzJwMT5Yb6irAiOi52DBjeAEeRt3bYzFYvHWCQ==", + "requires": { + "@types/jquery": "*" + } + }, "@types/eslint": { "version": "7.2.6", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.6.tgz", @@ -208,6 +302,15 @@ "@types/node": "*" } }, + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, "@types/highlight.js": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-10.1.0.tgz", @@ -217,11 +320,27 @@ "highlight.js": "*" } }, + "@types/jquery": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.5.tgz", + "integrity": "sha512-6RXU9Xzpc6vxNrS6FPPapN1SxSHgQ336WC6Jj/N8q30OiaBZ00l1GBgeP7usjVZPivSkGUfL1z/WW6TX989M+w==", + "requires": { + "@types/sizzle": "*" + } + }, "@types/json-schema": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", - "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", - "dev": true + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==" + }, + "@types/jss": { + "version": "9.5.8", + "resolved": "https://registry.npmjs.org/@types/jss/-/jss-9.5.8.tgz", + "integrity": "sha512-bBbHvjhm42UKki+wZpR89j73ykSXg99/bhuKuYYePtpma3ZAnmeGnl0WxXiZhPGsIfzKwCUkpPC0jlrVMBfRxA==", + "requires": { + "csstype": "^2.0.0", + "indefinite-observable": "^1.0.1" + } }, "@types/mime": { "version": "1.3.2", @@ -229,6 +348,11 @@ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", "dev": true }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" + }, "@types/mocha": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.0.tgz", @@ -238,8 +362,12 @@ "@types/node": { "version": "14.14.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.10.tgz", - "integrity": "sha512-J32dgx2hw8vXrSbu4ZlVhn1Nm3GbeCFNw2FWL8S5QKucHGY0cyNwjdQdO+KMBZ4wpmC7KhLCiNsdk1RFRIYUQQ==", - "dev": true + "integrity": "sha512-J32dgx2hw8vXrSbu4ZlVhn1Nm3GbeCFNw2FWL8S5QKucHGY0cyNwjdQdO+KMBZ4wpmC7KhLCiNsdk1RFRIYUQQ==" + }, + "@types/prop-types": { + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, "@types/qs": { "version": "6.9.5", @@ -253,6 +381,46 @@ "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", "dev": true }, + "@types/react": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.0.tgz", + "integrity": "sha512-aj/L7RIMsRlWML3YB6KZiXB3fV2t41+5RBGYF8z+tAKU43Px8C3cYUZsDvf1/+Bm4FK21QWBrDutu8ZJ/70qOw==", + "requires": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + }, + "dependencies": { + "csstype": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz", + "integrity": "sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==" + } + } + }, + "@types/react-dom": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.0.tgz", + "integrity": "sha512-lUqY7OlkF/RbNtD5nIq7ot8NquXrdFrjSOR6+w9a9RFQevGi1oZO1dcJbXMeONAPKtZ2UrZOEJ5UOCVsxbLk/g==", + "requires": { + "@types/react": "*" + } + }, + "@types/react-text-mask": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/@types/react-text-mask/-/react-text-mask-5.4.6.tgz", + "integrity": "sha512-0KkER9oXZY/v1x8aoMTHwANlWnKT5tnmV7Zz+g81gBvcHRtcIHotcpY4KgWRwx0T5JMcsYmEh7wGOz0lwdONew==", + "requires": { + "@types/react": "*" + } + }, + "@types/react-transition-group": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-2.9.2.tgz", + "integrity": "sha512-5Fv2DQNO+GpdPZcxp2x/OQG/H19A01WlmpjVD9cKvVFmoVLOZ9LvBgSWG6pSXIU4og5fgbvGPaCV5+VGkWAEHA==", + "requires": { + "@types/react": "*" + } + }, "@types/serve-static": { "version": "1.13.9", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz", @@ -269,6 +437,11 @@ "integrity": "sha512-akvzSmrvY4J5d3tHzUUiQr0xpjd4Nb3uzWW6dtwzYJ+qW/KdWw5F8NLatnor5q/1LURHnzDA1ReEwCVqcatRnw==", "dev": true }, + "@types/sizzle": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", + "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==" + }, "@types/text-table": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@types/text-table/-/text-table-0.2.1.tgz", @@ -281,6 +454,16 @@ "integrity": "sha512-Kt3bvWzAvvF/WH9YEcrCICDp0Z7aHhJGhLJ1BxeyNP6yRjonWqWnAIh35/pXAjswAnWOABrYlF7SwXR9+1nnLA==", "dev": true }, + "@types/vscode-notebook-renderer": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@types/vscode-notebook-renderer/-/vscode-notebook-renderer-1.48.0.tgz", + "integrity": "sha512-V7ifnlOgvVP3Ud1mM6EO98+oWRk9bt59INUL3Q0o06cAw45jOfos8pAFjDyCEHd1n6d3Q0ObPzdB0jgg8TdgDA==" + }, + "@types/webpack-env": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.0.tgz", + "integrity": "sha512-Fx+NpfOO0CpeYX2g9bkvX8O5qh9wrU1sOF4g8sft4Mu7z+qfe387YlyY8w8daDyDsKY5vUxM0yxkAYnbkRbZEw==" + }, "@types/winreg": { "version": "1.2.30", "resolved": "https://registry.npmjs.org/@types/winreg/-/winreg-1.2.30.tgz", @@ -524,24 +707,24 @@ } }, "@webpack-cli/configtest": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.0.tgz", - "integrity": "sha512-Un0SdBoN1h4ACnIO7EiCjWuyhNI0Jl96JC+63q6xi4HDUYRZn8Auluea9D+v9NWKc5J4sICVEltdBaVjLX39xw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.1.tgz", + "integrity": "sha512-B+4uBUYhpzDXmwuo3V9yBH6cISwxEI4J+NO5ggDaGEEHb0osY/R7MzeKc0bHURXQuZjMM4qD+bSJCKIuI3eNBQ==", "dev": true }, "@webpack-cli/info": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.1.tgz", - "integrity": "sha512-fLnDML5HZ5AEKzHul8xLAksoKN2cibu6MgonkUj8R9V7bbeVRkd1XbGEGWrAUNYHbX1jcqCsDEpBviE5StPMzQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.2.2.tgz", + "integrity": "sha512-5U9kUJHnwU+FhKH4PWGZuBC1hTEPYyxGSL5jjoBI96Gx8qcYJGOikpiIpFoTq8mmgX3im2zAo2wanv/alD74KQ==", "dev": true, "requires": { "envinfo": "^7.7.3" } }, "@webpack-cli/serve": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.2.2.tgz", - "integrity": "sha512-03GkWxcgFfm8+WIwcsqJb9agrSDNDDoxaNnexPnCCexP5SCE4IgFd9lNpSy+K2nFqVMpgTFw6SwbmVAVTndVew==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.3.0.tgz", + "integrity": "sha512-k2p2VrONcYVX1wRRrf0f3X2VGltLWcv+JzXRBDmvCxGlCeESx4OXw91TsWeKOkp784uNoVQo313vxJFHXPPwfw==", "dev": true }, "@xtuc/ieee754": { @@ -556,6 +739,15 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -581,7 +773,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -589,11 +780,15 @@ "uri-js": "^4.2.2" } }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" + }, "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" }, "ansi-colors": { "version": "4.1.1", @@ -601,11 +796,15 @@ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=" + }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "3.2.1", @@ -650,28 +849,140 @@ "sprintf-js": "~1.0.2" } }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, "astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, "at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } }, "base64-js": { "version": "1.5.1", @@ -679,6 +990,11 @@ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + }, "big-integer": { "version": "1.6.48", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", @@ -688,8 +1004,7 @@ "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" }, "binary": { "version": "0.3.0", @@ -737,6 +1052,56 @@ "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=", "dev": true }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -747,11 +1112,15 @@ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz", "integrity": "sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw==" }, + "bootstrap-css-only": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/bootstrap-css-only/-/bootstrap-css-only-4.4.1.tgz", + "integrity": "sha512-iBgNli7RnedBFwn6sMTQoAZ8WgIwmX4kF1rckfj+pgro5q/Q0DbLtcpfH60XoFnCXzbEJU/khC/B2EQap89mCg==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -766,6 +1135,11 @@ "fill-range": "^7.0.1" } }, + "brcast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/brcast/-/brcast-3.0.2.tgz", + "integrity": "sha512-f5XwwFCCuvgqP2nMH/hJ74FqnGmb4X3D+NC//HphxJzzhsZvSZa+Hk/syB7j3ZHpPDLMoYU8oBgviRWfNvEfKA==" + }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -801,6 +1175,11 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==" + }, "buffer-indexof-polyfill": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", @@ -819,6 +1198,36 @@ "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", "dev": true }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -896,6 +1305,37 @@ } } }, + "change-emitter": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz", + "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU=" + }, + "chart.js": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.3.tgz", + "integrity": "sha512-+2jlOobSk52c1VU6fzkh3UwqHMdSlgH1xFv9FKMqHiNCpXsGPQa/+81AFa+i3jZ253Mq9aAycPwDjnn1XbRNNw==", + "requires": { + "chartjs-color": "^2.1.0", + "moment": "^2.10.2" + } + }, + "chartjs-color": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", + "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", + "requires": { + "chartjs-color-string": "^0.6.0", + "color-convert": "^1.9.3" + } + }, + "chartjs-color-string": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", + "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", + "requires": { + "color-name": "^1.0.0" + } + }, "cheerio": { "version": "1.0.0-rc.5", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.5.tgz", @@ -953,6 +1393,32 @@ "tslib": "^1.9.0" } }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, "cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", @@ -982,19 +1448,32 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, "requires": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", "shallow-clone": "^3.0.0" } }, + "clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" + }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -1011,8 +1490,7 @@ "colorette": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", - "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", - "dev": true + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==" }, "commander": { "version": "7.0.0", @@ -1026,11 +1504,57 @@ "integrity": "sha512-vue7cRi1ZO5/72FJ+wZ5+siTSBlUv3ZksTk8bWD2IkaA6obitzMZP3yI65azTJLckwmi8lxfPP5Sd9oGuZ8e2g==", "dev": true }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" }, "console-control-strings": { "version": "1.1.0", @@ -1038,6 +1562,34 @@ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, "copy-webpack-plugin": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-7.0.0.tgz", @@ -1065,11 +1617,24 @@ } } }, + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-react-context": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.3.0.tgz", + "integrity": "sha512-dNldIoSuNSvlTJ7slIKC/ZFGKexBMBrrcc+TTe1NdmROnaASuLPvqpwj9v4XS4uXZ8+YPu0sNmShX2rXI5LNsw==", + "requires": { + "gud": "^1.0.0", + "warning": "^4.0.3" + } }, "cross-spawn": { "version": "7.0.3", @@ -1082,6 +1647,32 @@ "which": "^2.0.1" } }, + "css-loader": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.0.2.tgz", + "integrity": "sha512-gbkBigdcHbmNvZ1Cg6aV6qh6k9N6XOr8YWzISLQGrwk2mgOH8LLrizhkxbDhQtaLtktyKHD4970S0xwz5btfTA==", + "requires": { + "camelcase": "^6.2.0", + "cssesc": "^3.0.0", + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.4", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.4" + }, + "dependencies": { + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==" + } + } + }, "css-select": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/css-select/-/css-select-3.1.2.tgz", @@ -1094,11 +1685,29 @@ "nth-check": "^2.0.0" } }, + "css-vendor": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-0.3.8.tgz", + "integrity": "sha1-ZCHP0wNM5mT+dnOXL9ARn8KJQfo=", + "requires": { + "is-in-browser": "^1.0.2" + } + }, "css-what": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-4.0.0.tgz", "integrity": "sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==" }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + }, + "csstype": { + "version": "2.6.14", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.14.tgz", + "integrity": "sha512-2mSc+VEpGPblzAxyeR+vZhJKgYg0Og0nnRi7pmRXFYYxSfnOnW8A5wwQb4n4cE2nIOzqKOAzLCaEX6aBmNEv8A==" + }, "datatables.net": { "version": "1.10.23", "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.23.tgz", @@ -1154,11 +1763,15 @@ } } }, + "debounce": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz", + "integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg==" + }, "debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -1168,6 +1781,11 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, "decompress-response": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", @@ -1177,6 +1795,19 @@ "mimic-response": "^2.0.0" } }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -1189,23 +1820,228 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true + "deepmerge": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.3.0.tgz", + "integrity": "sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA==" }, - "devreplay": { - "version": "1.9.25", - "resolved": "https://registry.npmjs.org/devreplay/-/devreplay-1.9.25.tgz", - "integrity": "sha512-s49YeHIBKiMVnFljVgmE6kIlV+WO8tr8pgwBI5FZO2yz+xqRpjDmyL/7mNRpjDq3UAhQ3XivBAlSR4ZBUQEZMw==", - "dev": true, + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "^1.0.1" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "dev": true + }, + "detect-node": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==" + }, + "devreplay": { + "version": "1.9.25", + "resolved": "https://registry.npmjs.org/devreplay/-/devreplay-1.9.25.tgz", + "integrity": "sha512-s49YeHIBKiMVnFljVgmE6kIlV+WO8tr8pgwBI5FZO2yz+xqRpjDmyL/7mNRpjDq3UAhQ3XivBAlSR4ZBUQEZMw==", + "dev": true, "requires": { "@babel/code-frame": "^7.12.11", "@types/text-table": "^0.2.1", @@ -1258,6 +2094,28 @@ "path-type": "^4.0.0" } }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=" + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "requires": { + "buffer-indexof": "^1.0.0" + } + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -1267,6 +2125,14 @@ "esutils": "^2.0.2" } }, + "dom-helpers": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", + "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", + "requires": { + "@babel/runtime": "^7.1.2" + } + }, "dom-serializer": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.2.0.tgz", @@ -1309,6 +2175,11 @@ "readable-stream": "^2.0.2" } }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, "electron-to-chromium": { "version": "1.3.649", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.649.tgz", @@ -1323,14 +2194,35 @@ "emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "requires": { "once": "^1.4.0" } @@ -1361,16 +2253,15 @@ "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==" }, "envinfo": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.3.tgz", - "integrity": "sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.4.tgz", + "integrity": "sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ==", "dev": true }, "errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, "requires": { "prr": "~1.0.1" } @@ -1387,6 +2278,11 @@ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -1580,12 +2476,30 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, "events": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", "dev": true }, + "eventsource": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz", + "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==", + "requires": { + "original": "^1.0.0" + } + }, "execa": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", @@ -1603,17 +2517,201 @@ "strip-final-newline": "^2.0.0" } }, + "exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=" + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "dev": true }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { "version": "3.2.4", @@ -1632,8 +2730,7 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fast-levenshtein": { "version": "2.0.6", @@ -1656,6 +2753,28 @@ "reusify": "^1.0.4" } }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fbjs": { + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", + "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "requires": { + "core-js": "^1.0.0", + "isomorphic-fetch": "^2.1.1", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + } + }, "file-entry-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", @@ -1665,6 +2784,15 @@ "flat-cache": "^3.0.4" } }, + "file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -1674,6 +2802,35 @@ "to-regex-range": "^5.0.1" } }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -1706,6 +2863,38 @@ "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", "dev": true }, + "focus-trap": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-4.0.2.tgz", + "integrity": "sha512-HtLjfAK7Hp2qbBtLS6wEznID1mPT+48ZnP2nkHzgjpL4kroYHg0CdqJ5cTXk+UO5znAxF5fRUkhdyfgrhh8Lzw==", + "requires": { + "tabbable": "^3.1.2", + "xtend": "^4.0.1" + } + }, + "focus-trap-react": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/focus-trap-react/-/focus-trap-react-6.0.0.tgz", + "integrity": "sha512-mvEYxmP75PMx0vOqoIAmJHO/qUEvdTAdz6gLlEZyxxODnuKQdnKea2RWTYxghAPrV+ibiIq2o/GTSgQycnAjcw==", + "requires": { + "focus-trap": "^4.0.2" + } + }, + "follow-redirects": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz", + "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, "fotorama": { "version": "4.6.4", "resolved": "https://registry.npmjs.org/fotorama/-/fotorama-4.6.4.tgz", @@ -1714,6 +2903,19 @@ "jquery": ">=1.8" } }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -1734,8 +2936,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.1.3", @@ -1779,8 +2980,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -1831,10 +3031,15 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, - "get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==" + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } }, "get-stream": { "version": "6.0.0", @@ -1842,6 +3047,11 @@ "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", "dev": true }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, "github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -1852,7 +3062,6 @@ "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -1911,11 +3120,20 @@ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "gud": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", + "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==" + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -1923,8 +3141,12 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" }, "has-unicode": { "version": "2.0.1", @@ -1932,7 +3154,54 @@ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true }, - "he": { + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", @@ -1943,6 +3212,43 @@ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.5.0.tgz", "integrity": "sha512-xTmvd9HiIHR6L53TMC7TKolEj65zG1XU+Onr8oi86mYa+nLcIbxTTWkpW7CsEwv/vK7u1zb8alZIMLDqqN6KTw==" }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==" + }, "htmlparser2": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.0.0.tgz", @@ -1954,6 +3260,45 @@ "entities": "^2.0.0" } }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } + } + }, + "http-parser-js": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==" + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, "http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", @@ -1965,6 +3310,114 @@ "debug": "4" } }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, "https-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", @@ -1981,6 +3434,24 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, + "hyphenate-style-name": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", + "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" + }, "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -2058,11 +3529,23 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indefinite-observable": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/indefinite-observable/-/indefinite-observable-1.0.2.tgz", + "integrity": "sha512-Mps0898zEduHyPhb7UCgNmfzlqNZknVmaFz5qzr0mm04YQ5FGLhAyK/dJ+NaRxGyR6juQXIxh5Ev0xx+qq0nYA==", + "requires": { + "symbol-observable": "1.2.0" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -2071,8 +3554,7 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { "version": "1.3.8", @@ -2080,12 +3562,67 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + } + }, "interpret": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", "dev": true }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arguments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "requires": { + "call-bind": "^1.0.0" + } + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -2095,6 +3632,11 @@ "binary-extensions": "^2.0.0" } }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "is-core-module": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", @@ -2104,11 +3646,55 @@ "has": "^1.0.3" } }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -2119,17 +3705,42 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } }, + "is-in-browser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", + "integrity": "sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=" + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==" + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "requires": { + "path-is-inside": "^1.0.2" + } + }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -2140,34 +3751,58 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, "requires": { "isobject": "^3.0.1" } }, + "is-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.1" + } + }, "is-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } }, "jest-worker": { "version": "26.6.2", @@ -2210,8 +3845,7 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "3.14.0", @@ -2238,8 +3872,7 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -2247,11 +3880,15 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==" + }, "json5": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "dev": true, "requires": { "minimist": "^1.2.5" } @@ -2265,11 +3902,84 @@ "universalify": "^2.0.0" } }, + "jss": { + "version": "9.8.7", + "resolved": "https://registry.npmjs.org/jss/-/jss-9.8.7.tgz", + "integrity": "sha512-awj3XRZYxbrmmrx9LUSj5pXSUfm12m8xzi/VKeqI1ZwWBtQ0kVPTs3vYs32t4rFw83CgFDukA8wKzOE9sMQnoQ==", + "requires": { + "is-in-browser": "^1.1.3", + "symbol-observable": "^1.1.0", + "warning": "^3.0.0" + }, + "dependencies": { + "warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", + "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", + "requires": { + "loose-envify": "^1.0.0" + } + } + } + }, + "jss-camel-case": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jss-camel-case/-/jss-camel-case-6.1.0.tgz", + "integrity": "sha512-HPF2Q7wmNW1t79mCqSeU2vdd/vFFGpkazwvfHMOhPlMgXrJDzdj9viA2SaHk9ZbD5pfL63a8ylp4++irYbbzMQ==", + "requires": { + "hyphenate-style-name": "^1.0.2" + } + }, + "jss-default-unit": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/jss-default-unit/-/jss-default-unit-8.0.2.tgz", + "integrity": "sha512-WxNHrF/18CdoAGw2H0FqOEvJdREXVXLazn7PQYU7V6/BWkCV0GkmWsppNiExdw8dP4TU1ma1dT9zBNJ95feLmg==" + }, + "jss-global": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jss-global/-/jss-global-3.0.0.tgz", + "integrity": "sha512-wxYn7vL+TImyQYGAfdplg7yaxnPQ9RaXY/cIA8hawaVnmmWxDHzBK32u1y+RAvWboa3lW83ya3nVZ/C+jyjZ5Q==" + }, + "jss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/jss-nested/-/jss-nested-6.0.1.tgz", + "integrity": "sha512-rn964TralHOZxoyEgeq3hXY8hyuCElnvQoVrQwKHVmu55VRDd6IqExAx9be5HgK0yN/+hQdgAXQl/GUrBbbSTA==", + "requires": { + "warning": "^3.0.0" + }, + "dependencies": { + "warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", + "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", + "requires": { + "loose-envify": "^1.0.0" + } + } + } + }, + "jss-props-sort": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/jss-props-sort/-/jss-props-sort-6.0.0.tgz", + "integrity": "sha512-E89UDcrphmI0LzmvYk25Hp4aE5ZBsXqMWlkFXS0EtPkunJkRr+WXdCNYbXbksIPnKlBenGB9OxzQY+mVc70S+g==" + }, + "jss-vendor-prefixer": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/jss-vendor-prefixer/-/jss-vendor-prefixer-7.0.0.tgz", + "integrity": "sha512-Agd+FKmvsI0HLcYXkvy8GYOw3AAASBUpsmIRvVQheps+JWaN892uFOInTr0DRydwaD91vSSUCU4NssschvF7MA==", + "requires": { + "css-vendor": "^0.3.8" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==" + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, "levn": { "version": "0.4.1", @@ -2297,7 +4007,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", - "dev": true, "requires": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -2316,8 +4025,12 @@ "lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" }, "log-symbols": { "version": "4.0.0", @@ -2328,15 +4041,102 @@ "chalk": "^4.0.0" } }, + "loglevel": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", + "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "^1.0.0" + } + }, + "material-ui-pickers": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/material-ui-pickers/-/material-ui-pickers-2.2.4.tgz", + "integrity": "sha512-QCQh08Ylmnt+o4laW+rPs92QRAcESv3sPXl50YadLm++rAZAXAOh3K8lreGdynCMYFgZfdyu81Oz9xzTlAZNfw==", + "requires": { + "@types/react-text-mask": "^5.4.3", + "clsx": "^1.0.2", + "react-event-listener": "^0.6.6", + "react-text-mask": "^5.4.3", + "react-transition-group": "^2.5.3", + "tslib": "^1.9.3" + }, + "dependencies": { + "react-transition-group": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", + "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", + "requires": { + "dom-helpers": "^3.4.0", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2", + "react-lifecycles-compat": "^3.0.4" + } + } + } + }, + "mdbreact": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mdbreact/-/mdbreact-5.0.1.tgz", + "integrity": "sha512-2VaCb9FClZzo1eIjn2ACFb1CeGdzahSeTmGvC63tjUw3QaG3OWzVs2BGpLr/UFmOPuwzZTbvPDJ3tzjoLBF31g==", + "requires": { + "@date-io/moment": "1.3.5", + "@fortawesome/fontawesome-free": "^5.12.0", + "@material-ui/core": "3.9.3", + "bootstrap-css-only": "4.4.1", + "chart.js": "2.9.3", + "classnames": "2.2.6", + "focus-trap-react": "^6.0.0", + "material-ui-pickers": "2.2.4", + "moment": "2.24.0", + "perfect-scrollbar": "1.5.0", + "popper.js": "^1.16.0", + "prop-types": "15.7.2", + "raf": "3.4.1", + "react": "17.0.1", + "react-chartjs-2": "2.9.0", + "react-dom": "17.0.1", + "react-image-lightbox": "5.1.1", + "react-numeric-input": "2.2.3", + "react-popper": "^1.3.7", + "react-router-dom": "^5.1.2", + "react-scroll": "1.7.16", + "react-toastify": "5.5.0", + "react-transition-group": "4.3.0", + "sass-loader": "^8.0.2" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, "memory-fs": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", @@ -2347,6 +4147,11 @@ "readable-stream": "^2.0.1" } }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -2359,6 +4164,11 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, "micromatch": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", @@ -2369,17 +4179,20 @@ "picomatch": "^2.0.5" } }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, "mime-db": { "version": "1.45.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", - "dev": true + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" }, "mime-types": { "version": "2.1.28", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", - "dev": true, "requires": { "mime-db": "1.45.0" } @@ -2396,11 +4209,24 @@ "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", "dev": true }, + "mini-create-react-context": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", + "requires": { + "@babel/runtime": "^7.12.1", + "tiny-warning": "^1.0.3" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2408,8 +4234,34 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } }, "mkdirp-classic": { "version": "0.5.3", @@ -2519,17 +4371,34 @@ } } }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" }, "nan": { "version": "2.14.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", - "dev": true + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" }, "nanoid": { "version": "3.1.12", @@ -2537,7 +4406,25 @@ "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", "dev": true }, - "napi-build-utils": { + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "napi-build-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", @@ -2549,11 +4436,20 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, "node-abi": { "version": "2.19.3", @@ -2572,6 +4468,27 @@ } } }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + }, + "dependencies": { + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + } + } + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" + }, "node-releases": { "version": "1.1.70", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz", @@ -2587,8 +4504,12 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "normalize-scroll-left": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-scroll-left/-/normalize-scroll-left-0.1.2.tgz", + "integrity": "sha512-F9YMRls0zCF6BFIE2YnXDRpHPpfd91nOIaNdDgrx5YMoPLo8Wqj+6jNXHQsYBavJeXP4ww8HCt0xQAKc5qk2Fg==" }, "npm-run-path": { "version": "4.0.1", @@ -2628,14 +4549,88 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-is": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.4.tgz", + "integrity": "sha512-1ZvAZ4wlF7IyPVOcE1Omikt7UpaFlOQq0HlSti+ZvDH3UiD2brwGMwDbyV43jao2bKJ+4+WdPJHSd7kgzKYVqg==", + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "^3.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -2675,6 +4670,14 @@ } } }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "requires": { + "is-wsl": "^1.1.0" + } + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -2689,6 +4692,19 @@ "word-wrap": "^1.2.3" } }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "requires": { + "url-parse": "^1.4.3" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, "p-limit": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", @@ -2717,6 +4733,19 @@ } } }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==" + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "requires": { + "retry": "^0.12.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -2750,6 +4779,21 @@ "parse5": "^6.0.1" } }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2759,8 +4803,12 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" }, "path-key": { "version": "3.1.1", @@ -2774,18 +4822,51 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, + "perfect-scrollbar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.0.tgz", + "integrity": "sha512-NrNHJn5mUGupSiheBTy6x+6SXCFbLlm8fVZh9moIzw/LgqElN5q4ncR4pbCBCYuCJ8Kcl9mYM0NgDxvW+b4LxA==" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, "pkg-dir": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", @@ -2800,6 +4881,100 @@ "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "postcss": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.5.tgz", + "integrity": "sha512-wMcb7BpDcm3gxQOQx46NDNT36Kk0Ao6PJLLI2ed5vehbbbxCEuslSQzbQ2sfSKy+gkYxhWcGWSeaK+gwm4KIZg==", + "requires": { + "colorette": "^1.2.1", + "nanoid": "^3.1.20", + "source-map": "^0.6.1" + }, + "dependencies": { + "nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==" + } + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" + }, + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-selector-parser": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz", + "integrity": "sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==", + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1", + "util-deprecate": "^1.0.2" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" + }, + "preact": { + "version": "10.5.12", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.5.12.tgz", + "integrity": "sha512-r6siDkuD36oszwlCkcqDJCAKBQxGoeEGytw2DGMD5A/GGdu5Tymw+N2OBXwvOLxg6d1FeY8MgMV3cc5aVQo4Cg==" + }, "prebuild-install": { "version": "5.3.6", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", @@ -2832,8 +5007,7 @@ "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "progress": { "version": "2.0.3", @@ -2841,17 +5015,42 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -2860,8 +5059,30 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "requires": { + "performance-now": "^2.1.0" + } }, "randombytes": { "version": "2.1.0", @@ -2872,6 +5093,29 @@ "safe-buffer": "^5.1.0" } }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + } + } + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -2892,11 +5136,208 @@ } } }, + "react": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.1.tgz", + "integrity": "sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "react-bootstrap-table-next": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/react-bootstrap-table-next/-/react-bootstrap-table-next-4.0.3.tgz", + "integrity": "sha512-uKxC73qUdUfusRf2uzDfMiF9LvTG5vuhTZa0lbAgHWSLLLaKTsI0iHf1e4+c7gP71q8dFsp7StvkP65SxC1JRg==", + "requires": { + "classnames": "^2.2.5", + "react-transition-group": "^4.2.0", + "underscore": "1.9.1" + } + }, + "react-chartjs-2": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-2.9.0.tgz", + "integrity": "sha512-IYwqUUnQRAJ9SNA978vxulHJTcUFTJk2LDVfbAyk0TnJFZZG7+6U/2flsE4MCw6WCbBjTTypy8T82Ch7XrPtRw==", + "requires": { + "lodash": "^4.17.4", + "prop-types": "^15.5.8" + } + }, + "react-dom": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.1.tgz", + "integrity": "sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.1" + } + }, + "react-event-listener": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/react-event-listener/-/react-event-listener-0.6.6.tgz", + "integrity": "sha512-+hCNqfy7o9wvO6UgjqFmBzARJS7qrNoda0VqzvOuioEpoEXKutiKuv92dSz6kP7rYLmyHPyYNLesi5t/aH1gfw==", + "requires": { + "@babel/runtime": "^7.2.0", + "prop-types": "^15.6.0", + "warning": "^4.0.1" + } + }, + "react-image-lightbox": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-image-lightbox/-/react-image-lightbox-5.1.1.tgz", + "integrity": "sha512-GprldD8AqpRb2hsOdns3sI7Xeo9hJlcybDxuli4RB+ml1J/GaFaUuRkT/7IrTLv2+4vkR74ahz2LD0HOUHI7wA==", + "requires": { + "prop-types": "^15.6.2", + "react-modal": "^3.8.1" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "react-modal": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.12.1.tgz", + "integrity": "sha512-WGuXn7Fq31PbFJwtWmOk+jFtGC7E9tJVbFX0lts8ZoS5EPi9+WWylUJWLKKVm3H4GlQ7ZxY7R6tLlbSIBQ5oZA==", + "requires": { + "exenv": "^1.2.0", + "prop-types": "^15.5.10", + "react-lifecycles-compat": "^3.0.0", + "warning": "^4.0.3" + } + }, + "react-numeric-input": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-numeric-input/-/react-numeric-input-2.2.3.tgz", + "integrity": "sha1-S/WRjD6v7YUagN8euZLZQQArtVI=" + }, + "react-popper": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.7.tgz", + "integrity": "sha512-nmqYTx7QVjCm3WUZLeuOomna138R1luC4EqkW3hxJUrAe+3eNz3oFCLYdnPwILfn0mX1Ew2c3wctrjlUMYYUww==", + "requires": { + "@babel/runtime": "^7.1.2", + "create-react-context": "^0.3.0", + "deep-equal": "^1.1.1", + "popper.js": "^1.14.4", + "prop-types": "^15.6.1", + "typed-styles": "^0.0.7", + "warning": "^4.0.2" + } + }, + "react-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", + "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + } + } + }, + "react-router-dom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", + "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, + "react-scroll": { + "version": "1.7.16", + "resolved": "https://registry.npmjs.org/react-scroll/-/react-scroll-1.7.16.tgz", + "integrity": "sha512-f4M5AdL+3cw3MJ7c/T0hPMY2iHCeQLDXV13lRanAFQ6JIt9xyAdHCpTH9mLUQt9SQh4pRarD+Qc7KhU6qMx3Yg==", + "requires": { + "lodash.throttle": "^4.1.1", + "prop-types": "^15.5.8" + } + }, + "react-text-mask": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/react-text-mask/-/react-text-mask-5.4.3.tgz", + "integrity": "sha1-mR77QpnjDC5sLEbRP2FxaUY+DS0=", + "requires": { + "prop-types": "^15.5.6" + } + }, + "react-toastify": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-5.5.0.tgz", + "integrity": "sha512-jsVme7jALIFGRyQsri/g4YTsRuaaGI70T6/ikjwZMB4mwTZaCWqj5NqxhGrRStKlJc5npXKKvKeqTiRGQl78LQ==", + "requires": { + "@babel/runtime": "^7.4.2", + "classnames": "^2.2.6", + "prop-types": "^15.7.2", + "react-transition-group": "^4" + } + }, + "react-transition-group": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.3.0.tgz", + "integrity": "sha512-1qRV1ZuVSdxPlPf4O8t7inxUGpdyO5zG9IoNfJxSO0ImU2A1YWkEQvFPuIPZmMLkg5hYs7vv5mMOyfgSkvAwvw==", + "requires": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "dependencies": { + "csstype": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz", + "integrity": "sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==" + }, + "dom-helpers": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.0.tgz", + "integrity": "sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ==", + "requires": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + } + } + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -2925,6 +5366,49 @@ "resolve": "^1.9.0" } }, + "recompose": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.30.0.tgz", + "integrity": "sha512-ZTrzzUDa9AqUIhRk4KmVFihH0rapdCSMFXjhHbNrjAWxBuUD/guYlyysMnuHjlZC/KRiOKRtB4jf96yYSkKE8w==", + "requires": { + "@babel/runtime": "^7.0.0", + "change-emitter": "^0.1.2", + "fbjs": "^0.8.1", + "hoist-non-react-statics": "^2.3.1", + "react-lifecycles-compat": "^3.0.2", + "symbol-observable": "^1.0.4" + }, + "dependencies": { + "hoist-non-react-statics": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz", + "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==" + } + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, "regexpp": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", @@ -2937,6 +5421,21 @@ "integrity": "sha512-9YXf6xtW+qzQ+hcMQXx95MOvfqXFgsKDZodX3qZB0x2n5Z94ioetIITsBtvJbiOyxa/6s9AtyweBLCdPmPko/w==", "dev": true }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -2953,6 +5452,11 @@ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, "resolve": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", @@ -2986,6 +5490,26 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -3010,29 +5534,150 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sass-loader": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz", + "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==", + "requires": { + "clone-deep": "^4.0.1", + "loader-utils": "^1.2.3", + "neo-async": "^2.6.1", + "schema-utils": "^2.6.1", + "semver": "^6.3.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "scheduler": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.1.tgz", + "integrity": "sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } }, "schema-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz", "integrity": "sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==", - "dev": true, "requires": { "@types/json-schema": "^7.0.6", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" } }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" + }, + "selfsigned": { + "version": "1.10.8", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", + "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", + "requires": { + "node-forge": "^0.10.0" + } + }, "semver": { "version": "7.3.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", - "dev": true, "requires": { "lru-cache": "^6.0.0" } }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, "serialize-javascript": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", @@ -3042,22 +5687,107 @@ "randombytes": "^2.1.0" } }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, "shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, "requires": { "kind-of": "^6.0.2" } @@ -3147,8 +5877,7 @@ "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "simple-concat": { "version": "1.0.1", @@ -3227,6 +5956,154 @@ } } }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "sockjs": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", + "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==", + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^3.4.0", + "websocket-driver": "^0.7.4" + } + }, + "sockjs-client": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.0.tgz", + "integrity": "sha512-8Dt3BDi4FYNrCFGTL/HtwVzkARrENdwOUf1ZoW/9p3M8lZdFT35jVdrHza+qgxuG9H3/shR4cuX/X9umUrjP8Q==", + "requires": { + "debug": "^3.2.6", + "eventsource": "^1.0.7", + "faye-websocket": "^0.11.3", + "inherits": "^2.0.4", + "json3": "^3.3.3", + "url-parse": "^1.4.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, "source-code-tokenizer": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/source-code-tokenizer/-/source-code-tokenizer-0.1.5.tgz", @@ -3266,8 +6143,19 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } }, "source-map-support": { "version": "0.5.19", @@ -3279,6 +6167,11 @@ "source-map": "^0.6.0" } }, + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" + }, "spdx-exceptions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", @@ -3295,18 +6188,87 @@ "spdx-license-ids": "^3.0.0" } }, - "spdx-license-ids": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", - "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", - "dev": true - }, + "spdx-license-ids": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", + "dev": true + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -3336,7 +6298,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" } @@ -3345,11 +6306,15 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, "requires": { "ansi-regex": "^2.0.0" } }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -3362,6 +6327,15 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -3371,6 +6345,16 @@ "has-flag": "^3.0.0" } }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + }, + "tabbable": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-3.1.2.tgz", + "integrity": "sha512-wjB6puVXTYO0BSFtCmWQubA/KIn7Xvajw0x0l6eJUudMG/EAiJvIUnyNX6xO4NpGrJ16lbD0eUseB9WxW0vlpQ==" + }, "table": { "version": "6.0.7", "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", @@ -3541,6 +6525,50 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "tiny-invariant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", + "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3550,6 +6578,11 @@ "is-number": "^7.0.0" } }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, "traverse": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", @@ -3641,8 +6674,7 @@ "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "tsutils": { "version": "3.20.0", @@ -3677,17 +6709,98 @@ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typed-styles": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz", + "integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q==" + }, "typescript": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", "dev": true }, + "ua-parser-js": { + "version": "0.7.23", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.23.tgz", + "integrity": "sha512-m4hvMLxgGHXG3O3fQVAyyAQpZzDOvwnhOTjYz5Xmr7r/+LpkNy3vJXdVRWgd1TkAb7NGROZuSy96CrlNVjA7KA==" + }, + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + } + } + }, "unzipper": { "version": "0.10.11", "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", @@ -3706,20 +6819,78 @@ "setimmediate": "~1.0.4" } }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" + }, "uri-js": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", - "dev": true, "requires": { "punycode": "^2.1.0" } }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } + } + }, + "url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "requires": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + } + }, + "url-parse": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", + "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "v8-compile-cache": { "version": "2.2.0", @@ -3727,6 +6898,16 @@ "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", "dev": true }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, "vscode-test": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.5.0.tgz", @@ -3745,6 +6926,14 @@ "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", "dev": true }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "watchpack": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.0.tgz", @@ -3755,6 +6944,14 @@ "graceful-fs": "^4.1.2" } }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, "web-tree-sitter": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/web-tree-sitter/-/web-tree-sitter-0.18.0.tgz", @@ -3818,17 +7015,17 @@ } }, "webpack-cli": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.4.0.tgz", - "integrity": "sha512-/Qh07CXfXEkMu5S8wEpjuaw2Zj/CC0hf/qbTDp6N8N7JjdGuaOjZ7kttz+zhuJO/J5m7alQEhNk9lsc4rC6xgQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.5.0.tgz", + "integrity": "sha512-wXg/ef6Ibstl2f50mnkcHblRPN/P9J4Nlod5Hg9HGFgSeF8rsqDGHJeVe4aR26q9l62TUJi6vmvC2Qz96YJw1Q==", "dev": true, "requires": { "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.0", - "@webpack-cli/info": "^1.2.1", - "@webpack-cli/serve": "^1.2.2", + "@webpack-cli/configtest": "^1.0.1", + "@webpack-cli/info": "^1.2.2", + "@webpack-cli/serve": "^1.3.0", "colorette": "^1.2.1", - "commander": "^6.2.0", + "commander": "^7.0.0", "enquirer": "^2.3.6", "execa": "^5.0.0", "fastest-levenshtein": "^1.0.12", @@ -3837,13 +7034,358 @@ "rechoir": "^0.7.0", "v8-compile-cache": "^2.2.0", "webpack-merge": "^5.7.3" + } + }, + "webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" }, "dependencies": { - "commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "mime": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz", + "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==" + } + } + }, + "webpack-dev-server": { + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz", + "integrity": "sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ==", + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.8", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "sockjs-client": "^1.5.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "optional": true, + "requires": { + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "requires": { + "find-up": "^3.0.0" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==" } } }, @@ -3867,6 +7409,26 @@ "source-map": "^0.6.1" } }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + }, + "whatwg-fetch": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz", + "integrity": "sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A==" + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3974,8 +7536,20 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, "y18n": { "version": "4.0.0", @@ -3985,8 +7559,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yamljs": { "version": "0.3.0", @@ -4002,7 +7575,6 @@ "version": "13.3.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, "requires": { "cliui": "^5.0.0", "find-up": "^3.0.0", @@ -4020,7 +7592,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -4029,7 +7600,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -4039,7 +7609,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -4047,8 +7616,7 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" } } }, @@ -4056,7 +7624,6 @@ "version": "13.1.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" diff --git a/package.json b/package.json index 18cc75666..50df208ab 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,16 @@ "enableProposedApi": true, "main": "./dist/extension", "contributes": { + "notebookOutputRenderer": [ + { + "id": "r-notebook-table-renderer", + "displayName": "Notebook Table Renderer", + "entrypoint": "./dist/tableRenderer.js", + "mimeTypes": [ + "ms-vscode.r-notebook/table" + ] + } + ], "viewsContainers": { "activitybar": [ { @@ -617,12 +627,12 @@ "category": "R", "command": "r.helpPanel.openForSelection" }, - { - "title": "Restart Kernel", - "command": "r.notebook.restartKernel", - "icon": "$(refresh)", + { + "title": "Restart Kernel", + "command": "r.notebook.restartKernel", + "icon": "$(refresh)", "category": "R" - } + } ], "keybindings": [ { @@ -1034,23 +1044,38 @@ "typescript": "^4.1.3", "vscode-test": "^1.5.0", "webpack": "^5.19.0", - "webpack-cli": "^4.4.0", + "webpack-cli": "^4.5.0", "yamljs": "^0.3.0" }, "dependencies": { + "@fortawesome/fontawesome-free": "^5.15.2", + "@types/datatables.net": "^1.10.19", + "@types/react": "^17.0.0", + "@types/react-dom": "^17.0.0", + "@types/vscode-notebook-renderer": "^1.48.0", + "@types/webpack-env": "^1.16.0", "bootstrap": "^4.6.0", "cheerio": "^1.0.0-rc.5", + "css-loader": "^5.0.2", "datatables.net": "^1.10.23", "datatables.net-bs4": "^1.10.23", "datatables.net-fixedheader-jqui": "^3.1.7", + "file-loader": "^6.2.0", "fotorama": "^4.6.4", "fs-extra": "^9.1.0", "highlight.js": "^10.5.0", "jquery": "^3.5.1", "jquery.json-viewer": "^1.4.0", + "mdbreact": "^5.0.1", "popper.js": "^1.16.1", + "preact": "^10.5.12", + "react-bootstrap-table-next": "^4.0.3", + "react-dom": "^17.0.1", "showdown": "^1.9.1", + "style-loader": "^2.0.0", "tree-kill": "^1.2.2", + "url-loader": "^4.1.1", + "webpack-dev-server": "^3.11.2", "winreg": "^1.2.4" } } diff --git a/samples/test1.rmd b/samples/test1.rmd index 703747dec..f379dcf57 100644 --- a/samples/test1.rmd +++ b/samples/test1.rmd @@ -8,7 +8,7 @@ df = data.frame(a = c(1,2,3,4), b = c(10, 20, 13, 1)) library(ggplot2) library(plotly) - +df ``` ```{r} ggplot(df, aes(a, b)) + geom_point() diff --git a/src/client/renderers/tableRenderer.tsx b/src/client/renderers/tableRenderer.tsx new file mode 100644 index 000000000..016bc37e9 --- /dev/null +++ b/src/client/renderers/tableRenderer.tsx @@ -0,0 +1,33 @@ +import * as React from 'react'; +import { render } from 'react-dom'; + +import { MDBDataTable } from 'mdbreact'; +import '@fortawesome/fontawesome-free/css/all.min.css'; +import 'bootstrap-css-only/css/bootstrap.min.css'; +import 'mdbreact/dist/css/mdb.css'; + +const notebookApi = acquireNotebookRendererApi("r-notebook-table-renderer"); + +const DatatablePage = ({ data }) => { + const columns = Object.keys(data[0]).map((k) => { + return { + label: k.charAt(0).toLocaleUpperCase() + k.slice(1), + field: k, + sort: 'asc' + } + }) + const datatable = { + columns: columns, + rows: data + } + return ; +} + +notebookApi.onDidCreateOutput((evt) => { + const output = evt.output.data[evt.mimeType]; + render( +
+ + {/* */} +
as any, evt.element) +}); diff --git a/src/client/renderers/viewerRenderer.tsx b/src/client/renderers/viewerRenderer.tsx new file mode 100644 index 000000000..5296677c6 --- /dev/null +++ b/src/client/renderers/viewerRenderer.tsx @@ -0,0 +1,7 @@ +const notebookApi = acquireNotebookRendererApi("r-notebook-table-renderer"); + + +notebookApi.onDidCreateOutput((evt) => { + const output = evt.output.data[evt.mimeType]; + evt.element.innerHTML = +}); diff --git a/src/client/tsconfig.json b/src/client/tsconfig.json new file mode 100644 index 000000000..8bff92a81 --- /dev/null +++ b/src/client/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + "lib": [ + "ES2019", + "DOM" + ], + "jsx": "react", + "types": ["vscode-notebook-renderer", "webpack-env"], + "rootDir": ".", + } +} \ No newline at end of file diff --git a/src/api.d.ts b/src/extension/api.d.ts similarity index 100% rename from src/api.d.ts rename to src/extension/api.d.ts diff --git a/src/apiImplementation.ts b/src/extension/apiImplementation.ts similarity index 100% rename from src/apiImplementation.ts rename to src/extension/apiImplementation.ts diff --git a/src/completions.ts b/src/extension/completions.ts similarity index 100% rename from src/completions.ts rename to src/extension/completions.ts diff --git a/src/extension.ts b/src/extension/extension.ts similarity index 100% rename from src/extension.ts rename to src/extension/extension.ts diff --git a/src/inlineScripts.ts b/src/extension/inlineScripts.ts similarity index 100% rename from src/inlineScripts.ts rename to src/extension/inlineScripts.ts diff --git a/src/lineCache.ts b/src/extension/lineCache.ts similarity index 100% rename from src/lineCache.ts rename to src/extension/lineCache.ts diff --git a/src/notebook.ts b/src/extension/notebook.ts similarity index 97% rename from src/notebook.ts rename to src/extension/notebook.ts index daef4d356..720ded5ed 100644 --- a/src/notebook.ts +++ b/src/extension/notebook.ts @@ -357,21 +357,12 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } async renderTableOutput(response) { - const html = ` -
- - ` - return { outputKind: vscode.CellOutputKind.Rich, data: { - 'text/html': response.result.html, + 'ms-vscode.r-notebook/table': response.result.data, 'text/markdown': response.result.markdown, - 'text/plain': response.result.markdown + 'application/json': response.result.data, }, } } diff --git a/src/preview.ts b/src/extension/preview.ts similarity index 100% rename from src/preview.ts rename to src/extension/preview.ts diff --git a/src/rGitignore.ts b/src/extension/rGitignore.ts similarity index 100% rename from src/rGitignore.ts rename to src/extension/rGitignore.ts diff --git a/src/rHelp.ts b/src/extension/rHelp.ts similarity index 100% rename from src/rHelp.ts rename to src/extension/rHelp.ts diff --git a/src/rHelpPackages.ts b/src/extension/rHelpPackages.ts similarity index 100% rename from src/rHelpPackages.ts rename to src/extension/rHelpPackages.ts diff --git a/src/rHelpPanel.ts b/src/extension/rHelpPanel.ts similarity index 100% rename from src/rHelpPanel.ts rename to src/extension/rHelpPanel.ts diff --git a/src/rHelpProvider.ts b/src/extension/rHelpProvider.ts similarity index 100% rename from src/rHelpProvider.ts rename to src/extension/rHelpProvider.ts diff --git a/src/rHelpTree.ts b/src/extension/rHelpTree.ts similarity index 100% rename from src/rHelpTree.ts rename to src/extension/rHelpTree.ts diff --git a/src/rTerminal.ts b/src/extension/rTerminal.ts similarity index 100% rename from src/rTerminal.ts rename to src/extension/rTerminal.ts diff --git a/src/rmarkdown.ts b/src/extension/rmarkdown.ts similarity index 100% rename from src/rmarkdown.ts rename to src/extension/rmarkdown.ts diff --git a/src/rstudioapi.ts b/src/extension/rstudioapi.ts similarity index 100% rename from src/rstudioapi.ts rename to src/extension/rstudioapi.ts diff --git a/src/selection.ts b/src/extension/selection.ts similarity index 100% rename from src/selection.ts rename to src/extension/selection.ts diff --git a/src/session.ts b/src/extension/session.ts similarity index 100% rename from src/session.ts rename to src/extension/session.ts diff --git a/src/test/runTest.ts b/src/extension/test/runTest.ts similarity index 100% rename from src/test/runTest.ts rename to src/extension/test/runTest.ts diff --git a/src/test/suite/extension.test.ts b/src/extension/test/suite/extension.test.ts similarity index 100% rename from src/test/suite/extension.test.ts rename to src/extension/test/suite/extension.test.ts diff --git a/src/test/suite/index.ts b/src/extension/test/suite/index.ts similarity index 100% rename from src/test/suite/index.ts rename to src/extension/test/suite/index.ts diff --git a/src/extension/tsconfig.json b/src/extension/tsconfig.json new file mode 100644 index 000000000..13b312df8 --- /dev/null +++ b/src/extension/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + "rootDir": "." + } +} \ No newline at end of file diff --git a/src/util.ts b/src/extension/util.ts similarity index 100% rename from src/util.ts rename to src/extension/util.ts diff --git a/vscode.proposed.d.ts b/src/extension/vscode.proposed.d.ts similarity index 100% rename from vscode.proposed.d.ts rename to src/extension/vscode.proposed.d.ts diff --git a/src/workspaceViewer.ts b/src/extension/workspaceViewer.ts similarity index 100% rename from src/workspaceViewer.ts rename to src/extension/workspaceViewer.ts diff --git a/src/tsconfig.base.json b/src/tsconfig.base.json new file mode 100644 index 000000000..dff055aef --- /dev/null +++ b/src/tsconfig.base.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2018", + "outDir": "../out", + "lib": [ + "es2018", + "dom" + ], + "sourceMap": true, + // "strictNullChecks": true, + "rootDir": "src" + }, + "exclude": [ + "node_modules", + ".vscode-test", + "html/*" + ] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 726e69f08..df9bd54c6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,19 +1,11 @@ - { - "compilerOptions": { - "module": "commonjs", - "target": "es2018", - "outDir": "out", - "lib": [ - "es2018" - ], - "sourceMap": true, - // "strictNullChecks": true, - "rootDir": "src" - }, - "exclude": [ - "node_modules", - ".vscode-test", - "html/*" - ] + "files": [], + "references": [ + { + "path": "./src/client" + }, + { + "path": "./src/extension" + } + ] } \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index 0e5845ab7..f28c42232 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -4,11 +4,13 @@ const path = require('path'); const CopyPlugin = require('copy-webpack-plugin'); +const { extension } = require('showdown'); +const { DefinePlugin } = require('webpack'); -module.exports = { +const extensionConfig = { target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/ - entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/ + entry: './src/extension/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/ output: { // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/ path: path.resolve(__dirname, 'dist'), @@ -40,21 +42,71 @@ module.exports = { plugins: [ new CopyPlugin({ patterns: [ - { from: './node_modules/jquery/dist/jquery.min.js', to: 'resources' }, - { from: './node_modules/jquery.json-viewer/json-viewer', to: 'resources' }, - { from: './node_modules/bootstrap/dist/js/bootstrap.min.js', to: 'resources' }, - { from: './node_modules/bootstrap/dist/css/bootstrap.min.css', to: 'resources' }, - { from: './node_modules/datatables.net-bs4/js/dataTables.bootstrap4.min.js', to: 'resources' }, - { from: './node_modules/datatables.net-bs4/css/dataTables.bootstrap4.min.css', to: 'resources' }, - { from: './node_modules/datatables.net/js/jquery.dataTables.min.js', to: 'resources' }, - { from: './node_modules/datatables.net-fixedheader/js/dataTables.fixedHeader.min.js', to: 'resources' }, - { from: './node_modules/datatables.net-fixedheader-jqui/js/fixedHeader.jqueryui.min.js', to: 'resources' }, - { from: './node_modules/datatables.net-fixedheader-jqui/css/fixedHeader.jqueryui.min.css', to: 'resources' }, - { from: './node_modules/fotorama/fotorama.js', to: 'resources' }, - { from: './node_modules/fotorama/fotorama.css', to: 'resources' }, - { from: './node_modules/fotorama/fotorama.png', to: 'resources' }, - { from: './node_modules/fotorama/fotorama@2x.png', to: 'resources' }, - ] - }), + { from: './node_modules/jquery/dist/jquery.min.js', to: 'resources' }, + { from: './node_modules/jquery.json-viewer/json-viewer', to: 'resources' }, + { from: './node_modules/bootstrap/dist/js/bootstrap.min.js', to: 'resources' }, + { from: './node_modules/bootstrap/dist/css/bootstrap.min.css', to: 'resources' }, + { from: './node_modules/datatables.net-bs4/js/dataTables.bootstrap4.min.js', to: 'resources' }, + { from: './node_modules/datatables.net-bs4/css/dataTables.bootstrap4.min.css', to: 'resources' }, + { from: './node_modules/datatables.net/js/jquery.dataTables.min.js', to: 'resources' }, + { from: './node_modules/datatables.net-fixedheader/js/dataTables.fixedHeader.min.js', to: 'resources' }, + { from: './node_modules/datatables.net-fixedheader-jqui/js/fixedHeader.jqueryui.min.js', to: 'resources' }, + { from: './node_modules/datatables.net-fixedheader-jqui/css/fixedHeader.jqueryui.min.css', to: 'resources' }, + { from: './node_modules/fotorama/fotorama.js', to: 'resources' }, + { from: './node_modules/fotorama/fotorama.css', to: 'resources' }, + { from: './node_modules/fotorama/fotorama.png', to: 'resources' }, + { from: './node_modules/fotorama/fotorama@2x.png', to: 'resources' }, + ] + }), ], }; + +const clientConfig = { + target: 'web', + entry: { + "tableRenderer": "./src/client/renderers/tableRenderer.tsx" + }, + output: { + // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/ + path: path.resolve(__dirname, 'dist/'), + filename: '[name].js', + devtoolModuleFilenameTemplate: '../[resource-path]', + publicPath: '' + }, + resolve: { + extensions: ['.ts', '.tsx', '.js', '.jsx', '.css'], + }, + module: { + rules: [ + // Allow importing ts(x) files: + { + test: /\.tsx?$/, + exclude: /node_modules/, + use: [ + { + loader: 'ts-loader' + } + ] + }, + // Allow importing CSS modules: + { + test: /\.css$/, + use: ['style-loader', 'css-loader'], + }, + { + test: /\.(woff(2)?|ttf|eot|svg|png|jpg)(\?v=\d+\.\d+\.\d+)?$/, + use: ['url-loader'] + } + ] + }, + plugins: [ + new DefinePlugin({ + "process.env": { + NODE_ENV: JSON.stringify("production") + } + }) + ] +} + +// module.exports = [extensionConfig, clientConfig] +module.exports = [clientConfig] From ba7672a218c8ebc40420bcbed10f8ad69fd1d1c0 Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Tue, 9 Feb 2021 15:05:30 +0100 Subject: [PATCH 71/78] proper implementation for the viewer --- package.json | 8 ++++++++ samples/test1.rmd | 4 ++-- src/client/renderers/viewerRenderer.tsx | 12 ++++++++++-- src/extension/notebook.ts | 10 ++-------- webpack.config.js | 7 ++++--- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 50df208ab..318a25736 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,14 @@ "mimeTypes": [ "ms-vscode.r-notebook/table" ] + }, + { + "id": "r-notebook-viewer-renderer", + "displayName": "Notebook Viewer Render", + "entrypoint": "./dist/viewerRenderer.js", + "mimeTypes": [ + "ms-vscode.r-notebook/viewer" + ] } ], "viewsContainers": { diff --git a/samples/test1.rmd b/samples/test1.rmd index f379dcf57..774ee9d3f 100644 --- a/samples/test1.rmd +++ b/samples/test1.rmd @@ -8,10 +8,10 @@ df = data.frame(a = c(1,2,3,4), b = c(10, 20, 13, 1)) library(ggplot2) library(plotly) -df +ggplotly(ggplot(df, aes(a, b)) + geom_point()) ``` ```{r} -ggplot(df, aes(a, b)) + geom_point() +ggplotly(ggplot(df, aes(a, b)) + geom_point()) ``` ```{r} diff --git a/src/client/renderers/viewerRenderer.tsx b/src/client/renderers/viewerRenderer.tsx index 5296677c6..5981cb13f 100644 --- a/src/client/renderers/viewerRenderer.tsx +++ b/src/client/renderers/viewerRenderer.tsx @@ -1,7 +1,15 @@ -const notebookApi = acquireNotebookRendererApi("r-notebook-table-renderer"); +const notebookApi = acquireNotebookRendererApi("r-notebook-viewer-renderer"); notebookApi.onDidCreateOutput((evt) => { const output = evt.output.data[evt.mimeType]; - evt.element.innerHTML = + const iframe = document.createElement("iframe"); + iframe.style.border = "0"; + iframe.style.width = "90vw" + iframe.style.minHeight = "30vw" + iframe.sandbox.add("allow-scripts"); + iframe.sandbox.add("allow-forms"); + iframe.sandbox.add("allow-same-origin"); + iframe.srcdoc = output + evt.element.appendChild(iframe) }); diff --git a/src/extension/notebook.ts b/src/extension/notebook.ts index 720ded5ed..349c373bc 100644 --- a/src/extension/notebook.ts +++ b/src/extension/notebook.ts @@ -341,17 +341,11 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode const html = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(); const htmlDir = dirname(response.result) const htmlInline = await inlineAll(html, htmlDir) - const htmlWrapped = ` - - - ` + return { outputKind: vscode.CellOutputKind.Rich, data: { - 'text/html': htmlWrapped + 'ms-vscode.r-notebook/viewer': htmlInline }, } } diff --git a/webpack.config.js b/webpack.config.js index f28c42232..e33c337f5 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -64,7 +64,8 @@ const extensionConfig = { const clientConfig = { target: 'web', entry: { - "tableRenderer": "./src/client/renderers/tableRenderer.tsx" + "tableRenderer": "./src/client/renderers/tableRenderer.tsx", + "viewerRenderer": "./src/client/renderers/viewerRenderer.tsx" }, output: { // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/ @@ -108,5 +109,5 @@ const clientConfig = { ] } -// module.exports = [extensionConfig, clientConfig] -module.exports = [clientConfig] +module.exports = [extensionConfig, clientConfig] +// module.exports = [clientConfig] From 3ce52a57dcdd74755915f2f5b92c8d22d33d8e24 Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Tue, 9 Feb 2021 15:20:28 +0100 Subject: [PATCH 72/78] disable other output formats --- src/extension/notebook.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/extension/notebook.ts b/src/extension/notebook.ts index 349c373bc..254df0891 100644 --- a/src/extension/notebook.ts +++ b/src/extension/notebook.ts @@ -354,9 +354,10 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode return { outputKind: vscode.CellOutputKind.Rich, data: { - 'ms-vscode.r-notebook/table': response.result.data, - 'text/markdown': response.result.markdown, - 'application/json': response.result.data, + 'ms-vscode.r-notebook/table': response.result.data + // TODO: make the html table default, no clue how to do this. + // 'text/markdown': response.result.markdown, + // 'application/json': response.result.data, }, } } From 694e60b64ac3693505f1c332a1c3058be2690c93 Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Wed, 10 Feb 2021 10:17:23 +0100 Subject: [PATCH 73/78] fixes some types --- .gitignore | 1 + R/notebook.R | 14 +++++++------- src/extension/notebook.ts | 31 ++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index f781a72a9..9a3b2e6a8 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ temp.* tmp temp .Rhistory +.Rproj.user diff --git a/R/notebook.R b/R/notebook.R index 5077deeae..d5b55315e 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -64,19 +64,20 @@ r$run(function() { list( id = id, type = "plot", - result = list.files(plot_dir, pattern = ".*\\.svg", full.names = T) + # FIXME: support multiple plots + result = list(plot = list.files(plot_dir, pattern = ".*\\.svg", full.names = T)[[1]]) ) } else if (!is.null(viewer_file)) { list( id = id, type = "viewer", - result = viewer_file + result = list(file = viewer_file) ) } else if (!is.null(browser_url)) { list( id = id, type = "browser", - result = browser_url + result = list(url = browser_url) ) } else if (out$visible) { if (inherits(out$value, "data.frame")) { @@ -85,7 +86,6 @@ r$run(function() { id = id, type = "table", result = list( - html = knitr::kable(table, format = "html"), markdown = paste0(knitr::kable(table, format = "markdown"), collapse = "\n"), data = head(out$value, 1000) ) @@ -94,21 +94,21 @@ r$run(function() { list( id = id, type = "text", - result = paste0(text, collapse = "\n") + result = list(text = paste0(text, collapse = "\n")) ) } } else { list( id = id, type = "text", - result = "" + result = list(text = "") ) } }, error = function(e) { list( id = id, type = "error", - result = conditionMessage(e) + result = list(error = conditionMessage(e)) ) }) diff --git a/src/extension/notebook.ts b/src/extension/notebook.ts index 254df0891..ca515c2f3 100644 --- a/src/extension/notebook.ts +++ b/src/extension/notebook.ts @@ -10,10 +10,19 @@ interface RKernelRequest { expr?: any; } +interface RKernelResult { + text?: string, + plot?: string, + url?: string, + error?: string, + data?: any, + markdown?: string +} + interface RKernelResponse { id: number; - type: 'text' | 'plot' | 'viewer' | 'browser' | 'error'; - result: string; + type: 'text' | 'plot' | 'viewer' | 'browser' | 'error' | 'table'; + result: RKernelResult } class RKernel { @@ -307,8 +316,8 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode await vscode.workspace.fs.writeFile(targetResource, Buffer.from(content)); } - async renderPlotOutput(response) { - const content = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(); + async renderPlotOutput(response: RKernelResponse) { + const content = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result.plot))).toString(); return { outputKind: vscode.CellOutputKind.Rich, @@ -318,9 +327,9 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode }; } - async renderTextOutput(response) { + async renderTextOutput(response: RKernelResponse) { // Text may contain html, so render as such. - const isXml = response.result.match(/^<.+>$/gms) != null + const isXml = response.result.text.match(/^<.+>$/gms) != null if (isXml) { return { @@ -337,9 +346,9 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } } - async renderHtmlOutput(response) { - const html = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result))).toString(); - const htmlDir = dirname(response.result) + async renderHtmlOutput(response: RKernelResponse) { + const html = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result.url))).toString(); + const htmlDir = dirname(response.result.url) const htmlInline = await inlineAll(html, htmlDir) return { @@ -350,7 +359,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } } - async renderTableOutput(response) { + async renderTableOutput(response: RKernelResponse) { return { outputKind: vscode.CellOutputKind.Rich, data: { @@ -362,7 +371,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } } - async renderOutput(cell, response) { + async renderOutput(cell: vscode.NotebookCell, response: RKernelResponse) { switch (response.type) { case 'text': { From 8c6d6b771d71f88af42d3be939ad01ae84258789 Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Wed, 10 Feb 2021 11:30:31 +0100 Subject: [PATCH 74/78] refactored some deprecates --- R/notebook.R | 2 +- src/extension/notebook.ts | 120 +++++++++----- .../{ => types}/vscode.proposed.d.ts | 153 +++++++++++++----- 3 files changed, 197 insertions(+), 78 deletions(-) rename src/extension/{ => types}/vscode.proposed.d.ts (95%) diff --git a/R/notebook.R b/R/notebook.R index d5b55315e..e004e7838 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -65,7 +65,7 @@ r$run(function() { id = id, type = "plot", # FIXME: support multiple plots - result = list(plot = list.files(plot_dir, pattern = ".*\\.svg", full.names = T)[[1]]) + result = list(plot = list.files(plot_dir, pattern = ".*\\.svg", full.names = T)) ) } else if (!is.null(viewer_file)) { list( diff --git a/src/extension/notebook.ts b/src/extension/notebook.ts index ca515c2f3..b2769caeb 100644 --- a/src/extension/notebook.ts +++ b/src/extension/notebook.ts @@ -14,6 +14,7 @@ interface RKernelResult { text?: string, plot?: string, url?: string, + file?: string, error?: string, data?: any, markdown?: string @@ -161,6 +162,34 @@ class RNotebook implements vscode.Disposable { } } +class RNotebookCellEdit { + private uri: vscode.Uri; + private cellIndex: number; + + constructor(uri: vscode.Uri, cellIndex: number) { + this.uri = uri; + this.cellIndex = cellIndex + } + + apply(outputs?: (vscode.NotebookCellOutput | vscode.CellOutput)[], metadata?: vscode.NotebookCellMetadata, outputAppend: boolean = false) { + const edit = new vscode.WorkspaceEdit(); + + if (outputs){ + if (outputAppend) { + edit.appendNotebookCellOutput(this.uri, this.cellIndex, outputs) + } else { + edit.replaceNotebookCellOutput(this.uri, this.cellIndex, outputs) + } + } + + if (metadata) { + edit.replaceNotebookCellMetadata(this.uri, this.cellIndex, metadata) + } + + vscode.workspace.applyEdit(edit) + } +} + export class RNotebookProvider implements vscode.NotebookContentProvider, vscode.NotebookKernel { public label = 'R Kernel'; private kernelScript: string; @@ -316,7 +345,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode await vscode.workspace.fs.writeFile(targetResource, Buffer.from(content)); } - async renderPlotOutput(response: RKernelResponse) { + async renderPlotOutput(response: RKernelResponse): Promise { const content = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result.plot))).toString(); return { @@ -327,7 +356,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode }; } - async renderTextOutput(response: RKernelResponse) { + async renderTextOutput(response: RKernelResponse): Promise { // Text may contain html, so render as such. const isXml = response.result.text.match(/^<.+>$/gms) != null @@ -335,20 +364,22 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode return { outputKind: vscode.CellOutputKind.Rich, data: { - 'text/html': response.result + 'text/html': response.result.text } } } else { return { - outputKind: vscode.CellOutputKind.Text, - text: response.result, + outputKind: vscode.CellOutputKind.Rich, + data: { + 'text/plain': response.result.text + } } } } - async renderHtmlOutput(response: RKernelResponse) { - const html = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result.url))).toString(); - const htmlDir = dirname(response.result.url) + async renderHtmlOutput(response: RKernelResponse): Promise { + const html = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result.file))).toString(); + const htmlDir = dirname(response.result.file) const htmlInline = await inlineAll(html, htmlDir) return { @@ -359,7 +390,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } } - async renderTableOutput(response: RKernelResponse) { + async renderTableOutput(response: RKernelResponse): Promise { return { outputKind: vscode.CellOutputKind.Rich, data: { @@ -371,48 +402,43 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } } - async renderOutput(cell: vscode.NotebookCell, response: RKernelResponse) { + async renderOutput(response: RKernelResponse): Promise { switch (response.type) { case 'text': { - cell.outputs = [await this.renderTextOutput(response)]; - break; + return [await this.renderTextOutput(response)]; } case 'plot': { - cell.outputs = [await this.renderPlotOutput(response)] + return [await this.renderPlotOutput(response)] break; } case 'viewer': { - cell.outputs = [await this.renderHtmlOutput(response)]; - break; + return [await this.renderHtmlOutput(response)]; } case 'browser': { - cell.outputs = [{ + return [{ outputKind: vscode.CellOutputKind.Rich, data: { 'text/plain': response.result, }, }]; - break; } case 'table': { - cell.outputs = [await this.renderTableOutput(response)]; - break; + return [await this.renderTableOutput(response)]; } case 'error': { - cell.metadata.runState = vscode.NotebookCellRunState.Error; - cell.outputs = [{ + return [{ outputKind: vscode.CellOutputKind.Error, - evalue: response.result, + evalue: response.result.error, ename: 'Error', traceback: [], }]; - break; } } } - onDidChangeNotebook = new vscode.EventEmitter().event; + // FIXME: I think this should be changed in NotebookCellsChangeEvent + onDidChangeNotebook = new vscode.EventEmitter().event; async resolveNotebook(): Promise { } @@ -449,28 +475,44 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode return; } + const cellEdit = new RNotebookCellEdit(document.uri, cell.index) + if (notebook && cell.metadata.runState !== vscode.NotebookCellRunState.Running) { try { - cell.metadata.runState = vscode.NotebookCellRunState.Running; - const start = +new Date(); - cell.metadata.runStartTime = start; - cell.metadata.executionOrder = ++this.runIndex; + const startTime = +new Date() + + cellEdit.apply(undefined, { + runState: vscode.NotebookCellRunState.Running, + runStartTime: startTime, + executionOrder: ++this.runIndex, + }) + const response = await notebook.eval(cell); - cell.metadata.runState = vscode.NotebookCellRunState.Success; - cell.metadata.lastRunDuration = +new Date() - cell.metadata.runStartTime; console.log(`uri: ${cell.uri}, id: ${response.id}, type: ${response.type}, result: ${response.result}`); - await this.renderOutput(cell, response) + const outputs = await this.renderOutput(response) + + const runState = (outputs[0].outputKind === vscode.CellOutputKind.Error) ? vscode.NotebookCellRunState.Error : vscode.NotebookCellRunState.Success + + cellEdit.apply(outputs, { + runStartTime: +new Date(), + executionOrder: ++this.runIndex, + runState, + lastRunDuration: +new Date() - startTime, + }) + + } catch (e) { - cell.outputs = [{ - outputKind: vscode.CellOutputKind.Error, - evalue: e.toString(), - ename: '', - traceback: [], - }]; - cell.metadata.runState = vscode.NotebookCellRunState.Error; - cell.metadata.lastRunDuration = undefined; + cellEdit.apply([{ + outputKind: vscode.CellOutputKind.Error, + evalue: e.toString(), + ename: '', + traceback: [], + }], { + runState: vscode.NotebookCellRunState.Error, + lastRunDuration: undefined + }) } } } diff --git a/src/extension/vscode.proposed.d.ts b/src/extension/types/vscode.proposed.d.ts similarity index 95% rename from src/extension/vscode.proposed.d.ts rename to src/extension/types/vscode.proposed.d.ts index f48e12c11..373d3a905 100644 --- a/src/extension/vscode.proposed.d.ts +++ b/src/extension/types/vscode.proposed.d.ts @@ -1073,6 +1073,7 @@ declare module 'vscode' { custom?: { [key: string]: any; }; } + // todo@API support ids https://github.com/jupyter/enhancement-proposals/blob/master/62-cell-id/cell-id.md export interface NotebookCell { readonly index: number; readonly notebook: NotebookDocument; @@ -1082,6 +1083,7 @@ declare module 'vscode' { readonly language: string; /** @deprecated use WorkspaceEdit.replaceCellOutput */ outputs: CellOutput[]; + // readonly outputs2: NotebookCellOutput[]; /** @deprecated use WorkspaceEdit.replaceCellMetadata */ metadata: NotebookCellMetadata; } @@ -1318,6 +1320,7 @@ declare module 'vscode' { readonly visibleRanges: ReadonlyArray; } + // todo@API support ids https://github.com/jupyter/enhancement-proposals/blob/master/62-cell-id/cell-id.md export interface NotebookCellData { readonly cellKind: CellKind; readonly source: string; @@ -1482,13 +1485,14 @@ declare module 'vscode' { constructor(mime: string, value: unknown, metadata?: Record); } - //TODO@jrieken add id? + // @jrieken + //TODO@API add execution count to cell output? export class NotebookCellOutput { + readonly id: string; readonly outputs: NotebookCellOutputItem[]; - readonly metadata?: Record; - constructor(outputs: NotebookCellOutputItem[], metadata?: Record); + constructor(outputs: NotebookCellOutputItem[]); //TODO@jrieken HACK to workaround dependency issues... toJSON(): any; @@ -1502,8 +1506,14 @@ declare module 'vscode' { replaceNotebookMetadata(uri: Uri, value: NotebookDocumentMetadata): void; replaceNotebookCells(uri: Uri, start: number, end: number, cells: NotebookCellData[], metadata?: WorkspaceEditEntryMetadata): void; replaceNotebookCellMetadata(uri: Uri, index: number, cellMetadata: NotebookCellMetadata, metadata?: WorkspaceEditEntryMetadata): void; + replaceNotebookCellOutput(uri: Uri, index: number, outputs: (NotebookCellOutput | CellOutput)[], metadata?: WorkspaceEditEntryMetadata): void; - appendNotebookCellOutput(uri: Uri, index: number, outputs: NotebookCellOutput[], metadata?: WorkspaceEditEntryMetadata): void; + appendNotebookCellOutput(uri: Uri, index: number, outputs: (NotebookCellOutput | CellOutput)[], metadata?: WorkspaceEditEntryMetadata): void; + + // TODO@api + // https://jupyter-protocol.readthedocs.io/en/latest/messaging.html#update-display-data + // replaceNotebookCellOutput(uri: Uri, index: number, outputId:string, outputs: NotebookCellOutputItem[], metadata?: WorkspaceEditEntryMetadata): void; + // appendNotebookCellOutput(uri: Uri, index: number, outputId:string, outputs: NotebookCellOutputItem[], metadata?: WorkspaceEditEntryMetadata): void; } export interface NotebookEditorEdit { @@ -1972,6 +1982,11 @@ declare module 'vscode' { //#region https://github.com/microsoft/vscode/issues/16221 + // todo@API rename to InlayHint + // todo@API add "mini-markdown" for links and styles + // todo@API remove description + // (done:) add InlayHintKind with type, argument, etc + export namespace languages { /** * Register a inline hints provider. @@ -1987,6 +2002,12 @@ declare module 'vscode' { export function registerInlineHintsProvider(selector: DocumentSelector, provider: InlineHintsProvider): Disposable; } + export enum InlineHintKind { + Other = 0, + Type = 1, + Parameter = 2, + } + /** * Inline hint information. */ @@ -1999,9 +2020,10 @@ declare module 'vscode' { * The range of the hint. */ range: Range; - /** - * Tooltip when hover on the hint. - */ + + kind?: InlineHintKind; + + // todo@API remove this description?: string | MarkdownString; /** * Whitespace before the hint. @@ -2012,16 +2034,7 @@ declare module 'vscode' { */ whitespaceAfter?: boolean; - /** - * Creates a new inline hint information object. - * - * @param text The text of the hint. - * @param range The range of the hint. - * @param hoverMessage Tooltip when hover on the hint. - * @param whitespaceBefore Whitespace before the hint. - * @param whitespaceAfter TWhitespace after the hint. - */ - constructor(text: string, range: Range, description?: string | MarkdownString, whitespaceBefore?: boolean, whitespaceAfter?: boolean); + constructor(text: string, range: Range, kind?: InlineHintKind); } /** @@ -2095,10 +2108,12 @@ declare module 'vscode' { export function registerTestProvider(testProvider: TestProvider): Disposable; /** - * Runs tests with the given options. If no options are given, then - * all tests are run. Returns the resulting test run. + * Runs tests. The "run" contains the list of tests to run as well as a + * method that can be used to update their state. At the point in time + * that "run" is called, all tests given in the run have their state + * automatically set to {@link TestRunState.Queued}. */ - export function runTests(options: TestRunOptions, cancellationToken?: CancellationToken): Thenable; + export function runTests(run: TestRunOptions, cancellationToken?: CancellationToken): Thenable; /** * Returns an observer that retrieves tests in the given workspace folder. @@ -2212,6 +2227,14 @@ declare module 'vscode' { */ readonly discoveredInitialTests?: Thenable; + /** + * An event that fires when a test becomes outdated, as a result of + * file changes, for example. In "watch" mode, tests that are outdated + * will be automatically re-run after a short delay. Firing a test + * with children will mark the entire subtree as outdated. + */ + readonly onDidInvalidateTest?: Event; + /** * Dispose will be called when there are no longer observers interested * in the hierarchy. @@ -2256,11 +2279,11 @@ declare module 'vscode' { * @todo this will eventually need to be able to return a summary report, coverage for example. */ // eslint-disable-next-line vscode-dts-provider-naming - runTests?(options: TestRunOptions, cancellationToken: CancellationToken): ProviderResult; + runTests?(options: TestRun, cancellationToken: CancellationToken): ProviderResult; } /** - * Options given to `TestProvider.runTests` + * Options given to {@link test.runTests} */ export interface TestRunOptions { /** @@ -2275,6 +2298,17 @@ declare module 'vscode' { debug: boolean; } + /** + * Options given to `TestProvider.runTests` + */ + export interface TestRun extends TestRunOptions { + /** + * Updates the state of the test in the run. By default, all tests involved + * in the run will have a "queued" state until they are updated by this method. + */ + setState(test: T, state: TestState): void; + } + /** * A test item is an item shown in the "test explorer" view. It encompasses * both a suite and a test, since they have almost or identical capabilities. @@ -2323,12 +2357,6 @@ declare module 'vscode' { * Optional list of nested tests for this item. */ children?: TestItem[]; - - /** - * Test run state. Will generally be {@link TestRunState.Unset} by - * default. - */ - state: TestState; } /** @@ -2363,11 +2391,11 @@ declare module 'vscode' { * in order to update it. This allows consumers to quickly and easily check * for changes via object identity. */ - export class TestState { + export interface TestState { /** * Current state of the test. */ - readonly runState: TestRunState; + readonly state: TestRunState; /** * Optional duration of the test run, in milliseconds. @@ -2378,14 +2406,7 @@ declare module 'vscode' { * Associated test run message. Can, for example, contain assertion * failure information if the test fails. */ - readonly messages: ReadonlyArray>; - - /** - * @param state Run state to hold in the test state - * @param messages List of associated messages for the test - * @param duration Length of time the test run took, if appropriate. - */ - constructor(runState: TestRunState, messages?: TestMessage[], duration?: number); + readonly messages?: ReadonlyArray>; } /** @@ -2605,4 +2626,60 @@ declare module 'vscode' { } //#endregion + + //#region https://github.com/microsoft/vscode/issues/106488 + + export enum WorkspaceTrustState { + /** + * The workspace is untrusted, and it will have limited functionality. + */ + Untrusted = 0, + + /** + * The workspace is trusted, and all functionality will be available. + */ + Trusted = 1, + + /** + * The initial state of the workspace. + * + * If trust will be required, users will be prompted to make a choice. + */ + Unknown = 2 + } + + /** + * The event data that is fired when the trust state of the workspace changes + */ + export interface WorkspaceTrustStateChangeEvent { + /** + * Previous trust state of the workspace + */ + previousTrustState: WorkspaceTrustState; + + /** + * Current trust state of the workspace + */ + currentTrustState: WorkspaceTrustState; + } + + export namespace workspace { + /** + * The trust state of the current workspace + */ + export const trustState: WorkspaceTrustState; + + /** + * Prompt the user to chose whether to trust the current workspace + * @param message Optional message which would be displayed in the prompt + */ + export function requireWorkspaceTrust(message?: string): Thenable; + + /** + * Event that fires when the trust state of the current workspace changes + */ + export const onDidChangeWorkspaceTrustState: Event; + } + + //#endregion } From 138f3877f3fad337bce2fa24c3cbdf702381090c Mon Sep 17 00:00:00 2001 From: Kun Ren Date: Wed, 10 Feb 2021 21:52:50 +0800 Subject: [PATCH 75/78] Refine code --- R/notebook.R | 96 +++++++++++++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/R/notebook.R b/R/notebook.R index e004e7838..f6268d42c 100644 --- a/R/notebook.R +++ b/R/notebook.R @@ -20,10 +20,10 @@ r$run(function() { .vscNotebook <- local({ viewer_file <- NULL browser_url <- NULL - plot.new.called <- F + plot.new.called <- FALSE set_plot_new <- function() { - plot.new.called <<- T + plot.new.called <<- TRUE } setHook("before.plot.new", set_plot_new) setHook("before.grid.newpage", set_plot_new) @@ -44,75 +44,73 @@ r$run(function() { plot_dir <- tempdir() plot_file <- file.path(plot_dir, "plot%03d.svg") - svg(plot_file, width = 12, height = 8) - viewer_file <<- NULL browser_url <<- NULL + error <- NULL res <- tryCatch({ + svg(plot_file, width = 12, height = 8) expr <- parse(text = expr) out <- withVisible(eval(expr, globalenv())) - text <- utils::capture.output(print(out$value, view = TRUE)) - - dev.off() + }, error = function(e) { + error <<- list( + id = id, + type = "error", + result = list(error = conditionMessage(e)) + ) + }, finally = { graphics.off() + }) - if (plot.new.called) { - plot.new.called <<- F + if (!is.null(error)) { + error + } else if (plot.new.called) { + plot.new.called <<- FALSE + list( + id = id, + type = "plot", + # FIXME: support multiple plots + result = list(plot = list.files(plot_dir, pattern = ".*\\.svg", full.names = TRUE)) + ) + } else if (!is.null(viewer_file)) { + list( + id = id, + type = "viewer", + result = list(file = viewer_file) + ) + } else if (!is.null(browser_url)) { + list( + id = id, + type = "browser", + result = list(url = browser_url) + ) + } else if (out$visible) { + if (is.data.frame(out$value)) { + table <- head(out$value, 10) list( id = id, - type = "plot", - # FIXME: support multiple plots - result = list(plot = list.files(plot_dir, pattern = ".*\\.svg", full.names = T)) - ) - } else if (!is.null(viewer_file)) { - list( - id = id, - type = "viewer", - result = list(file = viewer_file) - ) - } else if (!is.null(browser_url)) { - list( - id = id, - type = "browser", - result = list(url = browser_url) - ) - } else if (out$visible) { - if (inherits(out$value, "data.frame")) { - table <- head(out$value, 10) - list( - id = id, - type = "table", - result = list( - markdown = paste0(knitr::kable(table, format = "markdown"), collapse = "\n"), - data = head(out$value, 1000) - ) - ) - } else { - list( - id = id, - type = "text", - result = list(text = paste0(text, collapse = "\n")) + type = "table", + result = list( + markdown = paste0(knitr::kable(table, format = "markdown"), collapse = "\n"), + data = head(out$value, 1000) ) - } + ) } else { list( id = id, type = "text", - result = list(text = "") + result = list(text = paste0(text, collapse = "\n")) ) } - }, error = function(e) { + } else { list( id = id, - type = "error", - result = list(error = conditionMessage(e)) + type = "text", + result = list(text = "") ) - }) - - res + } } environment() From 46430318c36db724d54c8976e94ed1fc1e314b35 Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Wed, 10 Feb 2021 21:16:56 +0100 Subject: [PATCH 76/78] should load outputs and metadata from json file. --- src/extension/notebook.ts | 58 ++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/src/extension/notebook.ts b/src/extension/notebook.ts index b2769caeb..c850f6af3 100644 --- a/src/extension/notebook.ts +++ b/src/extension/notebook.ts @@ -26,6 +26,15 @@ interface RKernelResponse { result: RKernelResult } +interface OutputCacheCells { + [cellIndex: string]: OutputCacheCell +} + +interface OutputCacheCell { + outputs: vscode.CellOutput[]; + metadata: vscode.NotebookCellMetadata; +} + class RKernel { private kernelScript: string; private doc: vscode.NotebookDocument; @@ -174,7 +183,7 @@ class RNotebookCellEdit { apply(outputs?: (vscode.NotebookCellOutput | vscode.CellOutput)[], metadata?: vscode.NotebookCellMetadata, outputAppend: boolean = false) { const edit = new vscode.WorkspaceEdit(); - if (outputs){ + if (outputs) { if (outputAppend) { edit.appendNotebookCellOutput(this.uri, this.cellIndex, outputs) } else { @@ -233,6 +242,13 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode async openNotebook(uri: vscode.Uri): Promise { const content = (await vscode.workspace.fs.readFile(uri)).toString(); + + const outputUri = vscode.Uri.parse(uri.toString() + ".json") + let outputContent: OutputCacheCells = {} + try { + outputContent = JSON.parse((await vscode.workspace.fs.readFile(outputUri)).toString()) + } catch {} + const lines = content.split(/\r?\n/); const cells: vscode.NotebookCellData[] = []; @@ -290,14 +306,14 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } } else if (cellType === 'r') { if (lines[line].startsWith('```')) { + const cacheCell = outputContent[cells.length] cells.push({ cellKind: vscode.CellKind.Code, source: lines.slice(cellStartLine + 1, line).join('\n'), language: 'r', - outputs: [], + outputs: cacheCell?.outputs || [], metadata: { - editable: true, - runnable: true, + ...cacheCell?.metadata || {}, custom: { header: lines[cellStartLine], footer: lines[line], @@ -320,6 +336,8 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode async save(document: vscode.NotebookDocument, targetResource: vscode.Uri, cancellation: vscode.CancellationToken): Promise { let content = ''; + let outputContent = {} + for (const cell of document.cells) { if (cancellation.isCancellationRequested) { return; @@ -340,11 +358,17 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } else { content += '```{' + cell.language + '}\n' + cell.document.getText() + '\n```\n'; } + + // save output as-is + outputContent[cell.index] = { + outputs: cell.outputs, + metadata: cell.metadata + } } } await vscode.workspace.fs.writeFile(targetResource, Buffer.from(content)); + await vscode.workspace.fs.writeFile(vscode.Uri.parse(targetResource.toString() + ".json"), Buffer.from(JSON.stringify(outputContent))); } - async renderPlotOutput(response: RKernelResponse): Promise { const content = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result.plot))).toString(); @@ -378,7 +402,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } async renderHtmlOutput(response: RKernelResponse): Promise { - const html = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result.file))).toString(); + const html = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result.file))).toString(); const htmlDir = dirname(response.result.file) const htmlInline = await inlineAll(html, htmlDir) @@ -410,7 +434,6 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } case 'plot': { return [await this.renderPlotOutput(response)] - break; } case 'viewer': { return [await this.renderHtmlOutput(response)]; @@ -437,10 +460,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } } - // FIXME: I think this should be changed in NotebookCellsChangeEvent - onDidChangeNotebook = new vscode.EventEmitter().event; - - async resolveNotebook(): Promise { } + async resolveNotebook(): Promise { } async saveNotebook(document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { await this.save(document, document.uri, cancellation); @@ -505,14 +525,14 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } catch (e) { cellEdit.apply([{ - outputKind: vscode.CellOutputKind.Error, - evalue: e.toString(), - ename: '', - traceback: [], - }], { - runState: vscode.NotebookCellRunState.Error, - lastRunDuration: undefined - }) + outputKind: vscode.CellOutputKind.Error, + evalue: e.toString(), + ename: '', + traceback: [], + }], { + runState: vscode.NotebookCellRunState.Error, + lastRunDuration: undefined + }) } } } From b86f9fb121298bc2c0a39b2bcfbaefc67cd3ab0d Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Fri, 12 Feb 2021 13:03:30 +0100 Subject: [PATCH 77/78] saving and loading output works now. --- src/extension/notebook.ts | 126 ++++----- src/extension/types/vscode.proposed.d.ts | 325 +++++++++++------------ 2 files changed, 203 insertions(+), 248 deletions(-) diff --git a/src/extension/notebook.ts b/src/extension/notebook.ts index c850f6af3..6a941877f 100644 --- a/src/extension/notebook.ts +++ b/src/extension/notebook.ts @@ -31,7 +31,7 @@ interface OutputCacheCells { } interface OutputCacheCell { - outputs: vscode.CellOutput[]; + outputs: vscode.NotebookCellOutput[]; metadata: vscode.NotebookCellMetadata; } @@ -180,14 +180,14 @@ class RNotebookCellEdit { this.cellIndex = cellIndex } - apply(outputs?: (vscode.NotebookCellOutput | vscode.CellOutput)[], metadata?: vscode.NotebookCellMetadata, outputAppend: boolean = false) { + async apply(outputs?: vscode.NotebookCellOutput, metadata?: vscode.NotebookCellMetadata, outputAppend: boolean = false): Promise { const edit = new vscode.WorkspaceEdit(); if (outputs) { if (outputAppend) { - edit.appendNotebookCellOutput(this.uri, this.cellIndex, outputs) + edit.appendNotebookCellOutput(this.uri, this.cellIndex, [outputs]) } else { - edit.replaceNotebookCellOutput(this.uri, this.cellIndex, outputs) + edit.replaceNotebookCellOutput(this.uri, this.cellIndex, [outputs]) } } @@ -195,7 +195,7 @@ class RNotebookCellEdit { edit.replaceNotebookCellMetadata(this.uri, this.cellIndex, metadata) } - vscode.workspace.applyEdit(edit) + await vscode.workspace.applyEdit(edit) } } @@ -307,11 +307,17 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } else if (cellType === 'r') { if (lines[line].startsWith('```')) { const cacheCell = outputContent[cells.length] + let cellOutput = undefined + if (cacheCell) { + cellOutput = cacheCell.outputs.map(x => new vscode.NotebookCellOutput(x.outputs, x.id)) + // const data = cacheCell.outputs[0].data + // Object.keys(data).map((x) => new vscode.NotebookCellOutputItem(x, )) + } cells.push({ cellKind: vscode.CellKind.Code, source: lines.slice(cellStartLine + 1, line).join('\n'), language: 'r', - outputs: cacheCell?.outputs || [], + outputs: cellOutput, metadata: { ...cacheCell?.metadata || {}, custom: { @@ -369,98 +375,79 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode await vscode.workspace.fs.writeFile(targetResource, Buffer.from(content)); await vscode.workspace.fs.writeFile(vscode.Uri.parse(targetResource.toString() + ".json"), Buffer.from(JSON.stringify(outputContent))); } - async renderPlotOutput(response: RKernelResponse): Promise { + + async renderPlotOutput(response: RKernelResponse): Promise { const content = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result.plot))).toString(); - return { - outputKind: vscode.CellOutputKind.Rich, - data: { - 'image/svg+xml': content, - }, - }; + return new vscode.NotebookCellOutput( + [new vscode.NotebookCellOutputItem('image/svg+xml', content)] + ) } - async renderTextOutput(response: RKernelResponse): Promise { + async renderTextOutput(response: RKernelResponse): Promise { // Text may contain html, so render as such. - const isXml = response.result.text.match(/^<.+>$/gms) != null + const mimeType = (response.result.text.match(/^<.+>$/gms) != null) ? + 'text/html' : 'text/plain' - if (isXml) { - return { - outputKind: vscode.CellOutputKind.Rich, - data: { - 'text/html': response.result.text - } - } - } else { - return { - outputKind: vscode.CellOutputKind.Rich, - data: { - 'text/plain': response.result.text - } - } - } + return new vscode.NotebookCellOutput( + [new vscode.NotebookCellOutputItem(mimeType, response.result.text)] + ) } - async renderHtmlOutput(response: RKernelResponse): Promise { + async renderHtmlOutput(response: RKernelResponse): Promise { const html = (await vscode.workspace.fs.readFile(vscode.Uri.parse(response.result.file))).toString(); const htmlDir = dirname(response.result.file) const htmlInline = await inlineAll(html, htmlDir) - - return { - outputKind: vscode.CellOutputKind.Rich, - data: { - 'ms-vscode.r-notebook/viewer': htmlInline - }, - } + return new vscode.NotebookCellOutput( + [new vscode.NotebookCellOutputItem('ms-vscode.r-notebook/viewer', htmlInline)] + ) } - async renderTableOutput(response: RKernelResponse): Promise { - return { - outputKind: vscode.CellOutputKind.Rich, - data: { - 'ms-vscode.r-notebook/table': response.result.data + async renderTableOutput(response: RKernelResponse): Promise { + return new vscode.NotebookCellOutput( + [new vscode.NotebookCellOutputItem('ms-vscode.r-notebook/table', response.result.data)] + ) + // TODO: make the html table default, no clue how to do this. // 'text/markdown': response.result.markdown, // 'application/json': response.result.data, - }, - } } - async renderOutput(response: RKernelResponse): Promise { + async renderOutput(response: RKernelResponse): Promise { switch (response.type) { case 'text': { - return [await this.renderTextOutput(response)]; + return await this.renderTextOutput(response); } case 'plot': { - return [await this.renderPlotOutput(response)] + return await this.renderPlotOutput(response) } case 'viewer': { - return [await this.renderHtmlOutput(response)]; + return await this.renderHtmlOutput(response); } case 'browser': { - return [{ - outputKind: vscode.CellOutputKind.Rich, - data: { - 'text/plain': response.result, - }, - }]; + return new vscode.NotebookCellOutput( + [new vscode.NotebookCellOutputItem('text/plain', response.result.url)] + ) } case 'table': { - return [await this.renderTableOutput(response)]; + return await this.renderTableOutput(response); } case 'error': { - return [{ - outputKind: vscode.CellOutputKind.Error, - evalue: response.result.error, - ename: 'Error', - traceback: [], - }]; + return new vscode.NotebookCellOutput( + [new vscode.NotebookCellOutputItem('application/x.notebook.error-traceback', response.result.error)] + ) } } } - async resolveNotebook(): Promise { } + async resolveNotebook(document: vscode.NotebookDocument): Promise { + const cells = document.cells + // new vscode.EventEmitter().fire({ document, cells }) + //vscode.notebook.onDidChangeCellOutputs() + console.log("hello") + + } async saveNotebook(document: vscode.NotebookDocument, cancellation: vscode.CancellationToken): Promise { await this.save(document, document.uri, cancellation); @@ -513,9 +500,9 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode const outputs = await this.renderOutput(response) - const runState = (outputs[0].outputKind === vscode.CellOutputKind.Error) ? vscode.NotebookCellRunState.Error : vscode.NotebookCellRunState.Success + const runState = (outputs.outputs[0].mime === 'application/x.notebook.error-traceback') ? vscode.NotebookCellRunState.Error : vscode.NotebookCellRunState.Success - cellEdit.apply(outputs, { + await cellEdit.apply(outputs, { runStartTime: +new Date(), executionOrder: ++this.runIndex, runState, @@ -524,12 +511,9 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } catch (e) { - cellEdit.apply([{ - outputKind: vscode.CellOutputKind.Error, - evalue: e.toString(), - ename: '', - traceback: [], - }], { + await cellEdit.apply(new vscode.NotebookCellOutput( + [new vscode.NotebookCellOutputItem('application/x.notebook.error-traceback', e.toString())] + ), { runState: vscode.NotebookCellRunState.Error, lastRunDuration: undefined }) diff --git a/src/extension/types/vscode.proposed.d.ts b/src/extension/types/vscode.proposed.d.ts index 373d3a905..9fea737d5 100644 --- a/src/extension/types/vscode.proposed.d.ts +++ b/src/extension/types/vscode.proposed.d.ts @@ -38,19 +38,19 @@ declare module 'vscode' { */ export interface AuthenticationProviderAuthenticationSessionsChangeEvent { /** - * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been added. + * The [AuthenticationSession](#AuthenticationSession)s of the [AuthenticationProvider](#AuthentiationProvider) that have been added. */ - readonly added: ReadonlyArray; + readonly added: ReadonlyArray; /** - * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been removed. + * The [AuthenticationSession](#AuthenticationSession)s of the [AuthenticationProvider](#AuthentiationProvider) that have been removed. */ - readonly removed: ReadonlyArray; + readonly removed: ReadonlyArray; /** - * The ids of the [AuthenticationSession](#AuthenticationSession)s that have been changed. + * The [AuthenticationSession](#AuthenticationSession)s of the [AuthenticationProvider](#AuthentiationProvider) that have been changed. */ - readonly changed: ReadonlyArray; + readonly changed: ReadonlyArray; } /** @@ -63,24 +63,33 @@ declare module 'vscode' { */ readonly onDidChangeSessions: Event; + /** + * Returns an array of current sessions. + * + * TODO @RMacfarlane finish deprecating this and remove it + */ + // eslint-disable-next-line vscode-dts-provider-naming + getAllSessions(): Thenable>; + + /** * Returns an array of current sessions. */ // eslint-disable-next-line vscode-dts-provider-naming - getSessions(): Thenable>; + getSessions(scopes: string[]): Thenable>; /** * Prompts a user to login. */ // eslint-disable-next-line vscode-dts-provider-naming - login(scopes: string[]): Thenable; + createSession(scopes: string[]): Thenable; /** * Removes the session corresponding to session id. * @param sessionId The session id to log out of */ // eslint-disable-next-line vscode-dts-provider-naming - logout(sessionId: string): Thenable; + removeSession(sessionId: string): Thenable; } /** @@ -1008,55 +1017,20 @@ declare module 'vscode' { Idle = 2 } + // TODO@API + // make this a class, allow modified using with-pattern export interface NotebookCellMetadata { /** * Controls whether a cell's editor is editable/readonly. */ editable?: boolean; - /** - * Controls if the cell is executable. - * This metadata is ignored for markdown cell. - */ - runnable?: boolean; - /** * Controls if the cell has a margin to support the breakpoint UI. * This metadata is ignored for markdown cell. */ breakpointMargin?: boolean; - /** - * Whether the [execution order](#NotebookCellMetadata.executionOrder) indicator will be displayed. - * Defaults to true. - */ - hasExecutionOrder?: boolean; - - /** - * The order in which this cell was executed. - */ - executionOrder?: number; - - /** - * A status message to be shown in the cell's status bar - */ - statusMessage?: string; - - /** - * The cell's current run state - */ - runState?: NotebookCellRunState; - - /** - * If the cell is running, the time at which the cell started running - */ - runStartTime?: number; - - /** - * The total duration of the cell's last run - */ - lastRunDuration?: number; - /** * Whether a code cell's editor is collapsed */ @@ -1081,13 +1055,16 @@ declare module 'vscode' { readonly cellKind: CellKind; readonly document: TextDocument; readonly language: string; + readonly outputs: readonly NotebookCellOutput[]; + readonly metadata: NotebookCellMetadata; /** @deprecated use WorkspaceEdit.replaceCellOutput */ - outputs: CellOutput[]; + // outputs: CellOutput[]; // readonly outputs2: NotebookCellOutput[]; /** @deprecated use WorkspaceEdit.replaceCellMetadata */ - metadata: NotebookCellMetadata; + // metadata: NotebookCellMetadata; } + export interface NotebookDocumentMetadata { /** * Controls if users can add or delete cells @@ -1095,30 +1072,11 @@ declare module 'vscode' { */ editable?: boolean; - /** - * Controls whether the full notebook can be run at once. - * Defaults to true - */ - runnable?: boolean; - /** * Default value for [cell editable metadata](#NotebookCellMetadata.editable). * Defaults to true. */ cellEditable?: boolean; - - /** - * Default value for [cell runnable metadata](#NotebookCellMetadata.runnable). - * Defaults to true. - */ - cellRunnable?: boolean; - - /** - * Default value for [cell hasExecutionOrder metadata](#NotebookCellMetadata.hasExecutionOrder). - * Defaults to true. - */ - cellHasExecutionOrder?: boolean; - displayOrder?: GlobPattern[]; /** @@ -1126,21 +1084,11 @@ declare module 'vscode' { */ custom?: { [key: string]: any; }; - /** - * The document's current run state - */ - runState?: NotebookRunState; - /** * Whether the document is trusted, default to true * When false, insecure outputs like HTML, JavaScript, SVG will not be rendered. */ trusted?: boolean; - - /** - * Languages the document supports - */ - languages?: string[]; } export interface NotebookDocumentContentOptions { @@ -1166,10 +1114,11 @@ declare module 'vscode' { readonly isUntitled: boolean; readonly cells: ReadonlyArray; readonly contentOptions: NotebookDocumentContentOptions; - languages: string[]; - metadata: NotebookDocumentMetadata; + readonly metadata: NotebookDocumentMetadata; } + // todo@API maybe have a NotebookCellPosition sibling + // todo@API should be a class export interface NotebookCellRange { readonly start: number; /** @@ -1241,18 +1190,6 @@ declare module 'vscode' { readonly onDidDispose: Event; } - // todo@API stale? - export interface NotebookOutputSelector { - mimeTypes?: string[]; - } - - // todo@API stale? - export interface NotebookRenderRequest { - output: CellDisplayOutput; - mimeType: string; - outputId: string; - } - export interface NotebookDocumentMetadataChangeEvent { readonly document: NotebookDocument; } @@ -1273,17 +1210,6 @@ declare module 'vscode' { readonly changes: ReadonlyArray; } - // todo@API stale? - export interface NotebookCellMoveEvent { - - /** - * The affected document. - */ - readonly document: NotebookDocument; - readonly index: number; - readonly newIndex: number; - } - export interface NotebookCellOutputsChangeEvent { /** @@ -1326,13 +1252,12 @@ declare module 'vscode' { readonly source: string; readonly language: string; // todo@API maybe use a separate data type? - readonly outputs: CellOutput[]; + readonly outputs: NotebookCellOutput[]; readonly metadata: NotebookCellMetadata | undefined; } export interface NotebookData { readonly cells: NotebookCellData[]; - readonly languages: string[]; readonly metadata: NotebookDocumentMetadata; } @@ -1416,86 +1341,29 @@ declare module 'vscode' { //#region https://github.com/microsoft/vscode/issues/106744, NotebookCellOutput - export enum CellOutputKind { - Text = 1, - Error = 2, - Rich = 3 - } - - export interface CellStreamOutput { - outputKind: CellOutputKind.Text; - text: string; - } - - export interface CellErrorOutput { - outputKind: CellOutputKind.Error; - /** - * Exception Name - */ - ename: string; - /** - * Exception Value - */ - evalue: string; - /** - * Exception call stack - */ - traceback: string[]; - } - - export interface NotebookCellOutputMetadata { - /** - * Additional attributes of a cell metadata. - */ - custom?: { [key: string]: any; }; - } - - export interface CellDisplayOutput { - outputKind: CellOutputKind.Rich; - /** - * { mime_type: value } - * - * Example: - * ```json - * { - * "outputKind": vscode.CellOutputKind.Rich, - * "data": { - * "text/html": [ - * "

Hello

" - * ], - * "text/plain": [ - * "" - * ] - * } - * } - */ - data: { [key: string]: any; }; - - readonly metadata?: NotebookCellOutputMetadata; - } - - export type CellOutput = CellStreamOutput | CellErrorOutput | CellDisplayOutput; - + // code specific mime types + // application/x.notebook.error-traceback + // application/x.notebook.stream export class NotebookCellOutputItem { + // todo@API + // add factory functions for common mime types + // static textplain(value:string): NotebookCellOutputItem; + // static errortrace(value:any): NotebookCellOutputItem; + readonly mime: string; readonly value: unknown; - readonly metadata?: Record; + readonly metadata?: Record; - constructor(mime: string, value: unknown, metadata?: Record); + constructor(mime: string, value: unknown, metadata?: Record); } // @jrieken //TODO@API add execution count to cell output? export class NotebookCellOutput { - readonly id: string; readonly outputs: NotebookCellOutputItem[]; - - constructor(outputs: NotebookCellOutputItem[]); - - //TODO@jrieken HACK to workaround dependency issues... - toJSON(): any; + constructor(outputs: NotebookCellOutputItem[], id?: string); } //#endregion @@ -1504,22 +1372,24 @@ declare module 'vscode' { export interface WorkspaceEdit { replaceNotebookMetadata(uri: Uri, value: NotebookDocumentMetadata): void; + + // todo@API use NotebookCellRange replaceNotebookCells(uri: Uri, start: number, end: number, cells: NotebookCellData[], metadata?: WorkspaceEditEntryMetadata): void; replaceNotebookCellMetadata(uri: Uri, index: number, cellMetadata: NotebookCellMetadata, metadata?: WorkspaceEditEntryMetadata): void; - replaceNotebookCellOutput(uri: Uri, index: number, outputs: (NotebookCellOutput | CellOutput)[], metadata?: WorkspaceEditEntryMetadata): void; - appendNotebookCellOutput(uri: Uri, index: number, outputs: (NotebookCellOutput | CellOutput)[], metadata?: WorkspaceEditEntryMetadata): void; + replaceNotebookCellOutput(uri: Uri, index: number, outputs: NotebookCellOutput[], metadata?: WorkspaceEditEntryMetadata): void; + appendNotebookCellOutput(uri: Uri, index: number, outputs: NotebookCellOutput[], metadata?: WorkspaceEditEntryMetadata): void; // TODO@api // https://jupyter-protocol.readthedocs.io/en/latest/messaging.html#update-display-data - // replaceNotebookCellOutput(uri: Uri, index: number, outputId:string, outputs: NotebookCellOutputItem[], metadata?: WorkspaceEditEntryMetadata): void; - // appendNotebookCellOutput(uri: Uri, index: number, outputId:string, outputs: NotebookCellOutputItem[], metadata?: WorkspaceEditEntryMetadata): void; + replaceNotebookCellOutputItems(uri: Uri, index: number, outputId: string, items: NotebookCellOutputItem[], metadata?: WorkspaceEditEntryMetadata): void; + appendNotebookCellOutputItems(uri: Uri, index: number, outputId: string, items: NotebookCellOutputItem[], metadata?: WorkspaceEditEntryMetadata): void; } export interface NotebookEditorEdit { replaceMetadata(value: NotebookDocumentMetadata): void; replaceCells(start: number, end: number, cells: NotebookCellData[]): void; - replaceCellOutput(index: number, outputs: (NotebookCellOutput | CellOutput)[]): void; + replaceCellOutput(index: number, outputs: NotebookCellOutput[]): void; replaceCellMetadata(index: number, metadata: NotebookCellMetadata): void; } @@ -1612,6 +1482,98 @@ declare module 'vscode' { //#region https://github.com/microsoft/vscode/issues/106744, NotebookKernel + export interface NotebookDocumentMetadata { + + /** + * Controls whether the full notebook can be run at once. + * Defaults to true + */ + // todo@API infer from kernel + // todo@API remove + runnable?: boolean; + + /** + * Default value for [cell runnable metadata](#NotebookCellMetadata.runnable). + * Defaults to true. + */ + cellRunnable?: boolean; + + /** + * Default value for [cell hasExecutionOrder metadata](#NotebookCellMetadata.hasExecutionOrder). + * Defaults to true. + */ + cellHasExecutionOrder?: boolean; + + /** + * The document's current run state + */ + runState?: NotebookRunState; + } + + // todo@API use the NotebookCellExecution-object as a container to model and enforce + // the flow of a cell execution + + // kernel -> execute_info + // ext -> createNotebookCellExecution(cell) + // kernel -> done + // exec.dispose(); + + // export interface NotebookCellExecution { + // dispose(): void; + // clearOutput(): void; + // appendOutput(out: NotebookCellOutput): void; + // replaceOutput(out: NotebookCellOutput): void; + // appendOutputItems(output:string, items: NotebookCellOutputItem[]):void; + // replaceOutputItems(output:string, items: NotebookCellOutputItem[]):void; + // } + + // export function createNotebookCellExecution(cell: NotebookCell, startTime?: number): NotebookCellExecution; + // export const onDidStartNotebookCellExecution: Event; + // export const onDidStopNotebookCellExecution: Event; + + export interface NotebookCellMetadata { + + /** + * Controls if the cell is executable. + * This metadata is ignored for markdown cell. + */ + // todo@API infer from kernel + runnable?: boolean; + + /** + * Whether the [execution order](#NotebookCellMetadata.executionOrder) indicator will be displayed. + * Defaults to true. + */ + hasExecutionOrder?: boolean; + + /** + * The order in which this cell was executed. + */ + executionOrder?: number; + + /** + * A status message to be shown in the cell's status bar + */ + // todo@API duplicates status bar API + statusMessage?: string; + + /** + * The cell's current run state + */ + runState?: NotebookCellRunState; + + /** + * If the cell is running, the time at which the cell started running + */ + runStartTime?: number; + + /** + * The total duration of the cell's last run + */ + // todo@API depends on having output + lastRunDuration?: number; + } + export interface NotebookKernel { readonly id?: string; label: string; @@ -1619,6 +1581,15 @@ declare module 'vscode' { detail?: string; isPreferred?: boolean; preloads?: Uri[]; + + // TODO@API control runnable state of cell + /** + * languages supported by kernel + * - first is preferred + * - `undefined` means all languages available in the editor + */ + supportedLanguages?: string[]; + // @roblourens // todo@API change to `executeCells(document: NotebookDocument, cells: NotebookCellRange[], context:{isWholeNotebooke: boolean}, token: CancelationToken): void;` // todo@API interrupt vs cancellation, https://github.com/microsoft/vscode/issues/106741 From 2621bc837917e268f698c6677a4f015c7c03e5e0 Mon Sep 17 00:00:00 2001 From: Mark Baas Date: Mon, 15 Feb 2021 13:01:56 +0100 Subject: [PATCH 78/78] update to latest proposed api. --- src/extension/notebook.ts | 15 ++++++------ src/extension/types/vscode.proposed.d.ts | 30 ++++++++++++------------ 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/extension/notebook.ts b/src/extension/notebook.ts index 6a941877f..41d69a36f 100644 --- a/src/extension/notebook.ts +++ b/src/extension/notebook.ts @@ -263,7 +263,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } else if (lines[line].startsWith('```{r')) { if (line > cellStartLine) { cells.push({ - cellKind: vscode.CellKind.Markdown, + cellKind: vscode.NotebookCellKind.Markdown, source: lines.slice(cellStartLine, line).join('\n'), language: 'markdown', outputs: [], @@ -278,7 +278,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } else if (line === lines.length - 1) { if (line > cellStartLine) { cells.push({ - cellKind: vscode.CellKind.Markdown, + cellKind: vscode.NotebookCellKind.Markdown, source: lines.slice(cellStartLine, line).join('\n'), language: 'markdown', outputs: [], @@ -292,7 +292,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } else if (cellType === 'yaml') { if (lines[line].startsWith('---')) { cells.push({ - cellKind: vscode.CellKind.Code, + cellKind: vscode.NotebookCellKind.Code, source: lines.slice(cellStartLine, line + 1).join('\n'), language: 'yaml', outputs: [], @@ -314,7 +314,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode // Object.keys(data).map((x) => new vscode.NotebookCellOutputItem(x, )) } cells.push({ - cellKind: vscode.CellKind.Code, + cellKind: vscode.NotebookCellKind.Code, source: lines.slice(cellStartLine + 1, line).join('\n'), language: 'r', outputs: cellOutput, @@ -334,7 +334,6 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } return { - languages: ['r'], metadata: {}, cells: cells, }; @@ -348,9 +347,9 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode if (cancellation.isCancellationRequested) { return; } - if (cell.cellKind === vscode.CellKind.Markdown) { + if (cell.cellKind === vscode.NotebookCellKind.Markdown) { content += cell.document.getText() + '\n'; - } else if (cell.cellKind === vscode.CellKind.Code) { + } else if (cell.cellKind === vscode.NotebookCellKind.Code) { if (cell.language === 'r') { if (cell.metadata.custom === undefined) { cell.metadata.custom = { @@ -474,7 +473,7 @@ export class RNotebookProvider implements vscode.NotebookContentProvider, vscode } for (const cell of document.cells) { - if (cell.cellKind === vscode.CellKind.Code && cell.metadata.runnable) { + if (cell.cellKind === vscode.NotebookCellKind.Code && cell.metadata.runnable) { await this.executeCell(document, cell); } } diff --git a/src/extension/types/vscode.proposed.d.ts b/src/extension/types/vscode.proposed.d.ts index 9fea737d5..0122b4e2b 100644 --- a/src/extension/types/vscode.proposed.d.ts +++ b/src/extension/types/vscode.proposed.d.ts @@ -64,29 +64,25 @@ declare module 'vscode' { readonly onDidChangeSessions: Event; /** - * Returns an array of current sessions. - * - * TODO @RMacfarlane finish deprecating this and remove it - */ - // eslint-disable-next-line vscode-dts-provider-naming - getAllSessions(): Thenable>; - - - /** - * Returns an array of current sessions. + * Get a list of sessions. + * @param scopes An optional list of scopes. If provided, the sessions returned should match + * these permissions, otherwise all sessions should be returned. + * @returns A promise that resolves to an array of authentication sessions. */ // eslint-disable-next-line vscode-dts-provider-naming - getSessions(scopes: string[]): Thenable>; + getSessions(scopes?: string[]): Thenable>; /** * Prompts a user to login. + * @param scopes A list of scopes, permissions, that the new session should be created with. + * @returns A promise that resolves to an authentication session. */ // eslint-disable-next-line vscode-dts-provider-naming createSession(scopes: string[]): Thenable; /** * Removes the session corresponding to session id. - * @param sessionId The session id to log out of + * @param sessionId The id of the session to remove. */ // eslint-disable-next-line vscode-dts-provider-naming removeSession(sessionId: string): Thenable; @@ -1000,7 +996,7 @@ declare module 'vscode' { //#region https://github.com/microsoft/vscode/issues/106744, Notebooks (misc) - export enum CellKind { + export enum NotebookCellKind { Markdown = 1, Code = 2 } @@ -1052,7 +1048,7 @@ declare module 'vscode' { readonly index: number; readonly notebook: NotebookDocument; readonly uri: Uri; - readonly cellKind: CellKind; + readonly cellKind: NotebookCellKind; readonly document: TextDocument; readonly language: string; readonly outputs: readonly NotebookCellOutput[]; @@ -1109,6 +1105,7 @@ declare module 'vscode' { readonly uri: Uri; readonly version: number; readonly fileName: string; + // todo@API should we really expose this? readonly viewType: string; readonly isDirty: boolean; readonly isUntitled: boolean; @@ -1248,7 +1245,7 @@ declare module 'vscode' { // todo@API support ids https://github.com/jupyter/enhancement-proposals/blob/master/62-cell-id/cell-id.md export interface NotebookCellData { - readonly cellKind: CellKind; + readonly cellKind: NotebookCellKind; readonly source: string; readonly language: string; // todo@API maybe use a separate data type? @@ -1309,6 +1306,8 @@ declare module 'vscode' { export namespace notebook { + // todo@API should we really support to pass the viewType? We do NOT support + // to open the same file with different viewTypes at the same time export function openNotebookDocument(uri: Uri, viewType?: string): Thenable; export const onDidOpenNotebookDocument: Event; export const onDidCloseNotebookDocument: Event; @@ -1334,6 +1333,7 @@ declare module 'vscode' { export const onDidChangeActiveNotebookEditor: Event; export const onDidChangeNotebookEditorSelection: Event; export const onDidChangeNotebookEditorVisibleRanges: Event; + // TODO@API add overload for just a URI export function showNotebookDocument(document: NotebookDocument, options?: NotebookDocumentShowOptions): Thenable; }