mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 04:49:35 +00:00
Merge remote-tracking branch 'origin/main' into alex/update-playwright
This commit is contained in:
commit
a573bc0b8d
|
@ -104,6 +104,7 @@
|
|||
"restrictions": [
|
||||
"assert",
|
||||
"sinon",
|
||||
"sinon-test",
|
||||
"vs/nls",
|
||||
"**/vs/base/common/**",
|
||||
"**/vs/base/test/common/**"
|
||||
|
@ -139,6 +140,7 @@
|
|||
"restrictions": [
|
||||
"assert",
|
||||
"sinon",
|
||||
"sinon-test",
|
||||
"vs/nls",
|
||||
"**/vs/base/{common,browser}/**",
|
||||
"**/vs/base/test/{common,browser}/**"
|
||||
|
@ -212,6 +214,7 @@
|
|||
"restrictions": [
|
||||
"assert",
|
||||
"sinon",
|
||||
"sinon-test",
|
||||
"vs/nls",
|
||||
"**/vs/base/common/**",
|
||||
"**/vs/base/parts/*/common/**",
|
||||
|
@ -225,6 +228,7 @@
|
|||
"restrictions": [
|
||||
"assert",
|
||||
"sinon",
|
||||
"sinon-test",
|
||||
"vs/nls",
|
||||
"**/vs/base/{common,browser}/**",
|
||||
"**/vs/base/parts/*/{common,browser}/**",
|
||||
|
@ -289,6 +293,7 @@
|
|||
"restrictions": [
|
||||
"assert",
|
||||
"sinon",
|
||||
"sinon-test",
|
||||
"vs/nls",
|
||||
"**/vs/base/{common,browser}/**",
|
||||
"**/vs/base/parts/*/{common,browser}/**",
|
||||
|
@ -311,6 +316,7 @@
|
|||
"restrictions": [
|
||||
"assert",
|
||||
"sinon",
|
||||
"sinon-test",
|
||||
"vs/nls",
|
||||
"**/vs/base/common/**",
|
||||
"**/vs/platform/*/common/**",
|
||||
|
@ -334,6 +340,7 @@
|
|||
"restrictions": [
|
||||
"assert",
|
||||
"sinon",
|
||||
"sinon-test",
|
||||
"vs/nls",
|
||||
"**/vs/base/{common,browser}/**",
|
||||
"**/vs/platform/*/{common,browser}/**",
|
||||
|
@ -357,6 +364,7 @@
|
|||
"restrictions": [
|
||||
"assert",
|
||||
"sinon",
|
||||
"sinon-test",
|
||||
"vs/nls",
|
||||
"**/vs/base/common/**",
|
||||
"**/vs/platform/*/common/**",
|
||||
|
@ -383,6 +391,7 @@
|
|||
"restrictions": [
|
||||
"assert",
|
||||
"sinon",
|
||||
"sinon-test",
|
||||
"vs/nls",
|
||||
"**/vs/base/{common,browser}/**",
|
||||
"**/vs/platform/*/{common,browser}/**",
|
||||
|
@ -397,6 +406,7 @@
|
|||
"restrictions": [
|
||||
"assert",
|
||||
"sinon",
|
||||
"sinon-test",
|
||||
"vs/nls",
|
||||
"**/vs/base/{common,browser}/**",
|
||||
"**/vs/base/test/{common,browser}/**",
|
||||
|
@ -921,6 +931,7 @@
|
|||
"**/vs/**",
|
||||
"assert",
|
||||
"sinon",
|
||||
"sinon-test",
|
||||
"crypto",
|
||||
"vscode"
|
||||
]
|
||||
|
@ -952,6 +963,7 @@
|
|||
"**/vs/**",
|
||||
"assert",
|
||||
"sinon",
|
||||
"sinon-test",
|
||||
"crypto",
|
||||
"xterm*"
|
||||
]
|
||||
|
@ -962,6 +974,7 @@
|
|||
"**/vs/**",
|
||||
"assert",
|
||||
"sinon",
|
||||
"sinon-test",
|
||||
"crypto",
|
||||
"xterm*"
|
||||
]
|
||||
|
@ -989,6 +1002,7 @@
|
|||
"vscode-dts-cancellation": "warn",
|
||||
"vscode-dts-use-thenable": "warn",
|
||||
"vscode-dts-region-comments": "warn",
|
||||
"vscode-dts-vscode-in-comments": "warn",
|
||||
"vscode-dts-provider-naming": [
|
||||
"warn",
|
||||
{
|
||||
|
|
4
.github/workflows/english-please.yml
vendored
4
.github/workflows/english-please.yml
vendored
|
@ -7,19 +7,17 @@ on:
|
|||
jobs:
|
||||
main:
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(github.event.issue.labels.*.name, '*english-please')
|
||||
steps:
|
||||
- name: Checkout Actions
|
||||
if: contains(github.event.issue.labels.*.name, '*english-please')
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: "microsoft/vscode-github-triage-actions"
|
||||
ref: stable
|
||||
path: ./actions
|
||||
- name: Install Actions
|
||||
if: contains(github.event.issue.labels.*.name, '*english-please')
|
||||
run: npm install --production --prefix ./actions
|
||||
- name: Run English Please
|
||||
if: contains(github.event.issue.labels.*.name, '*english-please')
|
||||
uses: ./actions/english-please
|
||||
with:
|
||||
appInsightsKey: ${{secrets.TRIAGE_ACTIONS_APP_INSIGHTS}}
|
||||
|
|
2
.github/workflows/rich-navigation.yml
vendored
2
.github/workflows/rich-navigation.yml
vendored
|
@ -33,5 +33,5 @@ jobs:
|
|||
with:
|
||||
languages: typescript
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
typescriptVersion: 0.6.0-next.8
|
||||
typescriptVersion: 0.6.0-dev.1
|
||||
continue-on-error: true
|
||||
|
|
|
@ -51,7 +51,7 @@ module.exports.indentationFilter = [
|
|||
'!test/monaco/out/**',
|
||||
'!test/smoke/out/**',
|
||||
'!extensions/typescript-language-features/test-workspace/**',
|
||||
'!extensions/notebook-markdown-extensions/notebook-out/**',
|
||||
'!extensions/markdown-math/notebook-out/**',
|
||||
'!extensions/vscode-api-tests/testWorkspace/**',
|
||||
'!extensions/vscode-api-tests/testWorkspace2/**',
|
||||
'!extensions/vscode-custom-editor-tests/test-workspace/**',
|
||||
|
@ -89,7 +89,7 @@ module.exports.indentationFilter = [
|
|||
'!**/*.dockerfile',
|
||||
'!extensions/markdown-language-features/media/*.js',
|
||||
'!extensions/markdown-language-features/notebook-out/*.js',
|
||||
'!extensions/notebook-markdown-extensions/notebook-out/*.js',
|
||||
'!extensions/markdown-math/notebook-out/*.js',
|
||||
'!extensions/simple-browser/media/*.js',
|
||||
];
|
||||
|
||||
|
@ -119,7 +119,7 @@ module.exports.copyrightFilter = [
|
|||
'!resources/completions/**',
|
||||
'!extensions/configuration-editing/build/inline-allOf.ts',
|
||||
'!extensions/markdown-language-features/media/highlight.css',
|
||||
'!extensions/notebook-markdown-extensions/notebook-out/**',
|
||||
'!extensions/markdown-math/notebook-out/**',
|
||||
'!extensions/html-language-features/server/src/modes/typescript/*',
|
||||
'!extensions/*/server/bin/*',
|
||||
'!src/vs/editor/test/node/classification/typescript-test.ts',
|
||||
|
|
|
@ -50,6 +50,7 @@ const compilations = [
|
|||
'json-language-features/server/tsconfig.json',
|
||||
'markdown-language-features/preview-src/tsconfig.json',
|
||||
'markdown-language-features/tsconfig.json',
|
||||
'markdown-math/tsconfig.json',
|
||||
'merge-conflict/tsconfig.json',
|
||||
'microsoft-authentication/tsconfig.json',
|
||||
'npm/tsconfig.json',
|
||||
|
|
45
build/lib/eslint/vscode-dts-vscode-in-comments.js
Normal file
45
build/lib/eslint/vscode-dts-vscode-in-comments.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
module.exports = new class ApiVsCodeInComments {
|
||||
constructor() {
|
||||
this.meta = {
|
||||
messages: {
|
||||
comment: `Don't use the term 'vs code' in comments`
|
||||
}
|
||||
};
|
||||
}
|
||||
create(context) {
|
||||
const sourceCode = context.getSourceCode();
|
||||
return {
|
||||
['Program']: (_node) => {
|
||||
for (const comment of sourceCode.getAllComments()) {
|
||||
if (comment.type !== 'Block') {
|
||||
continue;
|
||||
}
|
||||
if (!comment.range) {
|
||||
continue;
|
||||
}
|
||||
const startIndex = comment.range[0] + '/*'.length;
|
||||
const re = /vs code/ig;
|
||||
let match;
|
||||
while ((match = re.exec(comment.value))) {
|
||||
// Allow using 'VS Code' in quotes
|
||||
if (comment.value[match.index - 1] === `'` && comment.value[match.index + match[0].length] === `'`) {
|
||||
continue;
|
||||
}
|
||||
// Types for eslint seem incorrect
|
||||
const start = sourceCode.getLocFromIndex(startIndex + match.index);
|
||||
const end = sourceCode.getLocFromIndex(startIndex + match.index + match[0].length);
|
||||
context.report({
|
||||
messageId: 'comment',
|
||||
loc: { start, end }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
53
build/lib/eslint/vscode-dts-vscode-in-comments.ts
Normal file
53
build/lib/eslint/vscode-dts-vscode-in-comments.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as eslint from 'eslint';
|
||||
import type * as estree from 'estree';
|
||||
|
||||
export = new class ApiVsCodeInComments implements eslint.Rule.RuleModule {
|
||||
|
||||
readonly meta: eslint.Rule.RuleMetaData = {
|
||||
messages: {
|
||||
comment: `Don't use the term 'vs code' in comments`
|
||||
}
|
||||
};
|
||||
|
||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||
|
||||
const sourceCode = context.getSourceCode();
|
||||
|
||||
return {
|
||||
['Program']: (_node: any) => {
|
||||
|
||||
for (const comment of sourceCode.getAllComments()) {
|
||||
if (comment.type !== 'Block') {
|
||||
continue;
|
||||
}
|
||||
if (!comment.range) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const startIndex = comment.range[0] + '/*'.length;
|
||||
const re = /vs code/ig;
|
||||
let match: RegExpExecArray | null;
|
||||
while ((match = re.exec(comment.value))) {
|
||||
// Allow using 'VS Code' in quotes
|
||||
if (comment.value[match.index - 1] === `'` && comment.value[match.index + match[0].length] === `'`) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Types for eslint seem incorrect
|
||||
const start = sourceCode.getLocFromIndex(startIndex + match.index) as any as estree.Position;
|
||||
const end = sourceCode.getLocFromIndex(startIndex + match.index + match[0].length) as any as estree.Position;
|
||||
context.report({
|
||||
messageId: 'comment',
|
||||
loc: { start, end }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
|
@ -338,7 +338,7 @@ const webpackMediaConfigFiles = [
|
|||
// Additional projects to run esbuild on. These typically build code for webviews
|
||||
const esbuildMediaScripts = [
|
||||
'markdown-language-features/esbuild.js',
|
||||
'notebook-markdown-extensions/esbuild.js',
|
||||
'markdown-math/esbuild.js',
|
||||
];
|
||||
async function webpackExtensions(taskName, isWatch, webpackConfigLocations) {
|
||||
const webpack = require('webpack');
|
||||
|
|
|
@ -417,7 +417,7 @@ const webpackMediaConfigFiles = [
|
|||
// Additional projects to run esbuild on. These typically build code for webviews
|
||||
const esbuildMediaScripts = [
|
||||
'markdown-language-features/esbuild.js',
|
||||
'notebook-markdown-extensions/esbuild.js',
|
||||
'markdown-math/esbuild.js',
|
||||
];
|
||||
|
||||
export async function webpackExtensions(taskName: string, isWatch: boolean, webpackConfigLocations: { configPath: string, outputRoot?: string }[]) {
|
||||
|
|
|
@ -148,9 +148,9 @@ fsevents@~2.3.1:
|
|||
integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==
|
||||
|
||||
glob-parent@^5.1.1, glob-parent@~5.1.0:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
|
||||
integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
|
|
|
@ -28,9 +28,9 @@ exports.dirs = [
|
|||
'extensions/json-language-features',
|
||||
'extensions/json-language-features/server',
|
||||
'extensions/markdown-language-features',
|
||||
'extensions/markdown-math',
|
||||
'extensions/merge-conflict',
|
||||
'extensions/microsoft-authentication',
|
||||
'extensions/notebook-markdown-extensions',
|
||||
'extensions/npm',
|
||||
'extensions/php-language-features',
|
||||
'extensions/search-result',
|
||||
|
|
|
@ -25,7 +25,7 @@ function update(options) {
|
|||
throw new Error(`${location} doesn't exist.`);
|
||||
}
|
||||
let locExtFolder = idOrPath;
|
||||
if (/^\w{2}(-\w+)?$/.test(idOrPath)) {
|
||||
if (/^\w{2,3}(-\w+)?$/.test(idOrPath)) {
|
||||
locExtFolder = path.join('..', 'vscode-loc', 'i18n', `vscode-language-pack-${idOrPath}`);
|
||||
}
|
||||
let locExtStat = fs.statSync(locExtFolder);
|
||||
|
@ -88,7 +88,7 @@ function update(options) {
|
|||
for (let tp of translationPaths) {
|
||||
localization.translations.push({ id: tp.id, path: `./translations/${tp.resourceName}` });
|
||||
}
|
||||
fs.writeFileSync(path.join(locExtFolder, 'package.json'), JSON.stringify(packageJSON, null, '\t'));
|
||||
fs.writeFileSync(path.join(locExtFolder, 'package.json'), JSON.stringify(packageJSON, null, '\t') + '\n');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1488,9 +1488,9 @@ node-fetch@^2.6.0:
|
|||
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
|
||||
|
||||
normalize-url@^4.1.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
|
||||
integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
|
||||
version "4.5.1"
|
||||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a"
|
||||
integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==
|
||||
|
||||
nth-check@~1.0.1:
|
||||
version "1.0.2"
|
||||
|
|
|
@ -10,14 +10,164 @@ export function activate() {
|
|||
html: true
|
||||
});
|
||||
|
||||
const style = document.createElement('style');
|
||||
style.classList.add('markdown-style');
|
||||
style.textContent = `
|
||||
.emptyMarkdownCell::before {
|
||||
content: "${document.documentElement.style.getPropertyValue('--notebook-cell-markup-empty-content')}";
|
||||
font-style: italic;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:focus,
|
||||
input:focus,
|
||||
select:focus,
|
||||
textarea:focus {
|
||||
outline: 1px solid -webkit-focus-ring-color;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
height: 2px;
|
||||
border-bottom: 2px solid;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 26px;
|
||||
line-height: 31px;
|
||||
margin: 0;
|
||||
margin-bottom: 13px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 19px;
|
||||
margin: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Adjust margin of first item in markdown cell */
|
||||
*:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
/* h1 tags don't need top margin */
|
||||
h1:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Removes bottom margin when only one item exists in markdown cell */
|
||||
*:only-child,
|
||||
*:last-child {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
/* makes all markdown cells consistent */
|
||||
div {
|
||||
min-height: var(--notebook-markdown-min-height);
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
table th,
|
||||
table td {
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
table > thead > tr > th {
|
||||
text-align: left;
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
|
||||
table > thead > tr > th,
|
||||
table > thead > tr > td,
|
||||
table > tbody > tr > th,
|
||||
table > tbody > tr > td {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
table > tbody > tr + tr > td {
|
||||
border-top: 1px solid;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 7px 0 5px;
|
||||
padding: 0 16px 0 10px;
|
||||
border-left-width: 5px;
|
||||
border-left-style: solid;
|
||||
}
|
||||
|
||||
code,
|
||||
.code {
|
||||
font-size: 1em;
|
||||
line-height: 1.357em;
|
||||
}
|
||||
|
||||
.code {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
`;
|
||||
document.head.append(style);
|
||||
|
||||
return {
|
||||
renderOutputItem: (outputInfo: { text(): string }, element: HTMLElement) => {
|
||||
const rendered = markdownIt.render(outputInfo.text());
|
||||
element.innerHTML = rendered;
|
||||
let previewNode: HTMLElement;
|
||||
if (!element.shadowRoot) {
|
||||
const previewRoot = element.attachShadow({ mode: 'open' });
|
||||
|
||||
// Insert styles into markdown preview shadow dom so that they are applied
|
||||
for (const markdownStyleNode of document.getElementsByClassName('markdown-style')) {
|
||||
element.insertAdjacentElement('beforebegin', markdownStyleNode.cloneNode(true) as Element);
|
||||
// Insert styles into markdown preview shadow dom so that they are applied.
|
||||
// First add default webview style
|
||||
const defaultStyles = document.getElementById('_defaultStyles') as HTMLStyleElement;
|
||||
previewRoot.appendChild(defaultStyles.cloneNode(true));
|
||||
|
||||
// And then contributed styles
|
||||
for (const markdownStyleNode of document.getElementsByClassName('markdown-style')) {
|
||||
previewRoot.appendChild(markdownStyleNode.cloneNode(true));
|
||||
}
|
||||
|
||||
previewNode = document.createElement('div');
|
||||
previewNode.id = 'preview';
|
||||
previewRoot.appendChild(previewNode);
|
||||
} else {
|
||||
previewNode = element.shadowRoot.getElementById('preview')!;
|
||||
}
|
||||
|
||||
const text = outputInfo.text();
|
||||
if (text.trim().length === 0) {
|
||||
previewNode.innerText = '';
|
||||
previewNode.classList.add('emptyMarkdownCell');
|
||||
} else {
|
||||
previewNode.classList.remove('emptyMarkdownCell');
|
||||
|
||||
const rendered = markdownIt.render(text);
|
||||
previewNode.innerHTML = rendered;
|
||||
}
|
||||
},
|
||||
extendMarkdownIt: (f: (md: typeof markdownIt) => void) => {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"onCommand:markdown.showSource",
|
||||
"onCommand:markdown.showPreviewSecuritySelector",
|
||||
"onCommand:markdown.api.render",
|
||||
"onCommand:markdown.api.reloadPlugins",
|
||||
"onWebviewPanel:markdown.preview",
|
||||
"onCustomEditor:vscode.markdown.preview.editor"
|
||||
],
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export { OpenDocumentLinkCommand } from './openDocumentLink';
|
||||
export { ShowPreviewCommand, ShowPreviewToSideCommand, ShowLockedPreviewToSideCommand } from './showPreview';
|
||||
export { ShowSourceCommand } from './showSource';
|
||||
export { RefreshPreviewCommand } from './refreshPreview';
|
||||
export { ShowPreviewSecuritySelectorCommand } from './showPreviewSecuritySelector';
|
||||
export { MoveCursorToPositionCommand } from './moveCursorToPosition';
|
||||
export { ToggleLockCommand } from './toggleLock';
|
||||
export { OpenDocumentLinkCommand } from './openDocumentLink';
|
||||
export { RefreshPreviewCommand } from './refreshPreview';
|
||||
export { ReloadPlugins } from './reloadPlugins';
|
||||
export { RenderDocument } from './renderDocument';
|
||||
export { ShowLockedPreviewToSideCommand, ShowPreviewCommand, ShowPreviewToSideCommand } from './showPreview';
|
||||
export { ShowPreviewSecuritySelectorCommand } from './showPreviewSecuritySelector';
|
||||
export { ShowSourceCommand } from './showSource';
|
||||
export { ToggleLockCommand } from './toggleLock';
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Command } from '../commandManager';
|
||||
import { MarkdownPreviewManager } from '../features/previewManager';
|
||||
import { MarkdownEngine } from '../markdownEngine';
|
||||
|
||||
export class ReloadPlugins implements Command {
|
||||
public readonly id = 'markdown.api.reloadPlugins';
|
||||
|
||||
public constructor(
|
||||
private readonly webviewManager: MarkdownPreviewManager,
|
||||
private readonly engine: MarkdownEngine,
|
||||
) { }
|
||||
|
||||
public execute(): void {
|
||||
this.engine.reloadPlugins();
|
||||
this.engine.cleanCache();
|
||||
this.webviewManager.refresh();
|
||||
}
|
||||
}
|
|
@ -80,6 +80,7 @@ function registerMarkdownCommands(
|
|||
commandManager.register(new commands.OpenDocumentLinkCommand(engine));
|
||||
commandManager.register(new commands.ToggleLockCommand(previewManager));
|
||||
commandManager.register(new commands.RenderDocument(engine));
|
||||
commandManager.register(new commands.ReloadPlugins(previewManager, engine));
|
||||
return commandManager;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ interface RenderEnv {
|
|||
}
|
||||
|
||||
export class MarkdownEngine {
|
||||
|
||||
private md?: Promise<MarkdownIt>;
|
||||
|
||||
private _slugCount = new Map<string, number>();
|
||||
|
@ -129,6 +130,10 @@ export class MarkdownEngine {
|
|||
return md;
|
||||
}
|
||||
|
||||
public reloadPlugins() {
|
||||
this.md = undefined;
|
||||
}
|
||||
|
||||
private tokenizeDocument(
|
||||
document: SkinnyTextDocument,
|
||||
config: MarkdownItConfig,
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# Markdown Notebook Math support
|
||||
# Markdown Math support
|
||||
|
||||
**Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled.
|
17
extensions/markdown-math/extension-browser.webpack.config.js
Normal file
17
extensions/markdown-math/extension-browser.webpack.config.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
//@ts-check
|
||||
|
||||
'use strict';
|
||||
|
||||
const withBrowserDefaults = require('../shared.webpack.config').browser;
|
||||
|
||||
module.exports = withBrowserDefaults({
|
||||
context: __dirname,
|
||||
entry: {
|
||||
extension: './src/extension.ts'
|
||||
}
|
||||
});
|
20
extensions/markdown-math/extension.webpack.config.js
Normal file
20
extensions/markdown-math/extension.webpack.config.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
//@ts-check
|
||||
|
||||
'use strict';
|
||||
|
||||
const withDefaults = require('../shared.webpack.config');
|
||||
|
||||
module.exports = withDefaults({
|
||||
context: __dirname,
|
||||
resolve: {
|
||||
mainFields: ['module', 'main']
|
||||
},
|
||||
entry: {
|
||||
extension: './src/extension.ts',
|
||||
}
|
||||
});
|
Before Width: | Height: | Size: 903 B After Width: | Height: | Size: 903 B |
|
@ -1,11 +1,10 @@
|
|||
{
|
||||
"name": "notebook-markdown-extensions",
|
||||
"name": "markdown-math",
|
||||
"displayName": "%displayName%",
|
||||
"description": "%description%",
|
||||
"version": "1.0.0",
|
||||
"icon": "icon.png",
|
||||
"publisher": "vscode",
|
||||
"enableProposedApi": true,
|
||||
"license": "MIT",
|
||||
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
|
||||
"engines": {
|
||||
|
@ -20,16 +19,36 @@
|
|||
"supported": true
|
||||
}
|
||||
},
|
||||
"main": "./out/extension",
|
||||
"browser": "./dist/browser/extension",
|
||||
"activationEvents": [],
|
||||
"contributes": {
|
||||
"notebookRenderer": [
|
||||
{
|
||||
"id": "markdownItRenderer-katex",
|
||||
"displayName": "Markdown it katex renderer",
|
||||
"displayName": "Markdown it KaTeX renderer",
|
||||
"entrypoint": {
|
||||
"extends": "markdownItRenderer",
|
||||
"path": "./notebook-out/katex.js"
|
||||
}
|
||||
}
|
||||
],
|
||||
"markdown.markdownItPlugins": true,
|
||||
"markdown.previewStyles": [
|
||||
"./node_modules/katex/dist/katex.min.css",
|
||||
"./preview-styles/index.css"
|
||||
],
|
||||
"configuration": [
|
||||
{
|
||||
"title": "Markdown",
|
||||
"properties": {
|
||||
"markdown.math.enabled": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "%config.markdown.math.enabled%"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -37,10 +56,11 @@
|
|||
"watch": "npm run build-notebook",
|
||||
"build-notebook": "node ./esbuild"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iktakahiro/markdown-it-katex": "https://github.com/mjbvz/markdown-it-katex.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iktakahiro/markdown-it-katex": "https://github.com/mjbvz/markdown-it-katex.git",
|
||||
"@types/markdown-it": "^0.0.0",
|
||||
"markdown-it": "^12.0.4"
|
||||
"@types/markdown-it": "^0.0.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
5
extensions/markdown-math/package.nls.json
Normal file
5
extensions/markdown-math/package.nls.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"displayName": "Markdown Math",
|
||||
"description": "Adds math support to markdown in notebooks.",
|
||||
"config.markdown.math.enabled": "Enable/disable rendering math in the built-in markdown preview."
|
||||
}
|
8
extensions/markdown-math/preview-styles/index.css
Normal file
8
extensions/markdown-math/preview-styles/index.css
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.katex-error {
|
||||
color: var(--vscode-editorError-foreground);
|
||||
}
|
31
extensions/markdown-math/src/extension.ts
Normal file
31
extensions/markdown-math/src/extension.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
const enabledSetting = 'markdown.math.enabled';
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
function isEnabled(): boolean {
|
||||
const config = vscode.workspace.getConfiguration('markdown');
|
||||
console.log(config.get<boolean>('math.enabled', true));
|
||||
return config.get<boolean>('math.enabled', true);
|
||||
}
|
||||
|
||||
vscode.workspace.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(enabledSetting)) {
|
||||
vscode.commands.executeCommand('markdown.api.reloadPlugins');
|
||||
}
|
||||
}, undefined, context.subscriptions);
|
||||
|
||||
return {
|
||||
extendMarkdownIt(md: any) {
|
||||
if (isEnabled()) {
|
||||
const katex = require('@iktakahiro/markdown-it-katex');
|
||||
return md.use(katex);
|
||||
}
|
||||
return md;
|
||||
}
|
||||
};
|
||||
}
|
1
extensions/markdown-math/src/types.d.ts
vendored
Normal file
1
extensions/markdown-math/src/types.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/// <reference path='../../../src/vs/vscode.d.ts'/>
|
17
extensions/markdown-math/tsconfig.json
Normal file
17
extensions/markdown-math/tsconfig.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out",
|
||||
"experimentalDecorators": true,
|
||||
"lib": [
|
||||
"es6",
|
||||
"es2015.promise",
|
||||
"es2019.array",
|
||||
"es2020.string",
|
||||
"dom"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
]
|
||||
}
|
26
extensions/markdown-math/yarn.lock
Normal file
26
extensions/markdown-math/yarn.lock
Normal file
|
@ -0,0 +1,26 @@
|
|||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@iktakahiro/markdown-it-katex@https://github.com/mjbvz/markdown-it-katex.git":
|
||||
version "4.0.1"
|
||||
resolved "https://github.com/mjbvz/markdown-it-katex.git#2bf0b89c6c22ef0b585f55ccab66d1f7c5356bea"
|
||||
dependencies:
|
||||
katex "^0.13.0"
|
||||
|
||||
"@types/markdown-it@^0.0.0":
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.0.tgz#8f6acaa5e3245e275f684e95deb3e518d1c6ab16"
|
||||
integrity sha1-j2rKpeMkXidfaE6V3rPlGNHGqxY=
|
||||
|
||||
commander@^6.0.0:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
|
||||
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
|
||||
|
||||
katex@^0.13.0:
|
||||
version "0.13.0"
|
||||
resolved "https://registry.yarnpkg.com/katex/-/katex-0.13.0.tgz#62900e56c1ad8fdf7da23399e50d7a7b690b39ab"
|
||||
integrity sha512-6cHbzbegYgS9vvVGuH8UA+o97X+ZshtboSqJJCdq7trBYzuD75JNwr7Ef606xkUjecPPhFnyB+afx1dVafielg==
|
||||
dependencies:
|
||||
commander "^6.0.0"
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"displayName": "Markdown Notebook math",
|
||||
"description": "Provides rich language support for Markdown."
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@iktakahiro/markdown-it-katex@https://github.com/mjbvz/markdown-it-katex.git":
|
||||
version "4.0.1"
|
||||
resolved "https://github.com/mjbvz/markdown-it-katex.git#2bf0b89c6c22ef0b585f55ccab66d1f7c5356bea"
|
||||
dependencies:
|
||||
katex "^0.13.0"
|
||||
|
||||
"@types/markdown-it@^0.0.0":
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.0.tgz#8f6acaa5e3245e275f684e95deb3e518d1c6ab16"
|
||||
integrity sha1-j2rKpeMkXidfaE6V3rPlGNHGqxY=
|
||||
|
||||
argparse@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||
|
||||
commander@^6.0.0:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
|
||||
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
|
||||
|
||||
entities@~2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
|
||||
integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
|
||||
|
||||
katex@^0.13.0:
|
||||
version "0.13.0"
|
||||
resolved "https://registry.yarnpkg.com/katex/-/katex-0.13.0.tgz#62900e56c1ad8fdf7da23399e50d7a7b690b39ab"
|
||||
integrity sha512-6cHbzbegYgS9vvVGuH8UA+o97X+ZshtboSqJJCdq7trBYzuD75JNwr7Ef606xkUjecPPhFnyB+afx1dVafielg==
|
||||
dependencies:
|
||||
commander "^6.0.0"
|
||||
|
||||
linkify-it@^3.0.1:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.2.tgz#f55eeb8bc1d3ae754049e124ab3bb56d97797fb8"
|
||||
integrity sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==
|
||||
dependencies:
|
||||
uc.micro "^1.0.1"
|
||||
|
||||
markdown-it@^12.0.4:
|
||||
version "12.0.4"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.0.4.tgz#eec8247d296327eac3ba9746bdeec9cfcc751e33"
|
||||
integrity sha512-34RwOXZT8kyuOJy25oJNJoulO8L0bTHYWXcdZBYZqFnjIy3NgjeoM3FmPXIOFQ26/lSHYMr8oc62B6adxXcb3Q==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
entities "~2.1.0"
|
||||
linkify-it "^3.0.1"
|
||||
mdurl "^1.0.1"
|
||||
uc.micro "^1.0.5"
|
||||
|
||||
mdurl@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||
integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
|
||||
|
||||
uc.micro@^1.0.1, uc.micro@^1.0.5:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
|
||||
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
|
|
@ -703,7 +703,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
|||
if (isWeb()) {
|
||||
// On web, treat absolute paths as pointing to standard lib files
|
||||
if (filepath.startsWith('/')) {
|
||||
return vscode.Uri.joinPath(this.context.extensionUri, 'node_modules', 'typescript', 'lib', filepath.slice(1));
|
||||
return vscode.Uri.joinPath(this.context.extensionUri, 'dist', 'browser', 'typescript', filepath.slice(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ suite('Notebook Editor', function () {
|
|||
};
|
||||
|
||||
const disposables: vscode.Disposable[] = [];
|
||||
const testDisposables: vscode.Disposable[] = [];
|
||||
|
||||
suiteTeardown(async function () {
|
||||
utils.assertNoRpc();
|
||||
|
@ -38,6 +39,10 @@ suite('Notebook Editor', function () {
|
|||
disposables.push(vscode.workspace.registerNotebookSerializer('notebook.nbdtest', contentSerializer));
|
||||
});
|
||||
|
||||
teardown(async function () {
|
||||
utils.disposeAll(testDisposables);
|
||||
testDisposables.length = 0;
|
||||
});
|
||||
|
||||
test('showNotebookDocment', async function () {
|
||||
|
||||
|
@ -74,4 +79,48 @@ suite('Notebook Editor', function () {
|
|||
assert.ok(await openedEditor);
|
||||
assert.strictEqual(editor.document.uri.toString(), resource.toString());
|
||||
});
|
||||
|
||||
test('Active/Visible Editor', async function () {
|
||||
const firstEditorOpen = utils.asPromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const firstEditor = await vscode.window.showNotebookDocument(resource);
|
||||
await firstEditorOpen;
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor, firstEditor);
|
||||
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(firstEditor), true);
|
||||
|
||||
const secondEditor = await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Beside });
|
||||
assert.strictEqual(secondEditor === vscode.window.activeNotebookEditor, true);
|
||||
assert.notStrictEqual(firstEditor, secondEditor);
|
||||
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(secondEditor), true);
|
||||
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(firstEditor), true);
|
||||
assert.strictEqual(vscode.window.visibleNotebookEditors.length, 2);
|
||||
});
|
||||
|
||||
test('Notebook Editor Event - onDidChangeVisibleNotebookEditors on open/close', async function () {
|
||||
const openedEditor = utils.asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
|
||||
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
await vscode.window.showNotebookDocument(resource);
|
||||
assert.ok(await openedEditor);
|
||||
|
||||
const firstEditorClose = utils.asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
|
||||
await utils.closeAllEditors();
|
||||
await firstEditorClose;
|
||||
});
|
||||
|
||||
test('Notebook Editor Event - onDidChangeVisibleNotebookEditors on two editor groups', async function () {
|
||||
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
let count = 0;
|
||||
testDisposables.push(vscode.window.onDidChangeVisibleNotebookEditors(() => {
|
||||
count = vscode.window.visibleNotebookEditors.length;
|
||||
}));
|
||||
|
||||
await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Active });
|
||||
assert.strictEqual(count, 1);
|
||||
|
||||
await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Beside });
|
||||
assert.strictEqual(count, 2);
|
||||
|
||||
await utils.closeAllEditors();
|
||||
assert.strictEqual(count, 0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -56,18 +56,13 @@ class Kernel {
|
|||
}
|
||||
|
||||
protected async _runCell(cell: vscode.NotebookCell) {
|
||||
// create a single output with exec order 1 and output is plain/text
|
||||
// of either the cell itself or (iff empty) the cell's document's uri
|
||||
const task = this.controller.createNotebookCellExecution(cell);
|
||||
task.start();
|
||||
task.executionOrder = 1;
|
||||
if (cell.notebook.uri.path.endsWith('customRenderer.vsctestnb')) {
|
||||
await task.replaceOutput([new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text('test', 'text/custom')
|
||||
])]);
|
||||
return;
|
||||
}
|
||||
|
||||
await task.replaceOutput([new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text('my output', 'text/plain')
|
||||
vscode.NotebookCellOutputItem.text(cell.document.getText() || cell.document.uri.toString(), 'text/plain')
|
||||
])]);
|
||||
task.end(true);
|
||||
}
|
||||
|
@ -161,40 +156,12 @@ suite('Notebook API tests', function () {
|
|||
suiteDisposables.push(vscode.workspace.registerNotebookContentProvider('notebookCoreTest', apiTestContentProvider));
|
||||
});
|
||||
|
||||
let kernel1: Kernel;
|
||||
let kernel2: Kernel;
|
||||
let defaultKernel: Kernel;
|
||||
|
||||
setup(async function () {
|
||||
|
||||
kernel1 = new Kernel('mainKernel', 'Notebook Primary Test Kernel');
|
||||
|
||||
const listener = vscode.workspace.onDidOpenNotebookDocument(async notebook => {
|
||||
if (notebook.notebookType === kernel1.controller.notebookType) {
|
||||
await vscode.commands.executeCommand('notebook.selectKernel', {
|
||||
extension: 'vscode.vscode-api-tests',
|
||||
id: kernel1.controller.id
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
kernel2 = new class extends Kernel {
|
||||
constructor() {
|
||||
super('secondaryKernel', 'Notebook Secondary Test Kernel');
|
||||
this.controller.supportsExecutionOrder = false;
|
||||
}
|
||||
|
||||
override async _runCell(cell: vscode.NotebookCell) {
|
||||
const task = this.controller.createNotebookCellExecution(cell);
|
||||
task.start();
|
||||
await task.replaceOutput([new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text('my second output', 'text/plain')
|
||||
])]);
|
||||
task.end(true);
|
||||
}
|
||||
};
|
||||
|
||||
testDisposables.push(kernel1.controller, listener, kernel2.controller);
|
||||
// there should be ONE default kernel in this suite
|
||||
defaultKernel = new Kernel('mainKernel', 'Notebook Default Kernel');
|
||||
testDisposables.push(defaultKernel.controller);
|
||||
await saveAllFilesAndCloseAll();
|
||||
});
|
||||
|
||||
|
@ -204,35 +171,6 @@ suite('Notebook API tests', function () {
|
|||
await saveAllFilesAndCloseAll();
|
||||
});
|
||||
|
||||
test('editor onDidChangeVisibleNotebookEditors-event', async function () {
|
||||
const resource = await createRandomNotebookFile();
|
||||
const firstEditorOpen = asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
|
||||
await vscode.window.showNotebookDocument(resource);
|
||||
await firstEditorOpen;
|
||||
|
||||
const firstEditorClose = asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
|
||||
await closeAllEditors();
|
||||
await firstEditorClose;
|
||||
});
|
||||
|
||||
test('editor onDidChangeVisibleNotebookEditors-event 2', async function () {
|
||||
const resource = await createRandomNotebookFile();
|
||||
let count = 0;
|
||||
const disposables: vscode.Disposable[] = [];
|
||||
disposables.push(vscode.window.onDidChangeVisibleNotebookEditors(() => {
|
||||
count = vscode.window.visibleNotebookEditors.length;
|
||||
}));
|
||||
|
||||
await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Active });
|
||||
assert.strictEqual(count, 1);
|
||||
|
||||
await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Beside });
|
||||
assert.strictEqual(count, 2);
|
||||
|
||||
await closeAllEditors();
|
||||
assert.strictEqual(count, 0);
|
||||
});
|
||||
|
||||
test('correct cell selection on undo/redo of cell creation', async function () {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
await vscode.window.showNotebookDocument(notebook);
|
||||
|
@ -252,23 +190,21 @@ suite('Notebook API tests', function () {
|
|||
assert.strictEqual(selectionRedo[0].end, 2);
|
||||
});
|
||||
|
||||
test('editor editing event 2', async function () {
|
||||
// const notebook = await openRandomNotebookDocument();
|
||||
// await vscode.window.showNotebookDocument(notebook);
|
||||
const resource = await createRandomNotebookFile();
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
test('editor editing event', async function () {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
|
||||
const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebooks.onDidChangeNotebookCells);
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
const cellChangeEventRet = await cellsChangeEvent;
|
||||
assert.strictEqual(cellChangeEventRet.document, vscode.window.activeNotebookEditor?.document);
|
||||
assert.strictEqual(cellChangeEventRet.document, editor.document);
|
||||
assert.strictEqual(cellChangeEventRet.changes.length, 1);
|
||||
assert.deepStrictEqual(cellChangeEventRet.changes[0], {
|
||||
start: 1,
|
||||
deletedCount: 0,
|
||||
deletedItems: [],
|
||||
items: [
|
||||
vscode.window.activeNotebookEditor!.document.cellAt(1)
|
||||
editor.document.cellAt(1)
|
||||
]
|
||||
});
|
||||
|
||||
|
@ -280,8 +216,8 @@ suite('Notebook API tests', function () {
|
|||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
const cellOutputsAddedRet = await cellOutputChange;
|
||||
assert.deepStrictEqual(cellOutputsAddedRet, {
|
||||
document: vscode.window.activeNotebookEditor!.document,
|
||||
cells: [vscode.window.activeNotebookEditor!.document.cellAt(0)]
|
||||
document: editor.document,
|
||||
cells: [editor.document.cellAt(0)]
|
||||
});
|
||||
assert.strictEqual(cellOutputsAddedRet.cells[0].outputs.length, 1);
|
||||
|
||||
|
@ -289,8 +225,8 @@ suite('Notebook API tests', function () {
|
|||
await vscode.commands.executeCommand('notebook.cell.clearOutputs');
|
||||
const cellOutputsCleardRet = await cellOutputClear;
|
||||
assert.deepStrictEqual(cellOutputsCleardRet, {
|
||||
document: vscode.window.activeNotebookEditor!.document,
|
||||
cells: [vscode.window.activeNotebookEditor!.document.cellAt(0)]
|
||||
document: editor.document,
|
||||
cells: [editor.document.cellAt(0)]
|
||||
});
|
||||
assert.strictEqual(cellOutputsAddedRet.cells[0].outputs.length, 0);
|
||||
|
||||
|
@ -304,111 +240,45 @@ suite('Notebook API tests', function () {
|
|||
// });
|
||||
});
|
||||
|
||||
test('editor move cell event', async function () {
|
||||
const resource = await createRandomNotebookFile();
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
// const notebook = await openRandomNotebookDocument();
|
||||
// await vscode.window.showNotebookDocument(notebook);
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
|
||||
await vscode.commands.executeCommand('notebook.focusTop');
|
||||
|
||||
const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
|
||||
const moveChange = asPromise(vscode.notebooks.onDidChangeNotebookCells);
|
||||
await vscode.commands.executeCommand('notebook.cell.moveDown');
|
||||
await moveChange;
|
||||
await saveAllEditors();
|
||||
await closeAllEditors();
|
||||
|
||||
// await vscode.window.showNotebookDocument(notebook);
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
const firstEditor = vscode.window.activeNotebookEditor;
|
||||
assert.strictEqual(firstEditor?.document.cellCount, 2);
|
||||
});
|
||||
|
||||
test('notebook editor active/visible', async function () {
|
||||
const resource = await createRandomNotebookFile();
|
||||
const firstEditor = await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Active });
|
||||
assert.strictEqual(firstEditor === vscode.window.activeNotebookEditor, true);
|
||||
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(firstEditor), true);
|
||||
|
||||
const secondEditor = await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Beside });
|
||||
assert.strictEqual(secondEditor === vscode.window.activeNotebookEditor, true);
|
||||
|
||||
assert.notStrictEqual(firstEditor, secondEditor);
|
||||
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(secondEditor), true);
|
||||
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(firstEditor), true);
|
||||
assert.strictEqual(vscode.window.visibleNotebookEditors.length, 2);
|
||||
|
||||
const untitledEditorChange = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
await vscode.commands.executeCommand('workbench.action.files.newUntitledFile');
|
||||
await untitledEditorChange;
|
||||
assert.strictEqual(firstEditor && vscode.window.visibleNotebookEditors.indexOf(firstEditor) >= 0, true);
|
||||
assert.notStrictEqual(firstEditor, vscode.window.activeNotebookEditor);
|
||||
assert.strictEqual(secondEditor && vscode.window.visibleNotebookEditors.indexOf(secondEditor) < 0, true);
|
||||
assert.notStrictEqual(secondEditor, vscode.window.activeNotebookEditor);
|
||||
assert.strictEqual(vscode.window.visibleNotebookEditors.length, 1);
|
||||
|
||||
const activeEditorClose = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
||||
await activeEditorClose;
|
||||
assert.strictEqual(secondEditor, vscode.window.activeNotebookEditor);
|
||||
assert.strictEqual(vscode.window.visibleNotebookEditors.length, 2);
|
||||
assert.strictEqual(secondEditor && vscode.window.visibleNotebookEditors.indexOf(secondEditor) >= 0, true);
|
||||
});
|
||||
|
||||
test('notebook active editor change', async function () {
|
||||
const firstEditorOpen = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
await vscode.window.showNotebookDocument(notebook);
|
||||
await firstEditorOpen;
|
||||
|
||||
const firstEditorDeactivate = asPromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
await vscode.commands.executeCommand('workbench.action.splitEditor');
|
||||
await firstEditorDeactivate;
|
||||
});
|
||||
|
||||
test('edit API batch edits', async function () {
|
||||
const resource = await createRandomNotebookFile();
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
|
||||
const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebooks.onDidChangeNotebookCells);
|
||||
const cellMetadataChangeEvent = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebooks.onDidChangeCellMetadata);
|
||||
const version = vscode.window.activeNotebookEditor!.document.version;
|
||||
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
|
||||
const version = editor.document.version;
|
||||
await editor.edit(editBuilder => {
|
||||
editBuilder.replaceCells(1, 0, [{ kind: vscode.NotebookCellKind.Code, languageId: 'javascript', value: 'test 2', outputs: [], metadata: undefined }]);
|
||||
editBuilder.replaceCellMetadata(0, { inputCollapsed: false });
|
||||
});
|
||||
|
||||
await cellsChangeEvent;
|
||||
await cellMetadataChangeEvent;
|
||||
assert.strictEqual(version + 1, vscode.window.activeNotebookEditor!.document.version);
|
||||
assert.strictEqual(version + 1, editor.document.version);
|
||||
});
|
||||
|
||||
test('edit API batch edits undo/redo', async function () {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
await vscode.window.showNotebookDocument(notebook);
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
|
||||
const cellsChangeEvent = asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebooks.onDidChangeNotebookCells);
|
||||
const cellMetadataChangeEvent = asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebooks.onDidChangeCellMetadata);
|
||||
const version = vscode.window.activeNotebookEditor!.document.version;
|
||||
await vscode.window.activeNotebookEditor!.edit(editBuilder => {
|
||||
const version = editor.document.version;
|
||||
await editor.edit(editBuilder => {
|
||||
editBuilder.replaceCells(1, 0, [{ kind: vscode.NotebookCellKind.Code, languageId: 'javascript', value: 'test 2', outputs: [], metadata: undefined }]);
|
||||
editBuilder.replaceCellMetadata(0, { inputCollapsed: false });
|
||||
});
|
||||
|
||||
await cellsChangeEvent;
|
||||
await cellMetadataChangeEvent;
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 3);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(0)?.metadata.inputCollapsed, false);
|
||||
assert.strictEqual(version + 1, vscode.window.activeNotebookEditor!.document.version);
|
||||
assert.strictEqual(editor.document.cellCount, 3);
|
||||
assert.strictEqual(editor.document.cellAt(0)?.metadata.inputCollapsed, false);
|
||||
assert.strictEqual(version + 1, editor.document.version);
|
||||
|
||||
await vscode.commands.executeCommand('undo');
|
||||
assert.strictEqual(version + 2, vscode.window.activeNotebookEditor!.document.version);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(0)?.metadata.inputCollapsed, undefined);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 2);
|
||||
assert.strictEqual(version + 2, editor.document.version);
|
||||
assert.strictEqual(editor.document.cellAt(0)?.metadata.inputCollapsed, undefined);
|
||||
assert.strictEqual(editor.document.cellCount, 2);
|
||||
});
|
||||
|
||||
test('#98841, initialzation should not emit cell change events.', async function () {
|
||||
|
@ -422,76 +292,61 @@ suite('Notebook API tests', function () {
|
|||
await vscode.window.showNotebookDocument(notebook);
|
||||
assert.strictEqual(count, 0);
|
||||
});
|
||||
// });
|
||||
|
||||
// suite('notebook workflow', () => {
|
||||
|
||||
test('notebook open', async function () {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
await vscode.window.showNotebookDocument(notebook);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'test');
|
||||
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.languageId, 'typescript');
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor === editor, true, 'notebook first');
|
||||
assert.strictEqual(getFocusedCell(editor)?.document.getText(), 'test');
|
||||
assert.strictEqual(getFocusedCell(editor)?.document.languageId, 'typescript');
|
||||
|
||||
const secondCell = vscode.window.activeNotebookEditor!.document.cellAt(1);
|
||||
assert.strictEqual(secondCell!.outputs.length, 1);
|
||||
assert.deepStrictEqual(secondCell!.outputs[0].metadata, { testOutputMetadata: true, ['text/plain']: { testOutputItemMetadata: true } });
|
||||
assert.strictEqual(secondCell!.outputs[0].items.length, 1);
|
||||
assert.strictEqual(secondCell!.outputs[0].items[0].mime, 'text/plain');
|
||||
assert.strictEqual(new TextDecoder().decode(secondCell!.outputs[0].items[0].data), 'Hello World');
|
||||
assert.strictEqual(secondCell!.executionSummary?.executionOrder, 5);
|
||||
assert.strictEqual(secondCell!.executionSummary?.success, true);
|
||||
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
|
||||
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
|
||||
const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
|
||||
assert.notStrictEqual(getFocusedCell(vscode.window.activeNotebookEditor), undefined);
|
||||
assert.strictEqual(activeCell!.document.getText(), '');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 4);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
|
||||
|
||||
await vscode.commands.executeCommand('workbench.action.files.save');
|
||||
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
||||
const secondCell = editor.document.cellAt(1);
|
||||
assert.strictEqual(secondCell.outputs.length, 1);
|
||||
assert.deepStrictEqual(secondCell.outputs[0].metadata, { testOutputMetadata: true, ['text/plain']: { testOutputItemMetadata: true } });
|
||||
assert.strictEqual(secondCell.outputs[0].items.length, 1);
|
||||
assert.strictEqual(secondCell.outputs[0].items[0].mime, 'text/plain');
|
||||
assert.strictEqual(new TextDecoder().decode(secondCell.outputs[0].items[0].data), 'Hello World');
|
||||
assert.strictEqual(secondCell.executionSummary?.executionOrder, 5);
|
||||
assert.strictEqual(secondCell.executionSummary?.success, true);
|
||||
});
|
||||
|
||||
test('notebook cell actions', async function () {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
await vscode.window.showNotebookDocument(notebook);
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), 'test');
|
||||
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.languageId, 'typescript');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor === editor, true, 'notebook first');
|
||||
assert.strictEqual(getFocusedCell(editor)?.document.getText(), 'test');
|
||||
assert.strictEqual(getFocusedCell(editor)?.document.languageId, 'typescript');
|
||||
|
||||
// ---- insert cell below and focus ---- //
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor)?.document.getText(), '');
|
||||
assert.strictEqual(getFocusedCell(editor)?.document.getText(), '');
|
||||
|
||||
// ---- insert cell above and focus ---- //
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
|
||||
let activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
|
||||
assert.notStrictEqual(getFocusedCell(vscode.window.activeNotebookEditor), undefined);
|
||||
let activeCell = getFocusedCell(editor);
|
||||
assert.notStrictEqual(getFocusedCell(editor), undefined);
|
||||
assert.strictEqual(activeCell!.document.getText(), '');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 4);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
|
||||
assert.strictEqual(editor.document.cellCount, 4);
|
||||
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 1);
|
||||
|
||||
// ---- focus bottom ---- //
|
||||
await vscode.commands.executeCommand('notebook.focusBottom');
|
||||
activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 3);
|
||||
activeCell = getFocusedCell(editor);
|
||||
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 3);
|
||||
|
||||
// ---- focus top and then copy down ---- //
|
||||
await vscode.commands.executeCommand('notebook.focusTop');
|
||||
activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
|
||||
activeCell = getFocusedCell(editor);
|
||||
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 0);
|
||||
|
||||
await vscode.commands.executeCommand('notebook.cell.copyDown');
|
||||
activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
|
||||
activeCell = getFocusedCell(editor);
|
||||
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 1);
|
||||
assert.strictEqual(activeCell?.document.getText(), 'test');
|
||||
|
||||
{
|
||||
const focusedCell = getFocusedCell(vscode.window.activeNotebookEditor);
|
||||
const focusedCell = getFocusedCell(editor);
|
||||
assert.strictEqual(focusedCell !== undefined, true);
|
||||
// delete focused cell
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
|
@ -499,45 +354,44 @@ suite('Notebook API tests', function () {
|
|||
await vscode.workspace.applyEdit(edit);
|
||||
}
|
||||
|
||||
activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1);
|
||||
activeCell = getFocusedCell(editor);
|
||||
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 1);
|
||||
assert.strictEqual(activeCell?.document.getText(), '');
|
||||
|
||||
// ---- focus top and then copy up ---- //
|
||||
await vscode.commands.executeCommand('notebook.focusTop');
|
||||
await vscode.commands.executeCommand('notebook.cell.copyUp');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 5);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(0).document.getText(), 'test');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(1).document.getText(), 'test');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(2).document.getText(), '');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellAt(3).document.getText(), '');
|
||||
activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
|
||||
assert.strictEqual(editor.document.cellCount, 5);
|
||||
assert.strictEqual(editor.document.cellAt(0).document.getText(), 'test');
|
||||
assert.strictEqual(editor.document.cellAt(1).document.getText(), 'test');
|
||||
assert.strictEqual(editor.document.cellAt(2).document.getText(), '');
|
||||
assert.strictEqual(editor.document.cellAt(3).document.getText(), '');
|
||||
activeCell = getFocusedCell(editor);
|
||||
assert.strictEqual(editor.document.getCells().indexOf(activeCell!), 0);
|
||||
|
||||
|
||||
// ---- move up and down ---- //
|
||||
|
||||
await vscode.commands.executeCommand('notebook.cell.moveDown');
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(getFocusedCell(vscode.window.activeNotebookEditor)!), 1,
|
||||
`first move down, active cell ${getFocusedCell(vscode.window.activeNotebookEditor)!.document.uri.toString()}, ${getFocusedCell(vscode.window.activeNotebookEditor)!.document.getText()}`);
|
||||
assert.strictEqual(editor.document.getCells().indexOf(getFocusedCell(editor)!), 1,
|
||||
`first move down, active cell ${getFocusedCell(editor)!.document.uri.toString()}, ${getFocusedCell(editor)!.document.getText()}`);
|
||||
|
||||
await vscode.commands.executeCommand('workbench.action.files.save');
|
||||
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
|
||||
});
|
||||
|
||||
test('move cells will not recreate cells in ExtHost', async function () {
|
||||
test('editor move command - event and move cells will not recreate cells in ExtHost (#98126)', async function () {
|
||||
const notebook = await openRandomNotebookDocument();
|
||||
await vscode.window.showNotebookDocument(notebook);
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellBelow');
|
||||
await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove');
|
||||
await vscode.commands.executeCommand('notebook.focusTop');
|
||||
const editor = await vscode.window.showNotebookDocument(notebook);
|
||||
|
||||
const activeCell = getFocusedCell(vscode.window.activeNotebookEditor);
|
||||
assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 0);
|
||||
await vscode.commands.executeCommand('notebook.cell.moveDown');
|
||||
const activeCell = getFocusedCell(editor);
|
||||
assert.strictEqual(activeCell?.index, 0);
|
||||
const moveChange = asPromise(vscode.notebooks.onDidChangeNotebookCells);
|
||||
await vscode.commands.executeCommand('notebook.cell.moveDown');
|
||||
assert.ok(await moveChange);
|
||||
|
||||
const newActiveCell = getFocusedCell(vscode.window.activeNotebookEditor);
|
||||
const newActiveCell = getFocusedCell(editor);
|
||||
assert.strictEqual(newActiveCell?.index, 1);
|
||||
assert.deepStrictEqual(activeCell, newActiveCell);
|
||||
});
|
||||
|
||||
|
@ -674,18 +528,35 @@ suite('Notebook API tests', function () {
|
|||
|
||||
const cell = editor.document.cellAt(0);
|
||||
|
||||
const alternativeKernel = new class extends Kernel {
|
||||
constructor() {
|
||||
super('secondaryKernel', 'Notebook Secondary Test Kernel');
|
||||
this.controller.supportsExecutionOrder = false;
|
||||
}
|
||||
|
||||
override async _runCell(cell: vscode.NotebookCell) {
|
||||
const task = this.controller.createNotebookCellExecution(cell);
|
||||
task.start();
|
||||
await task.replaceOutput([new vscode.NotebookCellOutput([
|
||||
vscode.NotebookCellOutputItem.text('my second output', 'text/plain')
|
||||
])]);
|
||||
task.end(true);
|
||||
}
|
||||
};
|
||||
testDisposables.push(alternativeKernel.controller);
|
||||
|
||||
await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebooks.onDidChangeCellOutputs, async (event) => {
|
||||
await assertKernel(kernel1, notebook);
|
||||
await assertKernel(defaultKernel, notebook);
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
await event;
|
||||
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
||||
assert.strictEqual(cell.outputs[0].items.length, 1);
|
||||
assert.strictEqual(cell.outputs[0].items[0].mime, 'text/plain');
|
||||
assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].items[0].data), 'my output');
|
||||
assert.deepStrictEqual(new TextDecoder().decode(cell.outputs[0].items[0].data), cell.document.getText());
|
||||
});
|
||||
|
||||
await withEvent<vscode.NotebookCellOutputsChangeEvent>(vscode.notebooks.onDidChangeCellOutputs, async (event) => {
|
||||
await assertKernel(kernel2, notebook);
|
||||
await assertKernel(alternativeKernel, notebook);
|
||||
await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
await event;
|
||||
assert.strictEqual(cell.outputs.length, 1, 'should execute'); // runnable, it worked
|
||||
|
@ -1134,74 +1005,44 @@ suite('Notebook API tests', function () {
|
|||
assert.strictEqual(cell.executionSummary?.timing?.endTime, 20);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
suite('statusbar', () => {
|
||||
const emitter = new vscode.EventEmitter<vscode.NotebookCell>();
|
||||
const onDidCallProvide = emitter.event;
|
||||
const suiteDisposables: vscode.Disposable[] = [];
|
||||
suiteTeardown(async function () {
|
||||
assertNoRpc();
|
||||
|
||||
suite('statusbar', () => {
|
||||
const emitter = new vscode.EventEmitter<vscode.NotebookCell>();
|
||||
const onDidCallProvide = emitter.event;
|
||||
suiteSetup(() => {
|
||||
vscode.notebooks.registerNotebookCellStatusBarItemProvider('notebookCoreTest', {
|
||||
async provideCellStatusBarItems(cell: vscode.NotebookCell, _token: vscode.CancellationToken): Promise<vscode.NotebookCellStatusBarItem[]> {
|
||||
emitter.fire(cell);
|
||||
return [];
|
||||
}
|
||||
});
|
||||
});
|
||||
await revertAllDirty();
|
||||
await closeAllEditors();
|
||||
|
||||
test('provideCellStatusBarItems called on metadata change', async function () {
|
||||
const provideCalled = asPromise(onDidCallProvide);
|
||||
const resource = await createRandomNotebookFile();
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
await provideCalled;
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCellMetadata(resource, 0, { inputCollapsed: true });
|
||||
vscode.workspace.applyEdit(edit);
|
||||
await provideCalled;
|
||||
});
|
||||
disposeAll(suiteDisposables);
|
||||
suiteDisposables.length = 0;
|
||||
});
|
||||
|
||||
// });
|
||||
suiteSetup(() => {
|
||||
suiteDisposables.push(vscode.notebooks.registerNotebookCellStatusBarItemProvider('notebookCoreTest', {
|
||||
async provideCellStatusBarItems(cell: vscode.NotebookCell, _token: vscode.CancellationToken): Promise<vscode.NotebookCellStatusBarItem[]> {
|
||||
emitter.fire(cell);
|
||||
return [];
|
||||
}
|
||||
}));
|
||||
|
||||
// suite('webview', () => {
|
||||
// for web, `asWebUri` gets `https`?
|
||||
// test('asWebviewUri', async function () {
|
||||
// if (vscode.env.uiKind === vscode.UIKind.Web) {
|
||||
// return;
|
||||
// }
|
||||
suiteDisposables.push(vscode.workspace.registerNotebookContentProvider('notebookCoreTest', apiTestContentProvider));
|
||||
});
|
||||
|
||||
// const resource = await createRandomNotebookFile();
|
||||
// await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
// assert.strictEqual(vscode.window.activeNotebookEditor !== undefined, true, 'notebook first');
|
||||
// const uri = vscode.window.activeNotebookEditor!.asWebviewUri(vscode.Uri.file('./hello.png'));
|
||||
// assert.strictEqual(uri.scheme, 'vscode-webview-resource');
|
||||
// await closeAllEditors();
|
||||
// });
|
||||
test('provideCellStatusBarItems called on metadata change', async function () {
|
||||
const provideCalled = asPromise(onDidCallProvide);
|
||||
const resource = await createRandomNotebookFile();
|
||||
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
await provideCalled;
|
||||
|
||||
|
||||
// 404 on web
|
||||
// test('custom renderer message', async function () {
|
||||
// if (vscode.env.uiKind === vscode.UIKind.Web) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './customRenderer.vsctestnb'));
|
||||
// await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
|
||||
|
||||
// const editor = vscode.window.activeNotebookEditor;
|
||||
// const promise = new Promise(resolve => {
|
||||
// const messageEmitter = editor?.onDidReceiveMessage(e => {
|
||||
// if (e.type === 'custom_renderer_initialize') {
|
||||
// resolve();
|
||||
// messageEmitter?.dispose();
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
|
||||
// await vscode.commands.executeCommand('notebook.cell.execute');
|
||||
// await promise;
|
||||
// await closeAllEditors();
|
||||
// });
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCellMetadata(resource, 0, { inputCollapsed: true });
|
||||
vscode.workspace.applyEdit(edit);
|
||||
await provideCalled;
|
||||
});
|
||||
});
|
||||
|
||||
suite('Notebook API tests (metadata)', function () {
|
||||
|
|
|
@ -103,7 +103,8 @@
|
|||
"@types/minimist": "^1.2.1",
|
||||
"@types/mocha": "^8.2.0",
|
||||
"@types/node": "14.x",
|
||||
"@types/sinon": "^1.16.36",
|
||||
"@types/sinon": "^10.0.2",
|
||||
"@types/sinon-test": "^2.4.2",
|
||||
"@types/trusted-types": "^1.0.6",
|
||||
"@types/vscode-windows-registry": "^1.0.0",
|
||||
"@types/webpack": "^4.41.25",
|
||||
|
@ -183,7 +184,8 @@
|
|||
"rcedit": "^1.1.0",
|
||||
"request": "^2.85.0",
|
||||
"rimraf": "^2.2.8",
|
||||
"sinon": "^1.17.2",
|
||||
"sinon": "^11.1.1",
|
||||
"sinon-test": "^3.1.0",
|
||||
"source-map": "0.6.1",
|
||||
"source-map-support": "^0.3.2",
|
||||
"style-loader": "^1.0.0",
|
||||
|
@ -196,7 +198,7 @@
|
|||
"vinyl-fs": "^3.0.0",
|
||||
"vscode-debugprotocol": "1.47.0",
|
||||
"vscode-nls-dev": "^3.3.1",
|
||||
"vscode-telemetry-extractor": "^1.7.0",
|
||||
"vscode-telemetry-extractor": "^1.8.0",
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.3.12",
|
||||
"webpack-stream": "^5.2.1",
|
||||
|
|
|
@ -46,7 +46,7 @@ if %errorlevel% neq 0 exit /b %errorlevel%
|
|||
|
||||
:: Tests in the extension host
|
||||
|
||||
set ALL_PLATFORMS_API_TESTS_EXTRA_ARGS=--disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --no-cached-data --disable-updates --disable-keytar --disable-extensions --disable-workspace-trust --user-data-dir=%VSCODEUSERDATADIR%
|
||||
set ALL_PLATFORMS_API_TESTS_EXTRA_ARGS=--disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --no-sandbox --no-cached-data --disable-updates --disable-keytar --disable-extensions --disable-workspace-trust --user-data-dir=%VSCODEUSERDATADIR%
|
||||
|
||||
call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests %ALL_PLATFORMS_API_TESTS_EXTRA_ARGS%
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
|
|
|
@ -193,6 +193,24 @@ export class ActionRunner extends Disposable implements IActionRunner {
|
|||
|
||||
export class Separator extends Action {
|
||||
|
||||
/**
|
||||
* Joins all non-empty lists of actions with separators.
|
||||
*/
|
||||
public static join(...actionLists: readonly IAction[][]) {
|
||||
let out: IAction[] = [];
|
||||
for (const list of actionLists) {
|
||||
if (!list.length) {
|
||||
// skip
|
||||
} else if (out.length) {
|
||||
out = [...out, new Separator(), ...list];
|
||||
} else {
|
||||
out = list;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static readonly ID = 'vs.actions.separator';
|
||||
|
||||
constructor(label?: string) {
|
||||
|
|
|
@ -30,7 +30,7 @@ export namespace Iterable {
|
|||
return iterable[Symbol.iterator]().next().value;
|
||||
}
|
||||
|
||||
export function some<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): boolean {
|
||||
export function some<T>(iterable: Iterable<T>, predicate: (t: T) => unknown): boolean {
|
||||
for (const element of iterable) {
|
||||
if (predicate(element)) {
|
||||
return true;
|
||||
|
|
|
@ -161,7 +161,7 @@ suite('Decorators', () => {
|
|||
|
||||
clock.tick(200);
|
||||
assert.deepStrictEqual(spy.args, [[1], [5]]);
|
||||
spy.reset();
|
||||
spy.resetHistory();
|
||||
|
||||
t.report(4);
|
||||
t.report(5);
|
||||
|
|
|
@ -19,7 +19,7 @@ import { ModesContentHoverWidget } from 'vs/editor/contrib/hover/modesContentHov
|
|||
import { ModesGlyphHoverWidget } from 'vs/editor/contrib/hover/modesGlyphHover';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { editorHoverBackground, editorHoverBorder, editorHoverHighlight, textCodeBlockBackground, textLinkForeground, editorHoverStatusBarBackground, editorHoverForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { editorHoverBackground, editorHoverBorder, editorHoverHighlight, textCodeBlockBackground, textLinkForeground, editorHoverStatusBarBackground, editorHoverForeground, textLinkActiveForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { GotoDefinitionAtPositionEditorContribution } from 'vs/editor/contrib/gotoSymbol/link/goToDefinitionAtPosition';
|
||||
|
@ -327,6 +327,10 @@ registerThemingParticipant((theme, collector) => {
|
|||
if (link) {
|
||||
collector.addRule(`.monaco-editor .monaco-hover a { color: ${link}; }`);
|
||||
}
|
||||
const linkHover = theme.getColor(textLinkActiveForeground);
|
||||
if (linkHover) {
|
||||
collector.addRule(`.monaco-editor .monaco-hover a:hover { color: ${linkHover}; }`);
|
||||
}
|
||||
const hoverForeground = theme.getColor(editorHoverForeground);
|
||||
if (hoverForeground) {
|
||||
collector.addRule(`.monaco-editor .monaco-hover { color: ${hoverForeground}; }`);
|
||||
|
|
|
@ -24,6 +24,9 @@ interface CurrentChord {
|
|||
label: string | null;
|
||||
}
|
||||
|
||||
// Skip logging for high-frequency text editing commands
|
||||
const HIGH_FREQ_COMMANDS = /^(cursor|delete)/;
|
||||
|
||||
export abstract class AbstractKeybindingService extends Disposable implements IKeybindingService {
|
||||
public _serviceBrand: undefined;
|
||||
|
||||
|
@ -263,7 +266,9 @@ export abstract class AbstractKeybindingService extends Disposable implements IK
|
|||
} else {
|
||||
this._commandService.executeCommand(resolveResult.commandId, resolveResult.commandArgs).then(undefined, err => this._notificationService.warn(err));
|
||||
}
|
||||
this._telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', { id: resolveResult.commandId, from: 'keybinding' });
|
||||
if (!HIGH_FREQ_COMMANDS.test(resolveResult.commandId)) {
|
||||
this._telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', { id: resolveResult.commandId, from: 'keybinding' });
|
||||
}
|
||||
}
|
||||
|
||||
return shouldPreventDefault;
|
||||
|
|
|
@ -9,10 +9,13 @@ import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry';
|
|||
import { NullAppender, ITelemetryAppender } from 'vs/platform/telemetry/common/telemetryUtils';
|
||||
import * as Errors from 'vs/base/common/errors';
|
||||
import * as sinon from 'sinon';
|
||||
import * as sinonTest from 'sinon-test';
|
||||
import { ITelemetryData } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
const sinonTestFn = sinonTest(sinon);
|
||||
|
||||
class TestTelemetryAppender implements ITelemetryAppender {
|
||||
|
||||
public events: any[];
|
||||
|
@ -85,7 +88,7 @@ class ErrorTestingSettings {
|
|||
|
||||
suite('TelemetryService', () => {
|
||||
|
||||
test('Disposing', sinon.test(function () {
|
||||
test('Disposing', sinonTestFn(function () {
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new TelemetryService({ appender: testAppender }, undefined!);
|
||||
|
||||
|
@ -98,7 +101,7 @@ suite('TelemetryService', () => {
|
|||
}));
|
||||
|
||||
// event reporting
|
||||
test('Simple event', sinon.test(function () {
|
||||
test('Simple event', sinonTestFn(function () {
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new TelemetryService({ appender: testAppender }, undefined!);
|
||||
|
||||
|
@ -111,7 +114,7 @@ suite('TelemetryService', () => {
|
|||
});
|
||||
}));
|
||||
|
||||
test('Event with data', sinon.test(function () {
|
||||
test('Event with data', sinonTestFn(function () {
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new TelemetryService({ appender: testAppender }, undefined!);
|
||||
|
||||
|
@ -193,7 +196,7 @@ suite('TelemetryService', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('enableTelemetry on by default', sinon.test(function () {
|
||||
test('enableTelemetry on by default', sinonTestFn(function () {
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new TelemetryService({ appender: testAppender }, undefined!);
|
||||
|
||||
|
@ -224,7 +227,7 @@ suite('TelemetryService', () => {
|
|||
}
|
||||
}
|
||||
|
||||
test('Error events', sinon.test(async function (this: any) {
|
||||
test('Error events', sinonTestFn(async function (this: any) {
|
||||
|
||||
let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler();
|
||||
Errors.setUnexpectedErrorHandler(() => { });
|
||||
|
@ -256,7 +259,7 @@ suite('TelemetryService', () => {
|
|||
}
|
||||
}));
|
||||
|
||||
// test('Unhandled Promise Error events', sinon.test(function() {
|
||||
// test('Unhandled Promise Error events', sinonTestFn(function() {
|
||||
//
|
||||
// let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler();
|
||||
// Errors.setUnexpectedErrorHandler(() => {});
|
||||
|
@ -285,7 +288,7 @@ suite('TelemetryService', () => {
|
|||
// }
|
||||
// }));
|
||||
|
||||
test('Handle global errors', sinon.test(async function (this: any) {
|
||||
test('Handle global errors', sinonTestFn(async function (this: any) {
|
||||
let errorStub = sinon.stub();
|
||||
window.onerror = errorStub;
|
||||
|
||||
|
@ -313,7 +316,7 @@ suite('TelemetryService', () => {
|
|||
service.dispose();
|
||||
}));
|
||||
|
||||
test('Error Telemetry removes PII from filename with spaces', sinon.test(async function (this: any) {
|
||||
test('Error Telemetry removes PII from filename with spaces', sinonTestFn(async function (this: any) {
|
||||
let errorStub = sinon.stub();
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
|
@ -336,7 +339,7 @@ suite('TelemetryService', () => {
|
|||
service.dispose();
|
||||
}));
|
||||
|
||||
test('Uncaught Error Telemetry removes PII from filename', sinon.test(function (this: any) {
|
||||
test('Uncaught Error Telemetry removes PII from filename', sinonTestFn(function (this: any) {
|
||||
let clock = this.clock;
|
||||
let errorStub = sinon.stub();
|
||||
window.onerror = errorStub;
|
||||
|
@ -368,7 +371,7 @@ suite('TelemetryService', () => {
|
|||
});
|
||||
}));
|
||||
|
||||
test('Unexpected Error Telemetry removes PII', sinon.test(async function (this: any) {
|
||||
test('Unexpected Error Telemetry removes PII', sinonTestFn(async function (this: any) {
|
||||
let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler();
|
||||
Errors.setUnexpectedErrorHandler(() => { });
|
||||
try {
|
||||
|
@ -399,7 +402,7 @@ suite('TelemetryService', () => {
|
|||
}
|
||||
}));
|
||||
|
||||
test('Uncaught Error Telemetry removes PII', sinon.test(async function (this: any) {
|
||||
test('Uncaught Error Telemetry removes PII', sinonTestFn(async function (this: any) {
|
||||
let errorStub = sinon.stub();
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
|
@ -426,7 +429,7 @@ suite('TelemetryService', () => {
|
|||
service.dispose();
|
||||
}));
|
||||
|
||||
test('Unexpected Error Telemetry removes PII but preserves Code file path', sinon.test(async function (this: any) {
|
||||
test('Unexpected Error Telemetry removes PII but preserves Code file path', sinonTestFn(async function (this: any) {
|
||||
|
||||
let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler();
|
||||
Errors.setUnexpectedErrorHandler(() => { });
|
||||
|
@ -462,7 +465,7 @@ suite('TelemetryService', () => {
|
|||
}
|
||||
}));
|
||||
|
||||
test('Uncaught Error Telemetry removes PII but preserves Code file path', sinon.test(async function (this: any) {
|
||||
test('Uncaught Error Telemetry removes PII but preserves Code file path', sinonTestFn(async function (this: any) {
|
||||
let errorStub = sinon.stub();
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
|
@ -491,7 +494,7 @@ suite('TelemetryService', () => {
|
|||
service.dispose();
|
||||
}));
|
||||
|
||||
test('Unexpected Error Telemetry removes PII but preserves Code file path with node modules', sinon.test(async function (this: any) {
|
||||
test('Unexpected Error Telemetry removes PII but preserves Code file path with node modules', sinonTestFn(async function (this: any) {
|
||||
|
||||
let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler();
|
||||
Errors.setUnexpectedErrorHandler(() => { });
|
||||
|
@ -523,7 +526,7 @@ suite('TelemetryService', () => {
|
|||
}
|
||||
}));
|
||||
|
||||
test('Uncaught Error Telemetry removes PII but preserves Code file path', sinon.test(async function (this: any) {
|
||||
test('Uncaught Error Telemetry removes PII but preserves Code file path', sinonTestFn(async function (this: any) {
|
||||
let errorStub = sinon.stub();
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
|
@ -549,7 +552,7 @@ suite('TelemetryService', () => {
|
|||
}));
|
||||
|
||||
|
||||
test('Unexpected Error Telemetry removes PII but preserves Code file path when PIIPath is configured', sinon.test(async function (this: any) {
|
||||
test('Unexpected Error Telemetry removes PII but preserves Code file path when PIIPath is configured', sinonTestFn(async function (this: any) {
|
||||
|
||||
let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler();
|
||||
Errors.setUnexpectedErrorHandler(() => { });
|
||||
|
@ -585,7 +588,7 @@ suite('TelemetryService', () => {
|
|||
}
|
||||
}));
|
||||
|
||||
test('Uncaught Error Telemetry removes PII but preserves Code file path when PIIPath is configured', sinon.test(async function (this: any) {
|
||||
test('Uncaught Error Telemetry removes PII but preserves Code file path when PIIPath is configured', sinonTestFn(async function (this: any) {
|
||||
let errorStub = sinon.stub();
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
|
@ -614,7 +617,7 @@ suite('TelemetryService', () => {
|
|||
service.dispose();
|
||||
}));
|
||||
|
||||
test('Unexpected Error Telemetry removes PII but preserves Missing Model error message', sinon.test(async function (this: any) {
|
||||
test('Unexpected Error Telemetry removes PII but preserves Missing Model error message', sinonTestFn(async function (this: any) {
|
||||
|
||||
let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler();
|
||||
Errors.setUnexpectedErrorHandler(() => { });
|
||||
|
@ -650,7 +653,7 @@ suite('TelemetryService', () => {
|
|||
}
|
||||
}));
|
||||
|
||||
test('Uncaught Error Telemetry removes PII but preserves Missing Model error message', sinon.test(async function (this: any) {
|
||||
test('Uncaught Error Telemetry removes PII but preserves Missing Model error message', sinonTestFn(async function (this: any) {
|
||||
let errorStub = sinon.stub();
|
||||
window.onerror = errorStub;
|
||||
let settings = new ErrorTestingSettings();
|
||||
|
@ -680,7 +683,7 @@ suite('TelemetryService', () => {
|
|||
service.dispose();
|
||||
}));
|
||||
|
||||
test('Unexpected Error Telemetry removes PII but preserves No Such File error message', sinon.test(async function (this: any) {
|
||||
test('Unexpected Error Telemetry removes PII but preserves No Such File error message', sinonTestFn(async function (this: any) {
|
||||
|
||||
let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler();
|
||||
Errors.setUnexpectedErrorHandler(() => { });
|
||||
|
@ -716,7 +719,7 @@ suite('TelemetryService', () => {
|
|||
}
|
||||
}));
|
||||
|
||||
test('Uncaught Error Telemetry removes PII but preserves No Such File error message', sinon.test(async function (this: any) {
|
||||
test('Uncaught Error Telemetry removes PII but preserves No Such File error message', sinonTestFn(async function (this: any) {
|
||||
let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler();
|
||||
Errors.setUnexpectedErrorHandler(() => { });
|
||||
|
||||
|
@ -754,7 +757,7 @@ suite('TelemetryService', () => {
|
|||
}
|
||||
}));
|
||||
|
||||
test('Telemetry Service sends events when enableTelemetry is on', sinon.test(function () {
|
||||
test('Telemetry Service sends events when enableTelemetry is on', sinonTestFn(function () {
|
||||
let testAppender = new TestTelemetryAppender();
|
||||
let service = new TelemetryService({ appender: testAppender }, undefined!);
|
||||
|
||||
|
|
136
src/vs/vscode.d.ts
vendored
136
src/vs/vscode.d.ts
vendored
|
@ -1989,7 +1989,7 @@ declare module 'vscode' {
|
|||
* { language: 'typescript', scheme: 'file' }
|
||||
*
|
||||
* @example <caption>A language filter that applies to all package.json paths</caption>
|
||||
* { language: 'json', scheme: 'untitled', pattern: '**/package.json' }
|
||||
* { language: 'json', pattern: '**/package.json' }
|
||||
*/
|
||||
export interface DocumentFilter {
|
||||
|
||||
|
@ -2815,9 +2815,9 @@ declare module 'vscode' {
|
|||
}
|
||||
|
||||
/**
|
||||
* The inline values provider interface defines the contract between extensions and the VS Code debugger inline values feature.
|
||||
* The inline values provider interface defines the contract between extensions and the editor's debugger inline values feature.
|
||||
* In this contract the provider returns inline value information for a given document range
|
||||
* and VS Code shows this information in the editor at the end of lines.
|
||||
* and the editor shows this information in the editor at the end of lines.
|
||||
*/
|
||||
export interface InlineValuesProvider {
|
||||
|
||||
|
@ -2829,7 +2829,7 @@ declare module 'vscode' {
|
|||
|
||||
/**
|
||||
* Provide "inline value" information for a given document and range.
|
||||
* VS Code calls this method whenever debugging stops in the given document.
|
||||
* The editor calls this method whenever debugging stops in the given document.
|
||||
* The returned inline values information is rendered in the editor at the end of lines.
|
||||
*
|
||||
* @param document The document for which the inline values information is needed.
|
||||
|
@ -3646,7 +3646,7 @@ declare module 'vscode' {
|
|||
* ```
|
||||
*
|
||||
* @see {@link SemanticTokensBuilder} for a helper to encode tokens as integers.
|
||||
* *NOTE*: When doing edits, it is possible that multiple edits occur until VS Code decides to invoke the semantic tokens provider.
|
||||
* *NOTE*: When doing edits, it is possible that multiple edits occur until the editor decides to invoke the semantic tokens provider.
|
||||
* *NOTE*: If the provider cannot temporarily compute semantic tokens, it can indicate this by throwing an error with the message 'Busy'.
|
||||
*/
|
||||
provideDocumentSemanticTokens(document: TextDocument, token: CancellationToken): ProviderResult<SemanticTokens>;
|
||||
|
@ -5556,7 +5556,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* Role of the widget which defines how a screen reader interacts with it.
|
||||
* The role should be set in special cases when for example a tree-like element behaves like a checkbox.
|
||||
* If role is not specified VS Code will pick the appropriate role automatically.
|
||||
* If role is not specified the editor will pick the appropriate role automatically.
|
||||
* More about aria roles can be found here https://w3c.github.io/aria/#widget_roles
|
||||
*/
|
||||
role?: string;
|
||||
|
@ -5648,7 +5648,7 @@ declare module 'vscode' {
|
|||
* The command must be {@link commands.getCommands known}.
|
||||
*
|
||||
* Note that if this is a {@link Command `Command`} object, only the {@link Command.command `command`} and {@link Command.arguments `arguments`}
|
||||
* are used by VS Code.
|
||||
* are used by the editor.
|
||||
*/
|
||||
command: string | Command | undefined;
|
||||
|
||||
|
@ -5959,13 +5959,13 @@ declare module 'vscode' {
|
|||
export enum ExtensionMode {
|
||||
/**
|
||||
* The extension is installed normally (for example, from the marketplace
|
||||
* or VSIX) in VS Code.
|
||||
* or VSIX) in the editor.
|
||||
*/
|
||||
Production = 1,
|
||||
|
||||
/**
|
||||
* The extension is running from an `--extensionDevelopmentPath` provided
|
||||
* when launching VS Code.
|
||||
* when launching the editor.
|
||||
*/
|
||||
Development = 2,
|
||||
|
||||
|
@ -6549,7 +6549,7 @@ declare module 'vscode' {
|
|||
constructor(commandLine: string, options?: ShellExecutionOptions);
|
||||
|
||||
/**
|
||||
* Creates a shell execution with a command and arguments. For the real execution VS Code will
|
||||
* Creates a shell execution with a command and arguments. For the real execution the editor will
|
||||
* construct a command line from the command and the arguments. This is subject to interpretation
|
||||
* especially when it comes to quoting. If full control over the command line is needed please
|
||||
* use the constructor that creates a `ShellExecution` with the full command line.
|
||||
|
@ -6865,7 +6865,7 @@ declare module 'vscode' {
|
|||
export function fetchTasks(filter?: TaskFilter): Thenable<Task[]>;
|
||||
|
||||
/**
|
||||
* Executes a task that is managed by VS Code. The returned
|
||||
* Executes a task that is managed by the editor. The returned
|
||||
* task execution can be used to terminate the task.
|
||||
*
|
||||
* @throws When running a ShellExecution or a ProcessExecution
|
||||
|
@ -7281,7 +7281,7 @@ declare module 'vscode' {
|
|||
* @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
|
||||
* support writing (i.e. it is readonly), and `undefined` if the editor does not
|
||||
* know about the filesystem.
|
||||
*/
|
||||
isWritableFileSystem(scheme: string): boolean | undefined;
|
||||
|
@ -7362,7 +7362,7 @@ declare module 'vscode' {
|
|||
* Webviews are sandboxed from normal extension process, so all communication with the webview must use
|
||||
* message passing. To send a message from the extension to the webview, use {@link Webview.postMessage `postMessage`}.
|
||||
* To send message from the webview back to an extension, use the `acquireVsCodeApi` function inside the webview
|
||||
* to get a handle to VS Code's api and then call `.postMessage()`:
|
||||
* to get a handle to the editor's api and then call `.postMessage()`:
|
||||
*
|
||||
* ```html
|
||||
* <script>
|
||||
|
@ -7384,7 +7384,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* Fired when the webview content posts a message.
|
||||
*
|
||||
* Webview content can post strings or json serializable objects back to a VS Code extension. They cannot
|
||||
* Webview content can post strings or json serializable objects back to an extension. They cannot
|
||||
* post `Blob`, `File`, `ImageData` and other DOM specific objects since the extension that receives the
|
||||
* message does not run in a browser environment.
|
||||
*/
|
||||
|
@ -7452,7 +7452,7 @@ declare module 'vscode' {
|
|||
*
|
||||
* Normally the webview panel'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
|
||||
* or UI can set the `retainContextWhenHidden` to make the editor 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
|
||||
|
@ -7562,7 +7562,7 @@ declare module 'vscode' {
|
|||
* There are two types of webview persistence:
|
||||
*
|
||||
* - Persistence within a session.
|
||||
* - Persistence across sessions (across restarts of VS Code).
|
||||
* - Persistence across sessions (across restarts of the editor).
|
||||
*
|
||||
* A `WebviewPanelSerializer` is only required for the second case: persisting a webview across sessions.
|
||||
*
|
||||
|
@ -7582,8 +7582,8 @@ declare module 'vscode' {
|
|||
* setState({ value: oldState.value + 1 })
|
||||
* ```
|
||||
*
|
||||
* A `WebviewPanelSerializer` extends this persistence across restarts of VS Code. When the editor is shutdown,
|
||||
* VS Code will save off the state from `setState` of all webviews that have a serializer. When the
|
||||
* A `WebviewPanelSerializer` extends this persistence across restarts of the editor. When the editor is shutdown,
|
||||
* it will save off the state from `setState` of all webviews that have a serializer. When the
|
||||
* webview first becomes visible after the restart, this state is passed to `deserializeWebviewPanel`.
|
||||
* The extension can then restore the old `WebviewPanel` from this state.
|
||||
*
|
||||
|
@ -7678,7 +7678,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* Persisted state from the webview content.
|
||||
*
|
||||
* To save resources, VS Code normally deallocates webview documents (the iframe content) that are not visible.
|
||||
* To save resources, the editor 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.
|
||||
|
@ -7701,7 +7701,7 @@ declare module 'vscode' {
|
|||
* setState({ value: oldState.value + 1 })
|
||||
* ```
|
||||
*
|
||||
* VS Code ensures that the persisted state is saved correctly when a webview is hidden and across
|
||||
* The editor ensures that the persisted state is saved correctly when a webview is hidden and across
|
||||
* editor restarts.
|
||||
*/
|
||||
readonly state: T | undefined;
|
||||
|
@ -7731,7 +7731,7 @@ declare module 'vscode' {
|
|||
* Provider for text based custom editors.
|
||||
*
|
||||
* Text based custom editors use a {@link TextDocument `TextDocument`} as their data model. This considerably simplifies
|
||||
* implementing a custom editor as it allows VS Code to handle many common operations such as
|
||||
* implementing a custom editor as it allows the editor to handle many common operations such as
|
||||
* undo and backup. The provider is responsible for synchronizing text changes between the webview and the `TextDocument`.
|
||||
*/
|
||||
export interface CustomTextEditorProvider {
|
||||
|
@ -7762,7 +7762,7 @@ declare module 'vscode' {
|
|||
* Represents a custom document used by a {@link CustomEditorProvider `CustomEditorProvider`}.
|
||||
*
|
||||
* Custom documents are only used within a given `CustomEditorProvider`. The lifecycle of a `CustomDocument` is
|
||||
* managed by VS Code. When no more references remain to a `CustomDocument`, it is disposed of.
|
||||
* managed by the editor. When no more references remain to a `CustomDocument`, it is disposed of.
|
||||
*/
|
||||
interface CustomDocument {
|
||||
/**
|
||||
|
@ -7773,14 +7773,14 @@ declare module 'vscode' {
|
|||
/**
|
||||
* Dispose of the custom document.
|
||||
*
|
||||
* This is invoked by VS Code when there are no more references to a given `CustomDocument` (for example when
|
||||
* This is invoked by the editor when there are no more references to a given `CustomDocument` (for example when
|
||||
* all editors associated with the document have been closed.)
|
||||
*/
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event triggered by extensions to signal to VS Code that an edit has occurred on an {@link CustomDocument `CustomDocument`}.
|
||||
* Event triggered by extensions to signal to the editor that an edit has occurred on an {@link CustomDocument `CustomDocument`}.
|
||||
*
|
||||
* @see {@link CustomEditorProvider.onDidChangeCustomDocument `CustomEditorProvider.onDidChangeCustomDocument`}.
|
||||
*/
|
||||
|
@ -7794,18 +7794,18 @@ declare module 'vscode' {
|
|||
/**
|
||||
* Undo the edit operation.
|
||||
*
|
||||
* This is invoked by VS Code when the user undoes this edit. To implement `undo`, your
|
||||
* This is invoked by the editor 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`.
|
||||
* edit was added to the editor's internal edit stack by `onDidChangeCustomDocument`.
|
||||
*/
|
||||
undo(): Thenable<void> | void;
|
||||
|
||||
/**
|
||||
* Redo the edit operation.
|
||||
*
|
||||
* This is invoked by VS Code when the user redoes this edit. To implement `redo`, your
|
||||
* This is invoked by the editor 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`.
|
||||
* edit was added to the editor's internal edit stack by `onDidChangeCustomDocument`.
|
||||
*/
|
||||
redo(): Thenable<void> | void;
|
||||
|
||||
|
@ -7818,7 +7818,7 @@ declare module 'vscode' {
|
|||
}
|
||||
|
||||
/**
|
||||
* Event triggered by extensions to signal to VS Code that the content of a {@link CustomDocument `CustomDocument`}
|
||||
* Event triggered by extensions to signal to the editor that the content of a {@link CustomDocument `CustomDocument`}
|
||||
* has changed.
|
||||
*
|
||||
* @see {@link CustomEditorProvider.onDidChangeCustomDocument `CustomEditorProvider.onDidChangeCustomDocument`}.
|
||||
|
@ -7844,7 +7844,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* 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
|
||||
* This is called by the editor 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;
|
||||
|
@ -7955,14 +7955,14 @@ declare module 'vscode' {
|
|||
* anything from changing some text, to cropping an image, to reordering a list. Your extension is free to
|
||||
* define what an edit is and what data is stored on each edit.
|
||||
*
|
||||
* Firing `onDidChange` causes VS Code to mark the editors as being dirty. This is cleared when the user either
|
||||
* Firing `onDidChange` causes the editors to be marked as being dirty. This is cleared when the user either
|
||||
* saves or reverts the file.
|
||||
*
|
||||
* Editors that support undo/redo must fire a `CustomDocumentEditEvent` whenever an edit happens. This allows
|
||||
* users to undo and redo the edit using VS Code's standard VS Code keyboard shortcuts. VS Code will also mark
|
||||
* users to undo and redo the edit using the editor's standard keyboard shortcuts. The editor will also mark
|
||||
* the editor as no longer being dirty if the user undoes all edits to the last saved state.
|
||||
*
|
||||
* Editors that support editing but cannot use VS Code's standard undo/redo mechanism must fire a `CustomDocumentContentChangeEvent`.
|
||||
* Editors that support editing but cannot use the editor's standard undo/redo mechanism must fire a `CustomDocumentContentChangeEvent`.
|
||||
* The only way for a user to clear the dirty state of an editor that does not support undo/redo is to either
|
||||
* `save` or `revert` the file.
|
||||
*
|
||||
|
@ -7973,7 +7973,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* Save a custom document.
|
||||
*
|
||||
* This method is invoked by VS Code when the user saves a custom editor. This can happen when the user
|
||||
* This method is invoked by the editor when the user saves a custom editor. This can happen when the user
|
||||
* triggers save while the custom editor is active, by commands such as `save all`, or by auto save if enabled.
|
||||
*
|
||||
* To implement `save`, the implementer must persist the custom editor. This usually means writing the
|
||||
|
@ -7990,7 +7990,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* Save a custom document to a different location.
|
||||
*
|
||||
* This method is invoked by VS Code when the user triggers 'save as' on a custom editor. The implementer must
|
||||
* This method is invoked by the editor when the user triggers 'save as' on a custom editor. The implementer must
|
||||
* persist the custom editor to `destination`.
|
||||
*
|
||||
* When the user accepts save as, the current editor is be replaced by an non-dirty editor for the newly saved file.
|
||||
|
@ -8006,8 +8006,8 @@ declare module 'vscode' {
|
|||
/**
|
||||
* Revert a custom document to its last saved state.
|
||||
*
|
||||
* This method is invoked by VS Code when the user triggers `File: Revert File` in a custom editor. (Note that
|
||||
* this is only used using VS Code's `File: Revert File` command and not on a `git revert` of the file).
|
||||
* This method is invoked by the editor when the user triggers `File: Revert File` in a custom editor. (Note that
|
||||
* this is only used using the editor's `File: Revert File` command and not on a `git revert` of the file).
|
||||
*
|
||||
* To implement `revert`, the implementer must make sure all editor instances (webviews) for `document`
|
||||
* are displaying the document in the same state is saved in. This usually means reloading the file from the
|
||||
|
@ -8025,7 +8025,7 @@ declare module 'vscode' {
|
|||
*
|
||||
* Backups are used for hot exit and to prevent data loss. Your `backup` method should persist the resource in
|
||||
* its current state, i.e. with the edits applied. Most commonly this means saving the resource to disk in
|
||||
* the `ExtensionContext.storagePath`. When VS Code reloads and your custom editor is opened for a resource,
|
||||
* the `ExtensionContext.storagePath`. When the editor reloads and your custom editor is opened for a resource,
|
||||
* your extension should first check to see if any backups exist for the resource. If there is a backup, your
|
||||
* extension should load the file contents from there instead of from the resource in the workspace.
|
||||
*
|
||||
|
@ -8039,7 +8039,7 @@ declare module 'vscode' {
|
|||
* @param cancellation Token that signals the current backup since a new backup is coming in. It is up to your
|
||||
* extension to decided how to respond to cancellation. If for example your extension is backing up a large file
|
||||
* in an operation that takes time to complete, your extension may decide to finish the ongoing backup rather
|
||||
* than cancelling it to ensure that VS Code has some valid backup.
|
||||
* than cancelling it to ensure that the editor has some valid backup.
|
||||
*/
|
||||
backupCustomDocument(document: T, context: CustomDocumentBackupContext, cancellation: CancellationToken): Thenable<CustomDocumentBackup>;
|
||||
}
|
||||
|
@ -8193,7 +8193,7 @@ declare module 'vscode' {
|
|||
*
|
||||
* If the extension is running remotely, this function automatically establishes a port forwarding tunnel
|
||||
* from the local machine to `target` on the remote and returns a local uri to the tunnel. The lifetime of
|
||||
* the port forwarding tunnel is managed by VS Code and the tunnel can be closed by the user.
|
||||
* the port forwarding tunnel is managed by the editor and the tunnel can be closed by the user.
|
||||
*
|
||||
* *Note* that uris passed through `openExternal` are automatically resolved and you should not call `asExternalUri` on them.
|
||||
*
|
||||
|
@ -9357,7 +9357,7 @@ declare module 'vscode' {
|
|||
cwd?: string | Uri;
|
||||
|
||||
/**
|
||||
* Object with environment variables that will be added to the VS Code process.
|
||||
* Object with environment variables that will be added to the editor process.
|
||||
*/
|
||||
env?: { [key: string]: string | null | undefined };
|
||||
|
||||
|
@ -10306,15 +10306,15 @@ declare module 'vscode' {
|
|||
|
||||
/**
|
||||
* Namespace for dealing with the current workspace. A workspace is the collection of one
|
||||
* or more folders that are opened in a VS Code window (instance).
|
||||
* or more folders that are opened in an editor window (instance).
|
||||
*
|
||||
* It is also possible to open VS Code without a workspace. For example, when you open a
|
||||
* new VS Code window by selecting a file from your platform's File menu, you will not be
|
||||
* inside a workspace. In this mode, some of VS Code's capabilities are reduced but you can
|
||||
* It is also possible to open an editor without a workspace. For example, when you open a
|
||||
* new editor window by selecting a file from your platform's File menu, you will not be
|
||||
* inside a workspace. In this mode, some of the editor's capabilities are reduced but you can
|
||||
* still open text files and edit them.
|
||||
*
|
||||
* Refer to https://code.visualstudio.com/docs/editor/workspaces for more information on
|
||||
* the concept of workspaces in VS Code.
|
||||
* the concept of workspaces.
|
||||
*
|
||||
* The workspace offers support for {@link workspace.createFileSystemWatcher listening} to fs
|
||||
* events and for {@link workspace.findFiles finding} files. Both perform well and run _outside_
|
||||
|
@ -10331,22 +10331,22 @@ declare module 'vscode' {
|
|||
export const fs: FileSystem;
|
||||
|
||||
/**
|
||||
* The workspace folder that is open in VS Code. `undefined` when no workspace
|
||||
* The workspace folder that is open in the editor. `undefined` when no workspace
|
||||
* has been opened.
|
||||
*
|
||||
* Refer to https://code.visualstudio.com/docs/editor/workspaces for more information
|
||||
* on workspaces in VS Code.
|
||||
* on workspaces.
|
||||
*
|
||||
* @deprecated Use {@link workspace.workspaceFolders `workspaceFolders`} instead.
|
||||
*/
|
||||
export const rootPath: string | undefined;
|
||||
|
||||
/**
|
||||
* List of workspace folders that are open in VS Code. `undefined` when no workspace
|
||||
* List of workspace folders that are open in the editor. `undefined` when no workspace
|
||||
* has been opened.
|
||||
*
|
||||
* Refer to https://code.visualstudio.com/docs/editor/workspaces for more information
|
||||
* on workspaces in VS Code.
|
||||
* on workspaces.
|
||||
*
|
||||
* *Note* that the first entry corresponds to the value of `rootPath`.
|
||||
*/
|
||||
|
@ -10357,7 +10357,7 @@ declare module 'vscode' {
|
|||
* has been opened.
|
||||
*
|
||||
* Refer to https://code.visualstudio.com/docs/editor/workspaces for more information on
|
||||
* the concept of workspaces in VS Code.
|
||||
* the concept of workspaces.
|
||||
*/
|
||||
export const name: string | undefined;
|
||||
|
||||
|
@ -10386,7 +10386,7 @@ declare module 'vscode' {
|
|||
* ```
|
||||
*
|
||||
* Refer to https://code.visualstudio.com/docs/editor/workspaces for more information on
|
||||
* the concept of workspaces in VS Code.
|
||||
* the concept of workspaces.
|
||||
*
|
||||
* **Note:** it is not advised to use `workspace.workspaceFile` to write
|
||||
* configuration data into the file. You can use `workspace.getConfiguration().update()`
|
||||
|
@ -11079,7 +11079,7 @@ declare module 'vscode' {
|
|||
|
||||
/**
|
||||
* Register a provider that locates evaluatable expressions in text documents.
|
||||
* VS Code will evaluate the expression in the active debug session and will show the result in the debug hover.
|
||||
* The editor will evaluate the expression in the active debug session and will show the result in the debug hover.
|
||||
*
|
||||
* If multiple providers are registered for a language an arbitrary provider will be used.
|
||||
*
|
||||
|
@ -11091,7 +11091,7 @@ declare module 'vscode' {
|
|||
|
||||
/**
|
||||
* Register a provider that returns data for the debugger's 'inline value' feature.
|
||||
* Whenever the generic VS Code debugger has stopped in a source file, providers registered for the language of the file
|
||||
* Whenever the generic debugger has stopped in a source file, providers registered for the language of the file
|
||||
* are called to return textual data that will be shown in the editor at the end of lines.
|
||||
*
|
||||
* Multiple providers can be registered for a language. In that case providers are asked in
|
||||
|
@ -12074,7 +12074,7 @@ declare module 'vscode' {
|
|||
* The command must be {@link commands.getCommands known}.
|
||||
*
|
||||
* Note that if this is a {@link Command `Command`} object, only the {@link Command.command `command`} and {@link Command.arguments `arguments`}
|
||||
* are used by VS Code.
|
||||
* are used by the editor.
|
||||
*/
|
||||
command?: string | Command;
|
||||
|
||||
|
@ -12496,10 +12496,10 @@ declare module 'vscode' {
|
|||
customRequest(command: string, args?: any): Thenable<any>;
|
||||
|
||||
/**
|
||||
* Maps a VS Code breakpoint to the corresponding Debug Adapter Protocol (DAP) breakpoint that is managed by the debug adapter of the debug session.
|
||||
* If no DAP breakpoint exists (either because the VS Code breakpoint was not yet registered or because the debug adapter is not interested in the breakpoint), the value `undefined` is returned.
|
||||
* Maps a breakpoint in the editor to the corresponding Debug Adapter Protocol (DAP) breakpoint that is managed by the debug adapter of the debug session.
|
||||
* If no DAP breakpoint exists (either because the editor breakpoint was not yet registered or because the debug adapter is not interested in the breakpoint), the value `undefined` is returned.
|
||||
*
|
||||
* @param breakpoint A VS Code {@link Breakpoint}.
|
||||
* @param breakpoint A {@link Breakpoint} in the editor.
|
||||
* @return A promise that resolves to the Debug Adapter Protocol breakpoint or `undefined`.
|
||||
*/
|
||||
getDebugProtocolBreakpoint(breakpoint: Breakpoint): Thenable<DebugProtocolBreakpoint | undefined>;
|
||||
|
@ -12588,7 +12588,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* The command or path of the debug adapter executable.
|
||||
* A command must be either an absolute path of an executable or the name of an command to be looked up via the PATH environment variable.
|
||||
* The special value 'node' will be mapped to VS Code's built-in Node.js runtime.
|
||||
* The special value 'node' will be mapped to the editor's built-in Node.js runtime.
|
||||
*/
|
||||
readonly command: string;
|
||||
|
||||
|
@ -12659,12 +12659,12 @@ declare module 'vscode' {
|
|||
}
|
||||
|
||||
/**
|
||||
* A debug adapter that implements the Debug Adapter Protocol can be registered with VS Code if it implements the DebugAdapter interface.
|
||||
* A debug adapter that implements the Debug Adapter Protocol can be registered with the editor if it implements the DebugAdapter interface.
|
||||
*/
|
||||
export interface DebugAdapter extends Disposable {
|
||||
|
||||
/**
|
||||
* An event which fires after the debug adapter has sent a Debug Adapter Protocol message to VS Code.
|
||||
* An event which fires after the debug adapter has sent a Debug Adapter Protocol message to the editor.
|
||||
* Messages can be requests, responses, or events.
|
||||
*/
|
||||
readonly onDidSendMessage: Event<DebugProtocolMessage>;
|
||||
|
@ -12713,7 +12713,7 @@ declare module 'vscode' {
|
|||
}
|
||||
|
||||
/**
|
||||
* A Debug Adapter Tracker is a means to track the communication between VS Code and a Debug Adapter.
|
||||
* A Debug Adapter Tracker is a means to track the communication between the editor and a Debug Adapter.
|
||||
*/
|
||||
export interface DebugAdapterTracker {
|
||||
/**
|
||||
|
@ -12721,11 +12721,11 @@ declare module 'vscode' {
|
|||
*/
|
||||
onWillStartSession?(): void;
|
||||
/**
|
||||
* The debug adapter is about to receive a Debug Adapter Protocol message from VS Code.
|
||||
* The debug adapter is about to receive a Debug Adapter Protocol message from the editor.
|
||||
*/
|
||||
onWillReceiveMessage?(message: any): void;
|
||||
/**
|
||||
* The debug adapter has sent a Debug Adapter Protocol message to VS Code.
|
||||
* The debug adapter has sent a Debug Adapter Protocol message to the editor.
|
||||
*/
|
||||
onDidSendMessage?(message: any): void;
|
||||
/**
|
||||
|
@ -12745,7 +12745,7 @@ declare module 'vscode' {
|
|||
export interface DebugAdapterTrackerFactory {
|
||||
/**
|
||||
* The method 'createDebugAdapterTracker' is called at the start of a debug session in order
|
||||
* to return a "tracker" object that provides read-access to the communication between VS Code and a debug adapter.
|
||||
* to return a "tracker" object that provides read-access to the communication between the editor and a debug adapter.
|
||||
*
|
||||
* @param session The {@link DebugSession debug session} for which the debug adapter tracker will be used.
|
||||
* @return A {@link DebugAdapterTracker debug adapter tracker} or undefined.
|
||||
|
@ -13036,7 +13036,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* Converts a "Source" descriptor object received via the Debug Adapter Protocol into a Uri that can be used to load its contents.
|
||||
* If the source descriptor is based on a path, a file Uri is returned.
|
||||
* If the source descriptor uses a reference number, a specific debug Uri (scheme 'debug') is constructed that requires a corresponding VS Code ContentProvider and a running debug session
|
||||
* If the source descriptor uses a reference number, a specific debug Uri (scheme 'debug') is constructed that requires a corresponding ContentProvider and a running debug session
|
||||
*
|
||||
* If the "Source" descriptor has insufficient information for creating the Uri, an error is thrown.
|
||||
*
|
||||
|
@ -13585,7 +13585,7 @@ declare module 'vscode' {
|
|||
* quickpick to select which account they would like to use.
|
||||
*
|
||||
* Currently, there are only two authentication providers that are contributed from built in extensions
|
||||
* to VS Code that implement GitHub and Microsoft authentication: their providerId's are 'github' and 'microsoft'.
|
||||
* to the editor that implement GitHub and Microsoft authentication: their providerId's are 'github' and 'microsoft'.
|
||||
* @param providerId The id of the provider to use
|
||||
* @param scopes A list of scopes representing the permissions requested. These are dependent on the authentication provider
|
||||
* @param options The {@link GetSessionOptions} to use
|
||||
|
@ -13600,7 +13600,7 @@ declare module 'vscode' {
|
|||
* quickpick to select which account they would like to use.
|
||||
*
|
||||
* Currently, there are only two authentication providers that are contributed from built in extensions
|
||||
* to VS Code that implement GitHub and Microsoft authentication: their providerId's are 'github' and 'microsoft'.
|
||||
* to the editor that implement GitHub and Microsoft authentication: their providerId's are 'github' and 'microsoft'.
|
||||
* @param providerId The id of the provider to use
|
||||
* @param scopes A list of scopes representing the permissions requested. These are dependent on the authentication provider
|
||||
* @param options The {@link GetSessionOptions} to use
|
||||
|
|
48
src/vs/vscode.proposed.d.ts
vendored
48
src/vs/vscode.proposed.d.ts
vendored
|
@ -9,7 +9,7 @@
|
|||
* distribution and CANNOT be used in published extensions.
|
||||
*
|
||||
* To test these API in local environment:
|
||||
* - Use Insiders release of VS Code.
|
||||
* - Use Insiders release of 'VS Code'.
|
||||
* - Add `"enableProposedApi": true` to your package.json.
|
||||
* - Copy this file to your project.
|
||||
*/
|
||||
|
@ -147,8 +147,8 @@ declare module 'vscode' {
|
|||
/**
|
||||
* Resolve the authority part of the current opened `vscode-remote://` URI.
|
||||
*
|
||||
* This method will be invoked once during the startup of VS Code and again each time
|
||||
* VS Code detects a disconnection.
|
||||
* This method will be invoked once during the startup of the editor and again each time
|
||||
* the editor detects a disconnection.
|
||||
*
|
||||
* @param authority The authority part of the current opened `vscode-remote://` URI.
|
||||
* @param context A context indicating if this is the first call or a subsequent call.
|
||||
|
@ -438,11 +438,11 @@ declare module 'vscode' {
|
|||
/**
|
||||
* Additional information regarding the state of the completed search.
|
||||
*
|
||||
* Messages with "Information" tyle support links in markdown syntax:
|
||||
* Messages with "Information" style support links in markdown syntax:
|
||||
* - Click to [run a command](command:workbench.action.OpenQuickPick)
|
||||
* - Click to [open a website](https://aka.ms)
|
||||
*
|
||||
* Commands may optionally return { triggerSearch: true } to signal to VS Code that the original search should run be agian.
|
||||
* Commands may optionally return { triggerSearch: true } to signal to the editor that the original search should run be again.
|
||||
*/
|
||||
message?: TextSearchCompleteMessage | TextSearchCompleteMessage[];
|
||||
}
|
||||
|
@ -553,7 +553,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* 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
|
||||
* A FileSearchProvider is the more powerful of two ways to implement file search in the editor. 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,
|
||||
|
@ -987,7 +987,7 @@ declare module 'vscode' {
|
|||
* 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.
|
||||
* the editor will destroy 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.
|
||||
|
@ -1352,7 +1352,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* 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
|
||||
* This is called by the editor 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;
|
||||
|
@ -1434,11 +1434,13 @@ declare module 'vscode' {
|
|||
/**
|
||||
* The parameters without the return type. Render after `name`.
|
||||
*/
|
||||
//todo@API rename to signature
|
||||
parameters?: string;
|
||||
|
||||
/**
|
||||
* The fully qualified name, like package name or file path. Rendered after `signature`.
|
||||
*/
|
||||
//todo@API find better name
|
||||
qualifier?: string;
|
||||
|
||||
/**
|
||||
|
@ -1882,7 +1884,7 @@ declare module 'vscode' {
|
|||
* disambiguate multiple sets of results in a test run. It is useful if
|
||||
* tests are run across multiple platforms, for example.
|
||||
* @param persist Whether the results created by the run should be
|
||||
* persisted in VS Code. This may be false if the results are coming from
|
||||
* persisted in the editor. This may be false if the results are coming from
|
||||
* a file already saved externally, such as a coverage information file.
|
||||
*/
|
||||
export function createTestRun<T>(request: TestRunRequest<T>, name?: string, persist?: boolean): TestRun<T>;
|
||||
|
@ -1901,7 +1903,7 @@ declare module 'vscode' {
|
|||
export function createTestItem<T = void, TChildren = any>(options: TestItemOptions): TestItem<T, TChildren>;
|
||||
|
||||
/**
|
||||
* List of test results stored by VS Code, sorted in descnding
|
||||
* List of test results stored by the editor, sorted in descending
|
||||
* order by their `completedAt` time.
|
||||
* @stability experimental
|
||||
*/
|
||||
|
@ -1941,7 +1943,7 @@ declare module 'vscode' {
|
|||
readonly onDidDiscoverInitialTests: Event<void>;
|
||||
|
||||
/**
|
||||
* Dispose of the observer, allowing VS Code to eventually tell test
|
||||
* Dispose of the observer, allowing the editor to eventually tell test
|
||||
* providers that they no longer need to update tests.
|
||||
*/
|
||||
dispose(): void;
|
||||
|
@ -2028,7 +2030,7 @@ declare module 'vscode' {
|
|||
tests: TestItem<T>[];
|
||||
|
||||
/**
|
||||
* An array of tests the user has marked as excluded in VS Code. May be
|
||||
* An array of tests the user has marked as excluded in the editor. May be
|
||||
* omitted if no exclusions were requested. Test controllers should not run
|
||||
* excluded tests or any children of excluded tests.
|
||||
*/
|
||||
|
@ -2332,7 +2334,7 @@ declare module 'vscode' {
|
|||
}
|
||||
|
||||
/**
|
||||
* TestResults can be provided to VS Code in {@link test.publishTestResult},
|
||||
* TestResults can be provided to the editor in {@link test.publishTestResult},
|
||||
* or read from it in {@link test.testResults}.
|
||||
*
|
||||
* The results contain a 'snapshot' of the tests at the point when the test
|
||||
|
@ -2435,7 +2437,7 @@ declare module 'vscode' {
|
|||
* 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`.
|
||||
* The editor 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.
|
||||
*/
|
||||
|
@ -2450,21 +2452,21 @@ declare module 'vscode' {
|
|||
|
||||
/**
|
||||
* 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.
|
||||
* since the editor always contributes a built-in `Default` opener.
|
||||
*/
|
||||
Option = 1,
|
||||
|
||||
/**
|
||||
* The opener can open the uri.
|
||||
*
|
||||
* VS Code's built-in opener has `Default` priority. This means that any additional `Default`
|
||||
* The editor'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.
|
||||
* default openers, include the built-in one from the editor.
|
||||
*
|
||||
* A preferred opener will be automatically selected if no other preferred openers
|
||||
* are available. If multiple preferred openers are available, then the user
|
||||
|
@ -2477,7 +2479,7 @@ declare module 'vscode' {
|
|||
* 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.
|
||||
* inside of the editor instead of having the link be opened by the web browser.
|
||||
*
|
||||
* Currently openers may only be registered for `http` and `https` uris.
|
||||
*/
|
||||
|
@ -2568,11 +2570,11 @@ declare module 'vscode' {
|
|||
* 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
|
||||
* If `true`, the editor 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
|
||||
* that should be used if it is available. Use `'default'` to force the editor's
|
||||
* standard external opener to be used.
|
||||
*/
|
||||
readonly allowContributedOpeners?: boolean | string;
|
||||
|
@ -2601,7 +2603,7 @@ declare module 'vscode' {
|
|||
*
|
||||
* If the extension is running remotely, this function automatically establishes a port forwarding tunnel
|
||||
* from the local machine to `target` on the remote and returns a local uri to the tunnel. The lifetime of
|
||||
* the port forwarding tunnel is managed by VS Code and the tunnel can be closed by the user.
|
||||
* the port forwarding tunnel is managed by the editor and the tunnel can be closed by the user.
|
||||
*
|
||||
* *Note* that uris passed through `openExternal` are automatically resolved and you should not call `asExternalUri` on them.
|
||||
*
|
||||
|
@ -2638,7 +2640,7 @@ declare module 'vscode' {
|
|||
* #### Any other scheme
|
||||
*
|
||||
* Any other scheme will be handled as if the provided URI is a workspace URI. In that case, the method will return
|
||||
* a URI which, when handled, will make VS Code open the workspace.
|
||||
* a URI which, when handled, will make the editor open the workspace.
|
||||
*
|
||||
* @return A uri that can be used on the client machine.
|
||||
*/
|
||||
|
@ -2730,7 +2732,7 @@ declare module 'vscode' {
|
|||
/**
|
||||
* If your extension listens on ports, consider registering a PortAttributesProvider to provide information
|
||||
* about the ports. For example, a debug extension may know about debug ports in it's debuggee. By providing
|
||||
* this information with a PortAttributesProvider the extension can tell VS Code that these ports should be
|
||||
* this information with a PortAttributesProvider the extension can tell the editor that these ports should be
|
||||
* ignored, since they don't need to be user facing.
|
||||
*
|
||||
* @param portSelector If registerPortAttributesProvider is called after you start your process then you may already
|
||||
|
|
|
@ -22,6 +22,7 @@ import { ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/comm
|
|||
import { IPaneComposite } from 'vs/workbench/common/panecomposite';
|
||||
import { IComposite } from 'vs/workbench/common/composite';
|
||||
import { CompositeDragAndDropData, CompositeDragAndDropObserver, IDraggedCompositeData, ICompositeDragAndDrop, Before2D, toggleDropEffect } from 'vs/workbench/browser/dnd';
|
||||
import { Gesture, EventType as TouchEventType, GestureEvent } from 'vs/base/browser/touch';
|
||||
|
||||
export interface ICompositeBarItem {
|
||||
id: string;
|
||||
|
@ -233,6 +234,8 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
|||
|
||||
// Contextmenu for composites
|
||||
this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, e => this.showContextMenu(e)));
|
||||
this._register(Gesture.addTarget(parent));
|
||||
this._register(addDisposableListener(parent, TouchEventType.Contextmenu, e => this.showContextMenu(e)));
|
||||
|
||||
let insertDropBefore: Before2D | undefined = undefined;
|
||||
// Register a drop target on the whole bar to prevent forbidden feedback
|
||||
|
@ -619,7 +622,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
|||
return this.model.visibleItems.filter(c => overflowingIds.includes(c.id)).map(item => { return { id: item.id, name: this.getAction(item.id)?.label || item.name }; });
|
||||
}
|
||||
|
||||
private showContextMenu(e: MouseEvent): void {
|
||||
private showContextMenu(e: MouseEvent | GestureEvent): void {
|
||||
EventHelper.stop(e, true);
|
||||
const event = new StandardMouseEvent(e);
|
||||
this.contextMenuService.showContextMenu({
|
||||
|
|
|
@ -35,6 +35,7 @@ import { CompositeDragAndDropObserver } from 'vs/workbench/browser/dnd';
|
|||
import { IViewDescriptorService, ViewContainerLocation } from 'vs/workbench/common/views';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { CATEGORIES } from 'vs/workbench/common/actions';
|
||||
import { Gesture, EventType as GestureEventType } from 'vs/base/browser/touch';
|
||||
|
||||
export class SidebarPart extends CompositePart<Viewlet> implements IViewletService {
|
||||
|
||||
|
@ -171,6 +172,10 @@ export class SidebarPart extends CompositePart<Viewlet> implements IViewletServi
|
|||
this._register(addDisposableListener(titleArea, EventType.CONTEXT_MENU, e => {
|
||||
this.onTitleAreaContextMenu(new StandardMouseEvent(e));
|
||||
}));
|
||||
this._register(Gesture.addTarget(titleArea));
|
||||
this._register(addDisposableListener(titleArea, GestureEventType.Contextmenu, e => {
|
||||
this.onTitleAreaContextMenu(new StandardMouseEvent(e));
|
||||
}));
|
||||
|
||||
this.titleLabelElement!.draggable = true;
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import { dispose, IDisposable, Disposable, toDisposable, MutableDisposable } fro
|
|||
import { SimpleIconLabel } from 'vs/base/browser/ui/iconLabel/simpleIconLabel';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { Part } from 'vs/workbench/browser/part';
|
||||
import { EventType as TouchEventType, Gesture, GestureEvent } from 'vs/base/browser/touch';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { StatusbarAlignment, IStatusbarService, IStatusbarEntry, IStatusbarEntryAccessor } from 'vs/workbench/services/statusbar/common/statusbar';
|
||||
|
@ -586,6 +587,8 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
|||
|
||||
// Context menu support
|
||||
this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, e => this.showContextMenu(e)));
|
||||
this._register(Gesture.addTarget(parent));
|
||||
this._register(addDisposableListener(parent, TouchEventType.Contextmenu, e => this.showContextMenu(e)));
|
||||
|
||||
// Initial status bar entries
|
||||
this.createInitialStatusbarEntries();
|
||||
|
@ -660,7 +663,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
|||
}
|
||||
}
|
||||
|
||||
private showContextMenu(e: MouseEvent): void {
|
||||
private showContextMenu(e: MouseEvent | GestureEvent): void {
|
||||
EventHelper.stop(e, true);
|
||||
|
||||
const event = new StandardMouseEvent(e);
|
||||
|
|
|
@ -38,6 +38,7 @@ import { ViewPane } from 'vs/workbench/browser/parts/views/viewPane';
|
|||
import { CompositeMenuActions } from 'vs/workbench/browser/actions';
|
||||
import { createActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Gesture, EventType as TouchEventType } from 'vs/base/browser/touch';
|
||||
|
||||
export const ViewsSubMenu = new MenuId('Views');
|
||||
MenuRegistry.appendMenuItem(MenuId.ViewContainerTitle, <ISubmenuItem>{
|
||||
|
@ -409,6 +410,8 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
|
|||
this._register(this.paneview.onDidDrop(({ from, to }) => this.movePane(from as ViewPane, to as ViewPane)));
|
||||
this._register(this.paneview.onDidScroll(_ => this.onDidScrollPane()));
|
||||
this._register(addDisposableListener(parent, EventType.CONTEXT_MENU, (e: MouseEvent) => this.showContextMenu(new StandardMouseEvent(e))));
|
||||
this._register(Gesture.addTarget(parent));
|
||||
this._register(addDisposableListener(parent, TouchEventType.Contextmenu, (e: MouseEvent) => this.showContextMenu(new StandardMouseEvent(e))));
|
||||
|
||||
this._menuActions = this._register(this.instantiationService.createInstance(ViewContainerMenuActions, this.paneview.element, this.viewContainer));
|
||||
this._register(this._menuActions.onDidChange(() => this.updateTitleArea()));
|
||||
|
|
|
@ -233,9 +233,10 @@ class FormatOnSaveParticipant implements ITextFileSaveParticipant {
|
|||
const nestedProgress = new Progress<{ displayName?: string, extensionId?: ExtensionIdentifier }>(provider => {
|
||||
progress.report({
|
||||
message: localize(
|
||||
'formatting',
|
||||
"Running '{0}' Formatter ([configure](command:workbench.action.openSettings?%5B%22editor.formatOnSave%22%5D)).",
|
||||
provider.displayName || provider.extensionId && provider.extensionId.value || '???'
|
||||
{ key: 'formatting2', comment: ['[configure]({1}) is a link. Only translate `configure`. Do not change brackets and parentheses or {1}'] },
|
||||
"Running '{0}' Formatter ([configure]({1})).",
|
||||
provider.displayName || provider.extensionId && provider.extensionId.value || '???',
|
||||
'command:workbench.action.openSettings?%5B%22editor.formatOnSave%22%5D'
|
||||
)
|
||||
});
|
||||
});
|
||||
|
@ -336,9 +337,10 @@ class CodeActionOnSaveParticipant implements ITextFileSaveParticipant {
|
|||
private _report(): void {
|
||||
progress.report({
|
||||
message: localize(
|
||||
'codeaction.get',
|
||||
"Getting code actions from '{0}' ([configure](command:workbench.action.openSettings?%5B%22editor.codeActionsOnSave%22%5D)).",
|
||||
[...this._names].map(name => `'${name}'`).join(', ')
|
||||
{ key: 'codeaction.get2', comment: ['[configure]({1}) is a link. Only translate `configure`. Do not change brackets and parentheses or {1}'] },
|
||||
"Getting code actions from '{0}' ([configure]({1})).",
|
||||
[...this._names].map(name => `'${name}'`).join(', '),
|
||||
'command:workbench.action.openSettings?%5B%22editor.codeActionsOnSave%22%5D'
|
||||
)
|
||||
});
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ class UntitledTextEditorHintContentWidget implements IContentWidget {
|
|||
this.domNode.style.width = 'max-content';
|
||||
const language = $('a.language-mode');
|
||||
language.style.cursor = 'pointer';
|
||||
language.innerText = localize('selectAlanguage', "Select a language");
|
||||
language.innerText = localize('selectAlanguage2', "Select a language");
|
||||
this.domNode.appendChild(language);
|
||||
const toGetStarted = $('span');
|
||||
toGetStarted.innerText = localize('toGetStarted', " to get started. Start typing to dismiss, or ",);
|
||||
|
|
|
@ -41,7 +41,7 @@ export function filterExceptionsFromTelemetry<T extends { [key: string]: unknown
|
|||
|
||||
|
||||
export function isSessionAttach(session: IDebugSession): boolean {
|
||||
return session.configuration.request === 'attach' && !getExtensionHostDebugSession(session);
|
||||
return session.configuration.request === 'attach' && !getExtensionHostDebugSession(session) && (!session.parentSession || isSessionAttach(session.parentSession));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -487,12 +487,13 @@ export class ExplorerView extends ViewPane {
|
|||
}
|
||||
|
||||
private setContextKeys(stat: ExplorerItem | null | undefined): void {
|
||||
const isSingleFolder = this.contextService.getWorkbenchState() === WorkbenchState.FOLDER;
|
||||
const resource = stat ? stat.resource : isSingleFolder ? this.contextService.getWorkspace().folders[0].uri : null;
|
||||
const folders = this.contextService.getWorkspace().folders;
|
||||
const resource = stat ? stat.resource : folders[folders.length - 1].uri;
|
||||
stat = stat || this.explorerService.findClosest(resource);
|
||||
this.resourceContext.set(resource);
|
||||
this.folderContext.set((isSingleFolder && !stat) || !!stat && stat.isDirectory);
|
||||
this.folderContext.set(!!stat && stat.isDirectory);
|
||||
this.readonlyContext.set(!!stat && stat.isReadonly);
|
||||
this.rootContext.set(!stat || (stat && stat.isRoot));
|
||||
this.rootContext.set(!!stat && stat.isRoot);
|
||||
|
||||
if (resource) {
|
||||
const overrides = resource ? this.editorOverrideService.getEditorIds(resource) : [];
|
||||
|
|
|
@ -1874,14 +1874,18 @@ registerAction2(class NotebookConfigureLayoutAction extends Action2 {
|
|||
group: 'notebookLayout',
|
||||
when: ContextKeyExpr.and(
|
||||
NOTEBOOK_IS_ACTIVE_EDITOR,
|
||||
ContextKeyExpr.notEquals('config.notebook.globalToolbar', true)
|
||||
ContextKeyExpr.notEquals('config.notebook.globalToolbar', true),
|
||||
ContextKeyExpr.equals('config.notebook.experimental.openGettingStarted', true)
|
||||
),
|
||||
order: 0
|
||||
},
|
||||
{
|
||||
id: MenuId.NotebookToolbar,
|
||||
group: 'notebookLayout',
|
||||
when: ContextKeyExpr.equals('config.notebook.globalToolbar', true),
|
||||
when: ContextKeyExpr.and(
|
||||
ContextKeyExpr.equals('config.notebook.globalToolbar', true),
|
||||
ContextKeyExpr.equals('config.notebook.experimental.openGettingStarted', true)
|
||||
),
|
||||
order: 0
|
||||
}
|
||||
]
|
||||
|
|
|
@ -65,7 +65,7 @@ class NotebookViewportContribution extends Disposable implements INotebookEditor
|
|||
if (pickedMimeTypeRenderer.rendererId === BUILTIN_RENDERER_ID) {
|
||||
const renderer = this._notebookEditor.getOutputRenderer().getContribution(pickedMimeTypeRenderer.mimeType);
|
||||
if (renderer?.getType() === RenderOutputType.Html) {
|
||||
const renderResult = renderer.render(output, output.model.outputs.filter(op => op.mime === pickedMimeTypeRenderer.mimeType), DOM.$(''), this._notebookEditor.viewModel.uri) as IInsetRenderOutput;
|
||||
const renderResult = renderer.render(output, output.model.outputs.filter(op => op.mime === pickedMimeTypeRenderer.mimeType)[0], DOM.$(''), this._notebookEditor.viewModel.uri) as IInsetRenderOutput;
|
||||
this._notebookEditor.createOutput(viewCell, renderResult, 0);
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -764,7 +764,7 @@ export interface IOutputTransformContribution {
|
|||
* This call is allowed to have side effects, such as placing output
|
||||
* directly into the container element.
|
||||
*/
|
||||
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput;
|
||||
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput;
|
||||
}
|
||||
|
||||
export interface CellFindMatch {
|
||||
|
|
|
@ -1385,7 +1385,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
}
|
||||
}
|
||||
|
||||
await this._webview!.initializeMarkdown(requests.map(request => ({
|
||||
await this._webview!.initializeMarkup(requests.map(request => ({
|
||||
mime: 'text/markdown',
|
||||
cellId: request[0].id,
|
||||
cellHandle: request[0].handle,
|
||||
content: request[0].getText(),
|
||||
|
@ -1393,8 +1394,10 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
visible: false,
|
||||
})));
|
||||
} else {
|
||||
const initRequests = viewModel.viewCells.filter(cell => cell.cellKind === CellKind.Markup).slice(0, 5).map(cell => ({ cellId: cell.id, cellHandle: cell.handle, content: cell.getText(), offset: -10000, visible: false }));
|
||||
await this._webview!.initializeMarkdown(initRequests);
|
||||
const initRequests = viewModel.viewCells.filter(cell => cell.cellKind === CellKind.Markup).slice(0, 5).map(cell => ({
|
||||
cellId: cell.id, cellHandle: cell.handle, content: cell.getText(), offset: -10000, visible: false, mime: 'text/markdown',
|
||||
}));
|
||||
await this._webview!.initializeMarkup(initRequests);
|
||||
|
||||
// no cached view state so we are rendering the first viewport
|
||||
// after above async call, we already get init height for markdown cells, we can update their offset
|
||||
|
@ -2261,6 +2264,7 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor
|
|||
|
||||
const cellTop = this._list.getAbsoluteTopOfElement(cell);
|
||||
await this._webview.showMarkdownPreview({
|
||||
mime: 'text/markdown',
|
||||
cellHandle: cell.handle,
|
||||
cellId: cell.id,
|
||||
content: cell.getText(),
|
||||
|
|
|
@ -68,6 +68,6 @@ export class OutputRenderer {
|
|||
return this._renderMessage(container, localize('empty', "Cell has no output"));
|
||||
}
|
||||
|
||||
return renderer.render(viewModel, [first], container, notebookUri);
|
||||
return renderer.render(viewModel, first, container, notebookUri);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,13 +39,11 @@ class JavaScriptRendererContrib extends Disposable implements IOutputRendererCon
|
|||
super();
|
||||
}
|
||||
|
||||
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
let scriptVal = '';
|
||||
items.forEach(item => {
|
||||
const str = getStringValue(item);
|
||||
scriptVal += `<script type="application/javascript">${str}</script>`;
|
||||
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
|
||||
const str = getStringValue(item);
|
||||
const scriptVal = `<script type="application/javascript">${str}</script>`;
|
||||
|
||||
});
|
||||
return {
|
||||
type: RenderOutputType.Html,
|
||||
source: output,
|
||||
|
@ -72,8 +70,8 @@ class CodeRendererContrib extends Disposable implements IOutputRendererContribut
|
|||
super();
|
||||
}
|
||||
|
||||
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement): IRenderOutput {
|
||||
const value = items.map(getStringValue).join('');
|
||||
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement): IRenderOutput {
|
||||
const value = getStringValue(item);
|
||||
return this._render(output, container, value, 'javascript');
|
||||
}
|
||||
|
||||
|
@ -106,8 +104,8 @@ class JSONRendererContrib extends CodeRendererContrib {
|
|||
return ['application/json'];
|
||||
}
|
||||
|
||||
override render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement): IRenderOutput {
|
||||
const str = items.map(getStringValue).join('');
|
||||
override render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement): IRenderOutput {
|
||||
const str = getStringValue(item);
|
||||
return this._render(output, container, str, 'jsonc');
|
||||
}
|
||||
}
|
||||
|
@ -130,15 +128,13 @@ class StreamRendererContrib extends Disposable implements IOutputRendererContrib
|
|||
super();
|
||||
}
|
||||
|
||||
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
const linkDetector = this.instantiationService.createInstance(LinkDetector);
|
||||
|
||||
items.forEach(item => {
|
||||
const text = getStringValue(item);
|
||||
const contentNode = DOM.$('span.output-stream');
|
||||
truncatedArrayOfString(notebookUri!, output.cellViewModel, contentNode, [text], linkDetector, this.openerService, this.themeService);
|
||||
container.appendChild(contentNode);
|
||||
});
|
||||
const text = getStringValue(item);
|
||||
const contentNode = DOM.$('span.output-stream');
|
||||
truncatedArrayOfString(notebookUri, output.cellViewModel, contentNode, [text], linkDetector, this.openerService, this.themeService);
|
||||
container.appendChild(contentNode);
|
||||
|
||||
return { type: RenderOutputType.Mainframe };
|
||||
}
|
||||
|
@ -153,8 +149,8 @@ class StderrRendererContrib extends StreamRendererContrib {
|
|||
return ['application/vnd.code.notebook.stderr', 'application/x.notebook.stderr'];
|
||||
}
|
||||
|
||||
override render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
const result = super.render(output, items, container, notebookUri);
|
||||
override render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
const result = super.render(output, item, container, notebookUri);
|
||||
container.classList.add('error');
|
||||
return result;
|
||||
}
|
||||
|
@ -181,35 +177,34 @@ class JSErrorRendererContrib implements IOutputRendererContribution {
|
|||
return ['application/vnd.code.notebook.error'];
|
||||
}
|
||||
|
||||
render(_output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, _notebookUri: URI): IRenderOutput {
|
||||
render(_output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, _notebookUri: URI): IRenderOutput {
|
||||
const linkDetector = this._instantiationService.createInstance(LinkDetector);
|
||||
|
||||
type ErrorLike = Partial<Error>;
|
||||
|
||||
for (let item of items) {
|
||||
let err: ErrorLike;
|
||||
try {
|
||||
err = <ErrorLike>JSON.parse(getStringValue(item));
|
||||
} catch (e) {
|
||||
this._logService.warn('INVALID output item (failed to parse)', e);
|
||||
continue;
|
||||
}
|
||||
|
||||
const header = document.createElement('div');
|
||||
const headerMessage = err.name && err.message ? `${err.name}: ${err.message}` : err.name || err.message;
|
||||
if (headerMessage) {
|
||||
header.innerText = headerMessage;
|
||||
container.appendChild(header);
|
||||
}
|
||||
const stack = document.createElement('pre');
|
||||
stack.classList.add('traceback');
|
||||
if (err.stack) {
|
||||
stack.appendChild(handleANSIOutput(err.stack, linkDetector, this._themeService, undefined));
|
||||
}
|
||||
container.appendChild(stack);
|
||||
container.classList.add('error');
|
||||
let err: ErrorLike;
|
||||
try {
|
||||
err = <ErrorLike>JSON.parse(getStringValue(item));
|
||||
} catch (e) {
|
||||
this._logService.warn('INVALID output item (failed to parse)', e);
|
||||
return { type: RenderOutputType.Mainframe };
|
||||
}
|
||||
|
||||
const header = document.createElement('div');
|
||||
const headerMessage = err.name && err.message ? `${err.name}: ${err.message}` : err.name || err.message;
|
||||
if (headerMessage) {
|
||||
header.innerText = headerMessage;
|
||||
container.appendChild(header);
|
||||
}
|
||||
const stack = document.createElement('pre');
|
||||
stack.classList.add('traceback');
|
||||
if (err.stack) {
|
||||
stack.appendChild(handleANSIOutput(err.stack, linkDetector, this._themeService, undefined));
|
||||
}
|
||||
container.appendChild(stack);
|
||||
container.classList.add('error');
|
||||
|
||||
return { type: RenderOutputType.Mainframe };
|
||||
}
|
||||
}
|
||||
|
@ -232,12 +227,12 @@ class PlainTextRendererContrib extends Disposable implements IOutputRendererCont
|
|||
super();
|
||||
}
|
||||
|
||||
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
const linkDetector = this.instantiationService.createInstance(LinkDetector);
|
||||
|
||||
const str = items.map(getStringValue);
|
||||
const str = getStringValue(item);
|
||||
const contentNode = DOM.$('.output-plaintext');
|
||||
truncatedArrayOfString(notebookUri!, output.cellViewModel, contentNode, str, linkDetector, this.openerService, this.themeService);
|
||||
truncatedArrayOfString(notebookUri, output.cellViewModel, contentNode, [str], linkDetector, this.openerService, this.themeService);
|
||||
container.appendChild(contentNode);
|
||||
|
||||
return { type: RenderOutputType.Mainframe, supportAppend: true };
|
||||
|
@ -259,8 +254,8 @@ class HTMLRendererContrib extends Disposable implements IOutputRendererContribut
|
|||
super();
|
||||
}
|
||||
|
||||
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
const str = items.map(getStringValue).join('');
|
||||
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
const str = getStringValue(item);
|
||||
return {
|
||||
type: RenderOutputType.Html,
|
||||
source: output,
|
||||
|
@ -285,16 +280,14 @@ class MdRendererContrib extends Disposable implements IOutputRendererContributio
|
|||
super();
|
||||
}
|
||||
|
||||
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
const disposable = new DisposableStore();
|
||||
for (let item of items) {
|
||||
const str = getStringValue(item);
|
||||
const mdOutput = document.createElement('div');
|
||||
const mdRenderer = this.instantiationService.createInstance(MarkdownRenderer, { baseUrl: dirname(notebookUri) });
|
||||
mdOutput.appendChild(mdRenderer.render({ value: str, isTrusted: true, supportThemeIcons: true }, undefined, { gfm: true }).element);
|
||||
container.appendChild(mdOutput);
|
||||
disposable.add(mdRenderer);
|
||||
}
|
||||
const str = getStringValue(item);
|
||||
const mdOutput = document.createElement('div');
|
||||
const mdRenderer = this.instantiationService.createInstance(MarkdownRenderer, { baseUrl: dirname(notebookUri) });
|
||||
mdOutput.appendChild(mdRenderer.render({ value: str, isTrusted: true, supportThemeIcons: true }, undefined, { gfm: true }).element);
|
||||
container.appendChild(mdOutput);
|
||||
disposable.add(mdRenderer);
|
||||
return { type: RenderOutputType.Mainframe, disposable };
|
||||
}
|
||||
}
|
||||
|
@ -314,23 +307,21 @@ class ImgRendererContrib extends Disposable implements IOutputRendererContributi
|
|||
super();
|
||||
}
|
||||
|
||||
render(output: ICellOutputViewModel, items: IOutputItemDto[], container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
render(output: ICellOutputViewModel, item: IOutputItemDto, container: HTMLElement, notebookUri: URI): IRenderOutput {
|
||||
const disposable = new DisposableStore();
|
||||
|
||||
for (let item of items) {
|
||||
const bytes = new Uint8Array(item.valueBytes);
|
||||
const blob = new Blob([bytes], { type: item.mime });
|
||||
const src = URL.createObjectURL(blob);
|
||||
disposable.add(toDisposable(() => URL.revokeObjectURL(src)));
|
||||
|
||||
const bytes = new Uint8Array(item.valueBytes);
|
||||
const blob = new Blob([bytes], { type: item.mime });
|
||||
const src = URL.createObjectURL(blob);
|
||||
disposable.add(toDisposable(() => URL.revokeObjectURL(src)));
|
||||
const image = document.createElement('img');
|
||||
image.src = src;
|
||||
const display = document.createElement('div');
|
||||
display.classList.add('display');
|
||||
display.appendChild(image);
|
||||
container.appendChild(display);
|
||||
|
||||
const image = document.createElement('img');
|
||||
image.src = src;
|
||||
const display = document.createElement('div');
|
||||
display.classList.add('display');
|
||||
display.appendChild(image);
|
||||
container.appendChild(display);
|
||||
}
|
||||
return { type: RenderOutputType.Mainframe, disposable };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
|||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { asWebviewUri } from 'vs/workbench/api/common/shared/webview';
|
||||
import { CellEditState, ICellOutputViewModel, ICommonCellInfo, ICommonNotebookEditor, IDisplayOutputLayoutUpdateRequest, IDisplayOutputViewModel, IGenericCellViewModel, IInsetRenderOutput, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { PreloadOptions, preloadsScriptStr, RendererMetadata } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads';
|
||||
import { preloadsScriptStr, RendererMetadata } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads';
|
||||
import { transformWebviewThemeVars } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewThemeMapping';
|
||||
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
|
||||
import { INotebookKernel, INotebookRendererInfo, RendererMessagingSpec } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
|
@ -34,368 +34,7 @@ import { IScopedRendererMessaging } from 'vs/workbench/contrib/notebook/common/n
|
|||
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { IWebviewService, WebviewContentPurpose, WebviewElement } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
|
||||
interface BaseToWebviewMessage {
|
||||
readonly __vscode_notebook_message: true;
|
||||
}
|
||||
|
||||
export interface WebviewIntialized extends BaseToWebviewMessage {
|
||||
type: 'initialized';
|
||||
}
|
||||
|
||||
export interface DimensionUpdate {
|
||||
id: string;
|
||||
init?: boolean;
|
||||
height: number;
|
||||
isOutput?: boolean;
|
||||
}
|
||||
|
||||
export interface IDimensionMessage extends BaseToWebviewMessage {
|
||||
type: 'dimension';
|
||||
updates: readonly DimensionUpdate[];
|
||||
}
|
||||
|
||||
export interface IMouseEnterMessage extends BaseToWebviewMessage {
|
||||
type: 'mouseenter';
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface IMouseLeaveMessage extends BaseToWebviewMessage {
|
||||
type: 'mouseleave';
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface IOutputFocusMessage extends BaseToWebviewMessage {
|
||||
type: 'outputFocus';
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface IOutputBlurMessage extends BaseToWebviewMessage {
|
||||
type: 'outputBlur';
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface IWheelMessage extends BaseToWebviewMessage {
|
||||
type: 'did-scroll-wheel';
|
||||
payload: any;
|
||||
}
|
||||
|
||||
export interface IScrollAckMessage extends BaseToWebviewMessage {
|
||||
type: 'scroll-ack';
|
||||
data: { top: number };
|
||||
version: number;
|
||||
}
|
||||
|
||||
export interface IBlurOutputMessage extends BaseToWebviewMessage {
|
||||
type: 'focus-editor';
|
||||
id: string;
|
||||
focusNext?: boolean;
|
||||
}
|
||||
|
||||
export interface IClickedDataUrlMessage extends BaseToWebviewMessage {
|
||||
type: 'clicked-data-url';
|
||||
data: string | ArrayBuffer | null;
|
||||
downloadName?: string;
|
||||
}
|
||||
|
||||
export interface IClickMarkdownPreviewMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'clickMarkdownPreview';
|
||||
readonly cellId: string;
|
||||
readonly ctrlKey: boolean
|
||||
readonly altKey: boolean;
|
||||
readonly metaKey: boolean;
|
||||
readonly shiftKey: boolean;
|
||||
}
|
||||
|
||||
export interface IContextMenuMarkdownPreviewMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'contextMenuMarkdownPreview';
|
||||
readonly cellId: string;
|
||||
readonly clientX: number;
|
||||
readonly clientY: number;
|
||||
}
|
||||
|
||||
export interface IMouseEnterMarkdownPreviewMessage extends BaseToWebviewMessage {
|
||||
type: 'mouseEnterMarkdownPreview';
|
||||
cellId: string;
|
||||
}
|
||||
|
||||
export interface IMouseLeaveMarkdownPreviewMessage extends BaseToWebviewMessage {
|
||||
type: 'mouseLeaveMarkdownPreview';
|
||||
cellId: string;
|
||||
}
|
||||
|
||||
export interface IToggleMarkdownPreviewMessage extends BaseToWebviewMessage {
|
||||
type: 'toggleMarkdownPreview';
|
||||
cellId: string;
|
||||
}
|
||||
|
||||
export interface ICellDragStartMessage extends BaseToWebviewMessage {
|
||||
type: 'cell-drag-start';
|
||||
readonly cellId: string;
|
||||
readonly dragOffsetY: number;
|
||||
}
|
||||
|
||||
export interface ICellDragMessage extends BaseToWebviewMessage {
|
||||
type: 'cell-drag';
|
||||
readonly cellId: string;
|
||||
readonly dragOffsetY: number;
|
||||
}
|
||||
|
||||
export interface ICellDropMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'cell-drop';
|
||||
readonly cellId: string;
|
||||
readonly ctrlKey: boolean
|
||||
readonly altKey: boolean;
|
||||
readonly dragOffsetY: number;
|
||||
}
|
||||
|
||||
export interface ICellDragEndMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'cell-drag-end';
|
||||
readonly cellId: string;
|
||||
}
|
||||
|
||||
export interface IInitializedMarkdownPreviewMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'initializedMarkdownPreview';
|
||||
}
|
||||
|
||||
export interface ITelemetryFoundRenderedMarkdownMath extends BaseToWebviewMessage {
|
||||
readonly type: 'telemetryFoundRenderedMarkdownMath';
|
||||
}
|
||||
|
||||
export interface ITelemetryFoundUnrenderedMarkdownMath extends BaseToWebviewMessage {
|
||||
readonly type: 'telemetryFoundUnrenderedMarkdownMath';
|
||||
readonly latexDirective: string;
|
||||
}
|
||||
|
||||
export interface IClearMessage {
|
||||
type: 'clear';
|
||||
}
|
||||
|
||||
export interface IOutputRequestMetadata {
|
||||
/**
|
||||
* Additional attributes of a cell metadata.
|
||||
*/
|
||||
custom?: { [key: string]: unknown };
|
||||
}
|
||||
|
||||
export interface IOutputRequestDto {
|
||||
/**
|
||||
* { mime_type: value }
|
||||
*/
|
||||
data: { [key: string]: unknown; }
|
||||
|
||||
metadata?: IOutputRequestMetadata;
|
||||
outputId: string;
|
||||
}
|
||||
|
||||
export interface ICreationRequestMessage {
|
||||
type: 'html';
|
||||
content:
|
||||
| { type: RenderOutputType.Html; htmlContent: string }
|
||||
| { type: RenderOutputType.Extension; outputId: string; valueBytes: Uint8Array, metadata: unknown; metadata2: unknown, mimeType: string };
|
||||
cellId: string;
|
||||
outputId: string;
|
||||
cellTop: number;
|
||||
outputOffset: number;
|
||||
left: number;
|
||||
requiredPreloads: ReadonlyArray<IControllerPreload>;
|
||||
readonly initiallyHidden?: boolean;
|
||||
rendererId?: string | undefined;
|
||||
}
|
||||
|
||||
export interface IContentWidgetTopRequest {
|
||||
outputId: string;
|
||||
cellTop: number;
|
||||
outputOffset: number;
|
||||
forceDisplay: boolean;
|
||||
}
|
||||
|
||||
export interface IViewScrollTopRequestMessage {
|
||||
type: 'view-scroll';
|
||||
widgets: IContentWidgetTopRequest[];
|
||||
markdownPreviews: { id: string; top: number }[];
|
||||
}
|
||||
|
||||
export interface IScrollRequestMessage {
|
||||
type: 'scroll';
|
||||
id: string;
|
||||
top: number;
|
||||
widgetTop?: number;
|
||||
version: number;
|
||||
}
|
||||
|
||||
export interface IClearOutputRequestMessage {
|
||||
type: 'clearOutput';
|
||||
cellId: string;
|
||||
outputId: string;
|
||||
cellUri: string;
|
||||
rendererId: string | undefined;
|
||||
}
|
||||
|
||||
export interface IHideOutputMessage {
|
||||
type: 'hideOutput';
|
||||
outputId: string;
|
||||
cellId: string;
|
||||
}
|
||||
|
||||
export interface IShowOutputMessage {
|
||||
type: 'showOutput';
|
||||
cellId: string;
|
||||
outputId: string;
|
||||
cellTop: number;
|
||||
outputOffset: number;
|
||||
}
|
||||
|
||||
export interface IFocusOutputMessage {
|
||||
type: 'focus-output';
|
||||
cellId: string;
|
||||
}
|
||||
|
||||
export interface IAckOutputHeightMessage {
|
||||
type: 'ack-dimension',
|
||||
cellId: string;
|
||||
outputId: string;
|
||||
height: number;
|
||||
}
|
||||
|
||||
|
||||
export interface IControllerPreload {
|
||||
originalUri: string;
|
||||
uri: string;
|
||||
}
|
||||
|
||||
export interface IUpdateControllerPreloadsMessage {
|
||||
type: 'preload';
|
||||
resources: IControllerPreload[];
|
||||
}
|
||||
|
||||
export interface IUpdateDecorationsMessage {
|
||||
type: 'decorations';
|
||||
cellId: string;
|
||||
addedClassNames: string[];
|
||||
removedClassNames: string[];
|
||||
}
|
||||
|
||||
export interface ICustomKernelMessage extends BaseToWebviewMessage {
|
||||
type: 'customKernelMessage';
|
||||
message: unknown;
|
||||
}
|
||||
|
||||
export interface ICustomRendererMessage extends BaseToWebviewMessage {
|
||||
type: 'customRendererMessage';
|
||||
rendererId: string;
|
||||
message: unknown;
|
||||
}
|
||||
|
||||
export interface ICreateMarkdownMessage {
|
||||
type: 'createMarkdownPreview',
|
||||
cell: IMarkdownCellInitialization;
|
||||
}
|
||||
export interface IDeleteMarkdownMessage {
|
||||
type: 'deleteMarkdownPreview',
|
||||
ids: readonly string[];
|
||||
}
|
||||
|
||||
export interface IHideMarkdownMessage {
|
||||
type: 'hideMarkdownPreviews';
|
||||
ids: readonly string[];
|
||||
}
|
||||
|
||||
export interface IUnhideMarkdownMessage {
|
||||
type: 'unhideMarkdownPreviews';
|
||||
ids: readonly string[];
|
||||
}
|
||||
|
||||
export interface IShowMarkdownMessage {
|
||||
type: 'showMarkdownPreview',
|
||||
id: string;
|
||||
handle: number;
|
||||
content: string | undefined;
|
||||
top: number;
|
||||
}
|
||||
|
||||
export interface IUpdateSelectedMarkdownPreviews {
|
||||
readonly type: 'updateSelectedMarkdownPreviews',
|
||||
readonly selectedCellIds: readonly string[]
|
||||
}
|
||||
|
||||
export interface IMarkdownCellInitialization {
|
||||
cellId: string;
|
||||
cellHandle: number;
|
||||
content: string;
|
||||
offset: number;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
export interface IInitializeMarkdownMessage {
|
||||
type: 'initializeMarkdownPreview';
|
||||
cells: ReadonlyArray<IMarkdownCellInitialization>;
|
||||
}
|
||||
|
||||
export interface INotebookStylesMessage {
|
||||
type: 'notebookStyles';
|
||||
styles: {
|
||||
[key: string]: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface INotebookOptionsMessage {
|
||||
type: 'notebookOptions';
|
||||
options: PreloadOptions;
|
||||
}
|
||||
|
||||
export type FromWebviewMessage =
|
||||
| WebviewIntialized
|
||||
| IDimensionMessage
|
||||
| IMouseEnterMessage
|
||||
| IMouseLeaveMessage
|
||||
| IOutputFocusMessage
|
||||
| IOutputBlurMessage
|
||||
| IWheelMessage
|
||||
| IScrollAckMessage
|
||||
| IBlurOutputMessage
|
||||
| ICustomKernelMessage
|
||||
| ICustomRendererMessage
|
||||
| IClickedDataUrlMessage
|
||||
| IClickMarkdownPreviewMessage
|
||||
| IContextMenuMarkdownPreviewMessage
|
||||
| IMouseEnterMarkdownPreviewMessage
|
||||
| IMouseLeaveMarkdownPreviewMessage
|
||||
| IToggleMarkdownPreviewMessage
|
||||
| ICellDragStartMessage
|
||||
| ICellDragMessage
|
||||
| ICellDropMessage
|
||||
| ICellDragEndMessage
|
||||
| IInitializedMarkdownPreviewMessage
|
||||
| ITelemetryFoundRenderedMarkdownMath
|
||||
| ITelemetryFoundUnrenderedMarkdownMath
|
||||
;
|
||||
|
||||
export type ToWebviewMessage =
|
||||
| IClearMessage
|
||||
| IFocusOutputMessage
|
||||
| IAckOutputHeightMessage
|
||||
| ICreationRequestMessage
|
||||
| IViewScrollTopRequestMessage
|
||||
| IScrollRequestMessage
|
||||
| IClearOutputRequestMessage
|
||||
| IHideOutputMessage
|
||||
| IShowOutputMessage
|
||||
| IUpdateControllerPreloadsMessage
|
||||
| IUpdateDecorationsMessage
|
||||
| ICustomKernelMessage
|
||||
| ICustomRendererMessage
|
||||
| ICreateMarkdownMessage
|
||||
| IDeleteMarkdownMessage
|
||||
| IShowMarkdownMessage
|
||||
| IHideMarkdownMessage
|
||||
| IUnhideMarkdownMessage
|
||||
| IUpdateSelectedMarkdownPreviews
|
||||
| IInitializeMarkdownMessage
|
||||
| INotebookStylesMessage
|
||||
| INotebookOptionsMessage;
|
||||
|
||||
export type AnyMessage = FromWebviewMessage | ToWebviewMessage;
|
||||
import { ICreationRequestMessage, IMarkupCellInitialization, FromWebviewMessage, IClickedDataUrlMessage, IContentWidgetTopRequest, IControllerPreload, ToWebviewMessage } from './webviewMessages';
|
||||
|
||||
export interface ICachedInset<K extends ICommonCellInfo> {
|
||||
outputId: string;
|
||||
|
@ -424,7 +63,7 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
|
|||
element: HTMLElement;
|
||||
webview: WebviewElement | undefined = undefined;
|
||||
insetMapping: Map<IDisplayOutputViewModel, ICachedInset<T>> = new Map();
|
||||
readonly markdownPreviewMapping = new Map<string, IMarkdownCellInitialization>();
|
||||
readonly markdownPreviewMapping = new Map<string, IMarkupCellInitialization>();
|
||||
hiddenInsetMapping: Set<IDisplayOutputViewModel> = new Set();
|
||||
reversedInsetMapping: Map<string, IDisplayOutputViewModel> = new Map();
|
||||
localResourceRootsCache: URI[] | undefined = undefined;
|
||||
|
@ -525,7 +164,8 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
|
|||
'notebook-markdown-left-margin': `${this.options.markdownLeftMargin}px`,
|
||||
'notebook-output-node-left-padding': `${this.options.outputNodeLeftPadding}px`,
|
||||
'notebook-markdown-min-height': `${this.options.previewNodePadding * 2}px`,
|
||||
'notebook-cell-output-font-size': `${this.options.fontSize}px`
|
||||
'notebook-cell-output-font-size': `${this.options.fontSize}px`,
|
||||
'notebook-cell-markup-empty-content': nls.localize('notebook.emptyMarkdownPlaceholder', "Empty markdown cell, double click or press enter to edit."),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -536,134 +176,6 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<base href="${baseUrl}/"/>
|
||||
|
||||
<!--
|
||||
Markdown previews are rendered using a shadow dom and are not effected by normal css.
|
||||
Insert this style node into all preview shadow doms for styling.
|
||||
-->
|
||||
<template id="preview-styles">
|
||||
<style>
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:focus,
|
||||
input:focus,
|
||||
select:focus,
|
||||
textarea:focus {
|
||||
outline: 1px solid -webkit-focus-ring-color;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
height: 2px;
|
||||
border-bottom: 2px solid;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 26px;
|
||||
line-height: 31px;
|
||||
margin: 0;
|
||||
margin-bottom: 13px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 19px;
|
||||
margin: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
div {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Adjust margin of first item in markdown cell */
|
||||
*:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
/* h1 tags don't need top margin */
|
||||
h1:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Removes bottom margin when only one item exists in markdown cell */
|
||||
*:only-child,
|
||||
*:last-child {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
/* makes all markdown cells consistent */
|
||||
div {
|
||||
min-height: var(--notebook-markdown-min-height);
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
table th,
|
||||
table td {
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
table > thead > tr > th {
|
||||
text-align: left;
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
|
||||
table > thead > tr > th,
|
||||
table > thead > tr > td,
|
||||
table > tbody > tr > th,
|
||||
table > tbody > tr > td {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
table > tbody > tr + tr > td {
|
||||
border-top: 1px solid;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 7px 0 5px;
|
||||
padding: 0 16px 0 10px;
|
||||
border-left-width: 5px;
|
||||
border-left-style: solid;
|
||||
}
|
||||
|
||||
code,
|
||||
.code {
|
||||
font-family: var(--monaco-monospace-font);
|
||||
font-size: 1em;
|
||||
line-height: 1.357em;
|
||||
}
|
||||
|
||||
.code {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
dragging {
|
||||
background-color: var(--theme-background);
|
||||
}
|
||||
</style>
|
||||
</template>
|
||||
<style>
|
||||
#container .cell_container {
|
||||
width: 100%;
|
||||
|
@ -707,12 +219,6 @@ export class BackLayerWebView<T extends ICommonCellInfo> extends Disposable {
|
|||
cursor: grab;
|
||||
}
|
||||
|
||||
#container > div.preview.emptyMarkdownCell::before {
|
||||
content: "${nls.localize('notebook.emptyMarkdownPlaceholder', "Empty markdown cell, double click or press enter to edit.")}";
|
||||
font-style: italic;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
#container > div.preview.selected {
|
||||
background: var(--theme-notebook-cell-selected-background);
|
||||
}
|
||||
|
@ -1049,7 +555,7 @@ var requirejs = (function() {
|
|||
this.rendererMessaging?.postMessage(data.rendererId, data.message);
|
||||
break;
|
||||
}
|
||||
case 'clickMarkdownPreview':
|
||||
case 'clickMarkupCell':
|
||||
{
|
||||
const cell = this.notebookEditor.getCellById(data.cellId);
|
||||
if (cell) {
|
||||
|
@ -1063,7 +569,7 @@ var requirejs = (function() {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 'contextMenuMarkdownPreview':
|
||||
case 'contextMenuMarkupCell':
|
||||
{
|
||||
const cell = this.notebookEditor.getCellById(data.cellId);
|
||||
if (cell) {
|
||||
|
@ -1088,7 +594,7 @@ var requirejs = (function() {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 'toggleMarkdownPreview':
|
||||
case 'toggleMarkupPreview':
|
||||
{
|
||||
const cell = this.notebookEditor.getCellById(data.cellId);
|
||||
if (cell) {
|
||||
|
@ -1097,7 +603,7 @@ var requirejs = (function() {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 'mouseEnterMarkdownPreview':
|
||||
case 'mouseEnterMarkupCell':
|
||||
{
|
||||
const cell = this.notebookEditor.getCellById(data.cellId);
|
||||
if (cell instanceof MarkdownCellViewModel) {
|
||||
|
@ -1105,7 +611,7 @@ var requirejs = (function() {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 'mouseLeaveMarkdownPreview':
|
||||
case 'mouseLeaveMarkupCell':
|
||||
{
|
||||
const cell = this.notebookEditor.getCellById(data.cellId);
|
||||
if (cell instanceof MarkdownCellViewModel) {
|
||||
|
@ -1246,7 +752,7 @@ var requirejs = (function() {
|
|||
|
||||
const mdCells = [...this.markdownPreviewMapping.values()];
|
||||
this.markdownPreviewMapping.clear();
|
||||
this.initializeMarkdown(mdCells);
|
||||
this.initializeMarkup(mdCells);
|
||||
this._updateStyles();
|
||||
this._updateOptions();
|
||||
}
|
||||
|
@ -1324,7 +830,7 @@ var requirejs = (function() {
|
|||
});
|
||||
}
|
||||
|
||||
private async createMarkdownPreview(initialization: IMarkdownCellInitialization) {
|
||||
private async createMarkdownPreview(initialization: IMarkupCellInitialization) {
|
||||
if (this._disposed) {
|
||||
return;
|
||||
}
|
||||
|
@ -1336,12 +842,12 @@ var requirejs = (function() {
|
|||
|
||||
this.markdownPreviewMapping.set(initialization.cellId, initialization);
|
||||
this._sendMessageToWebview({
|
||||
type: 'createMarkdownPreview',
|
||||
type: 'createMarkupCell',
|
||||
cell: initialization
|
||||
});
|
||||
}
|
||||
|
||||
async showMarkdownPreview(initialization: IMarkdownCellInitialization) {
|
||||
async showMarkdownPreview(initialization: IMarkupCellInitialization) {
|
||||
if (this._disposed) {
|
||||
return;
|
||||
}
|
||||
|
@ -1354,7 +860,7 @@ var requirejs = (function() {
|
|||
const sameContent = initialization.content === entry.content;
|
||||
if (!sameContent || !entry.visible) {
|
||||
this._sendMessageToWebview({
|
||||
type: 'showMarkdownPreview',
|
||||
type: 'showMarkupCell',
|
||||
id: initialization.cellId,
|
||||
handle: initialization.cellHandle,
|
||||
// If the content has not changed, we still want to make sure the
|
||||
|
@ -1387,7 +893,7 @@ var requirejs = (function() {
|
|||
|
||||
if (cellsToHide.length) {
|
||||
this._sendMessageToWebview({
|
||||
type: 'hideMarkdownPreviews',
|
||||
type: 'hideMarkupCells',
|
||||
ids: cellsToHide
|
||||
});
|
||||
}
|
||||
|
@ -1412,7 +918,7 @@ var requirejs = (function() {
|
|||
}
|
||||
|
||||
this._sendMessageToWebview({
|
||||
type: 'unhideMarkdownPreviews',
|
||||
type: 'unhideMarkupCells',
|
||||
ids: toUnhide,
|
||||
});
|
||||
}
|
||||
|
@ -1431,7 +937,7 @@ var requirejs = (function() {
|
|||
|
||||
if (cellIds.length) {
|
||||
this._sendMessageToWebview({
|
||||
type: 'deleteMarkdownPreview',
|
||||
type: 'deleteMarkupCell',
|
||||
ids: cellIds
|
||||
});
|
||||
}
|
||||
|
@ -1443,12 +949,12 @@ var requirejs = (function() {
|
|||
}
|
||||
|
||||
this._sendMessageToWebview({
|
||||
type: 'updateSelectedMarkdownPreviews',
|
||||
type: 'updateSelectedMarkupCells',
|
||||
selectedCellIds: selectedCellsIds.filter(id => this.markdownPreviewMapping.has(id)),
|
||||
});
|
||||
}
|
||||
|
||||
async initializeMarkdown(cells: ReadonlyArray<IMarkdownCellInitialization>) {
|
||||
async initializeMarkup(cells: readonly IMarkupCellInitialization[]) {
|
||||
if (this._disposed) {
|
||||
return;
|
||||
}
|
||||
|
@ -1456,7 +962,7 @@ var requirejs = (function() {
|
|||
// TODO: use proper handler
|
||||
const p = new Promise<void>(resolve => {
|
||||
this.webview?.onMessage(e => {
|
||||
if (e.message.type === 'initializedMarkdownPreview') {
|
||||
if (e.message.type === 'initializedMarkup') {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
@ -1467,7 +973,7 @@ var requirejs = (function() {
|
|||
}
|
||||
|
||||
this._sendMessageToWebview({
|
||||
type: 'initializeMarkdownPreview',
|
||||
type: 'initializeMarkup',
|
||||
cells,
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,366 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import type { RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import type { PreloadOptions } from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads';
|
||||
|
||||
interface BaseToWebviewMessage {
|
||||
readonly __vscode_notebook_message: true;
|
||||
}
|
||||
|
||||
export interface WebviewIntialized extends BaseToWebviewMessage {
|
||||
readonly type: 'initialized';
|
||||
}
|
||||
|
||||
export interface DimensionUpdate {
|
||||
readonly id: string;
|
||||
readonly init?: boolean;
|
||||
readonly height: number;
|
||||
readonly isOutput?: boolean;
|
||||
}
|
||||
|
||||
export interface IDimensionMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'dimension';
|
||||
readonly updates: readonly DimensionUpdate[];
|
||||
}
|
||||
|
||||
export interface IMouseEnterMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'mouseenter';
|
||||
readonly id: string;
|
||||
}
|
||||
|
||||
export interface IMouseLeaveMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'mouseleave';
|
||||
readonly id: string;
|
||||
}
|
||||
|
||||
export interface IOutputFocusMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'outputFocus';
|
||||
readonly id: string;
|
||||
}
|
||||
|
||||
export interface IOutputBlurMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'outputBlur';
|
||||
readonly id: string;
|
||||
}
|
||||
|
||||
export interface IWheelMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'did-scroll-wheel';
|
||||
readonly payload: any;
|
||||
}
|
||||
|
||||
export interface IScrollAckMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'scroll-ack';
|
||||
readonly data: { top: number; };
|
||||
readonly version: number;
|
||||
}
|
||||
|
||||
export interface IBlurOutputMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'focus-editor';
|
||||
readonly id: string;
|
||||
readonly focusNext?: boolean;
|
||||
}
|
||||
|
||||
export interface IClickedDataUrlMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'clicked-data-url';
|
||||
readonly data: string | ArrayBuffer | null;
|
||||
readonly downloadName?: string;
|
||||
}
|
||||
|
||||
export interface IClickMarkupCellMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'clickMarkupCell';
|
||||
readonly cellId: string;
|
||||
readonly ctrlKey: boolean;
|
||||
readonly altKey: boolean;
|
||||
readonly metaKey: boolean;
|
||||
readonly shiftKey: boolean;
|
||||
}
|
||||
|
||||
export interface IContextMenuMarkupCellMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'contextMenuMarkupCell';
|
||||
readonly cellId: string;
|
||||
readonly clientX: number;
|
||||
readonly clientY: number;
|
||||
}
|
||||
|
||||
export interface IMouseEnterMarkupCellMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'mouseEnterMarkupCell';
|
||||
readonly cellId: string;
|
||||
}
|
||||
|
||||
export interface IMouseLeaveMarkupCellMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'mouseLeaveMarkupCell';
|
||||
readonly cellId: string;
|
||||
}
|
||||
|
||||
export interface IToggleMarkupPreviewMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'toggleMarkupPreview';
|
||||
readonly cellId: string;
|
||||
}
|
||||
|
||||
export interface ICellDragStartMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'cell-drag-start';
|
||||
readonly cellId: string;
|
||||
readonly dragOffsetY: number;
|
||||
}
|
||||
|
||||
export interface ICellDragMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'cell-drag';
|
||||
readonly cellId: string;
|
||||
readonly dragOffsetY: number;
|
||||
}
|
||||
|
||||
export interface ICellDropMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'cell-drop';
|
||||
readonly cellId: string;
|
||||
readonly ctrlKey: boolean;
|
||||
readonly altKey: boolean;
|
||||
readonly dragOffsetY: number;
|
||||
}
|
||||
|
||||
export interface ICellDragEndMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'cell-drag-end';
|
||||
readonly cellId: string;
|
||||
}
|
||||
|
||||
export interface IInitializedMarkupMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'initializedMarkup';
|
||||
}
|
||||
|
||||
export interface ITelemetryFoundRenderedMarkdownMath extends BaseToWebviewMessage {
|
||||
readonly type: 'telemetryFoundRenderedMarkdownMath';
|
||||
}
|
||||
|
||||
export interface ITelemetryFoundUnrenderedMarkdownMath extends BaseToWebviewMessage {
|
||||
readonly type: 'telemetryFoundUnrenderedMarkdownMath';
|
||||
readonly latexDirective: string;
|
||||
}
|
||||
|
||||
export interface IClearMessage {
|
||||
readonly type: 'clear';
|
||||
}
|
||||
|
||||
export interface IOutputRequestMetadata {
|
||||
/**
|
||||
* Additional attributes of a cell metadata.
|
||||
*/
|
||||
readonly custom?: { [key: string]: unknown; };
|
||||
}
|
||||
|
||||
export interface IOutputRequestDto {
|
||||
/**
|
||||
* { mime_type: value }
|
||||
*/
|
||||
readonly data: { [key: string]: unknown; };
|
||||
|
||||
readonly metadata?: IOutputRequestMetadata;
|
||||
readonly outputId: string;
|
||||
}
|
||||
|
||||
export interface ICreationRequestMessage {
|
||||
readonly type: 'html';
|
||||
readonly content: { type: RenderOutputType.Html; htmlContent: string; } |
|
||||
{ type: RenderOutputType.Extension; outputId: string; valueBytes: Uint8Array; metadata: unknown; metadata2: unknown; mimeType: string; };
|
||||
readonly cellId: string;
|
||||
readonly outputId: string;
|
||||
cellTop: number;
|
||||
outputOffset: number;
|
||||
readonly left: number;
|
||||
readonly requiredPreloads: ReadonlyArray<IControllerPreload>;
|
||||
readonly initiallyHidden?: boolean;
|
||||
readonly rendererId?: string | undefined;
|
||||
}
|
||||
|
||||
export interface IContentWidgetTopRequest {
|
||||
readonly outputId: string;
|
||||
readonly cellTop: number;
|
||||
readonly outputOffset: number;
|
||||
readonly forceDisplay: boolean;
|
||||
}
|
||||
|
||||
export interface IViewScrollTopRequestMessage {
|
||||
readonly type: 'view-scroll';
|
||||
readonly widgets: IContentWidgetTopRequest[];
|
||||
readonly markdownPreviews: { id: string; top: number; }[];
|
||||
}
|
||||
|
||||
export interface IScrollRequestMessage {
|
||||
readonly type: 'scroll';
|
||||
readonly id: string;
|
||||
readonly top: number;
|
||||
readonly widgetTop?: number;
|
||||
readonly version: number;
|
||||
}
|
||||
|
||||
export interface IClearOutputRequestMessage {
|
||||
readonly type: 'clearOutput';
|
||||
readonly cellId: string;
|
||||
readonly outputId: string;
|
||||
readonly cellUri: string;
|
||||
readonly rendererId: string | undefined;
|
||||
}
|
||||
|
||||
export interface IHideOutputMessage {
|
||||
readonly type: 'hideOutput';
|
||||
readonly outputId: string;
|
||||
readonly cellId: string;
|
||||
}
|
||||
|
||||
export interface IShowOutputMessage {
|
||||
readonly type: 'showOutput';
|
||||
readonly cellId: string;
|
||||
readonly outputId: string;
|
||||
readonly cellTop: number;
|
||||
readonly outputOffset: number;
|
||||
}
|
||||
|
||||
export interface IFocusOutputMessage {
|
||||
readonly type: 'focus-output';
|
||||
readonly cellId: string;
|
||||
}
|
||||
|
||||
export interface IAckOutputHeightMessage {
|
||||
readonly type: 'ack-dimension';
|
||||
readonly cellId: string;
|
||||
readonly outputId: string;
|
||||
readonly height: number;
|
||||
}
|
||||
|
||||
export interface IControllerPreload {
|
||||
readonly originalUri: string;
|
||||
readonly uri: string;
|
||||
}
|
||||
|
||||
export interface IUpdateControllerPreloadsMessage {
|
||||
readonly type: 'preload';
|
||||
readonly resources: IControllerPreload[];
|
||||
}
|
||||
|
||||
export interface IUpdateDecorationsMessage {
|
||||
readonly type: 'decorations';
|
||||
readonly cellId: string;
|
||||
readonly addedClassNames: string[];
|
||||
readonly removedClassNames: string[];
|
||||
}
|
||||
|
||||
export interface ICustomKernelMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'customKernelMessage';
|
||||
readonly message: unknown;
|
||||
}
|
||||
|
||||
export interface ICustomRendererMessage extends BaseToWebviewMessage {
|
||||
readonly type: 'customRendererMessage';
|
||||
readonly rendererId: string;
|
||||
readonly message: unknown;
|
||||
}
|
||||
|
||||
export interface ICreateMarkupCellMessage {
|
||||
readonly type: 'createMarkupCell';
|
||||
readonly cell: IMarkupCellInitialization;
|
||||
}
|
||||
|
||||
export interface IDeleteMarkupCellMessage {
|
||||
readonly type: 'deleteMarkupCell';
|
||||
readonly ids: readonly string[];
|
||||
}
|
||||
|
||||
export interface IHideMarkupCellMessage {
|
||||
readonly type: 'hideMarkupCells';
|
||||
readonly ids: readonly string[];
|
||||
}
|
||||
|
||||
export interface IUnhideMarkupCellMessage {
|
||||
readonly type: 'unhideMarkupCells';
|
||||
readonly ids: readonly string[];
|
||||
}
|
||||
|
||||
export interface IShowMarkupCellMessage {
|
||||
readonly type: 'showMarkupCell';
|
||||
readonly id: string;
|
||||
readonly handle: number;
|
||||
readonly content: string | undefined;
|
||||
readonly top: number;
|
||||
}
|
||||
|
||||
export interface IUpdateSelectedMarkupCellsMessage {
|
||||
readonly type: 'updateSelectedMarkupCells';
|
||||
readonly selectedCellIds: readonly string[];
|
||||
}
|
||||
|
||||
export interface IMarkupCellInitialization {
|
||||
mime: string;
|
||||
cellId: string;
|
||||
cellHandle: number;
|
||||
content: string;
|
||||
offset: number;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
export interface IInitializeMarkupCells {
|
||||
readonly type: 'initializeMarkup';
|
||||
readonly cells: ReadonlyArray<IMarkupCellInitialization>;
|
||||
}
|
||||
|
||||
export interface INotebookStylesMessage {
|
||||
readonly type: 'notebookStyles';
|
||||
readonly styles: {
|
||||
[key: string]: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface INotebookOptionsMessage {
|
||||
readonly type: 'notebookOptions';
|
||||
readonly options: PreloadOptions;
|
||||
}
|
||||
|
||||
export type FromWebviewMessage = WebviewIntialized |
|
||||
IDimensionMessage |
|
||||
IMouseEnterMessage |
|
||||
IMouseLeaveMessage |
|
||||
IOutputFocusMessage |
|
||||
IOutputBlurMessage |
|
||||
IWheelMessage |
|
||||
IScrollAckMessage |
|
||||
IBlurOutputMessage |
|
||||
ICustomKernelMessage |
|
||||
ICustomRendererMessage |
|
||||
IClickedDataUrlMessage |
|
||||
IClickMarkupCellMessage |
|
||||
IContextMenuMarkupCellMessage |
|
||||
IMouseEnterMarkupCellMessage |
|
||||
IMouseLeaveMarkupCellMessage |
|
||||
IToggleMarkupPreviewMessage |
|
||||
ICellDragStartMessage |
|
||||
ICellDragMessage |
|
||||
ICellDropMessage |
|
||||
ICellDragEndMessage |
|
||||
IInitializedMarkupMessage |
|
||||
ITelemetryFoundRenderedMarkdownMath |
|
||||
ITelemetryFoundUnrenderedMarkdownMath;
|
||||
|
||||
export type ToWebviewMessage = IClearMessage |
|
||||
IFocusOutputMessage |
|
||||
IAckOutputHeightMessage |
|
||||
ICreationRequestMessage |
|
||||
IViewScrollTopRequestMessage |
|
||||
IScrollRequestMessage |
|
||||
IClearOutputRequestMessage |
|
||||
IHideOutputMessage |
|
||||
IShowOutputMessage |
|
||||
IUpdateControllerPreloadsMessage |
|
||||
IUpdateDecorationsMessage |
|
||||
ICustomKernelMessage |
|
||||
ICustomRendererMessage |
|
||||
ICreateMarkupCellMessage |
|
||||
IDeleteMarkupCellMessage |
|
||||
IShowMarkupCellMessage |
|
||||
IHideMarkupCellMessage |
|
||||
IUnhideMarkupCellMessage |
|
||||
IUpdateSelectedMarkupCellsMessage |
|
||||
IInitializeMarkupCells |
|
||||
INotebookStylesMessage |
|
||||
INotebookOptionsMessage;
|
||||
|
||||
export type AnyMessage = FromWebviewMessage | ToWebviewMessage;
|
|
@ -6,7 +6,7 @@
|
|||
import type { Event } from 'vs/base/common/event';
|
||||
import type { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import type { FromWebviewMessage, IBlurOutputMessage, ICellDropMessage, ICellDragMessage, ICellDragStartMessage, IClickedDataUrlMessage, IDimensionMessage, IClickMarkdownPreviewMessage, IMouseEnterMarkdownPreviewMessage, IMouseEnterMessage, IMouseLeaveMarkdownPreviewMessage, IMouseLeaveMessage, IToggleMarkdownPreviewMessage, IWheelMessage, ToWebviewMessage, ICellDragEndMessage, IOutputFocusMessage, IOutputBlurMessage, DimensionUpdate, IContextMenuMarkdownPreviewMessage, ITelemetryFoundRenderedMarkdownMath, ITelemetryFoundUnrenderedMarkdownMath, IMarkdownCellInitialization } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView';
|
||||
import type * as webviewMessages from 'vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages';
|
||||
|
||||
// !! IMPORTANT !! everything must be in-line within the webviewPreloads
|
||||
// function. Imports are not allowed. This is stringified and injected into
|
||||
|
@ -71,7 +71,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
};
|
||||
|
||||
const handleDataUrl = async (data: string | ArrayBuffer | null, downloadName: string) => {
|
||||
postNotebookMessage<IClickedDataUrlMessage>('clicked-data-url', {
|
||||
postNotebookMessage<webviewMessages.IClickedDataUrlMessage>('clicked-data-url', {
|
||||
data,
|
||||
downloadName
|
||||
});
|
||||
|
@ -201,7 +201,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
});
|
||||
|
||||
const dimensionUpdater = new class {
|
||||
private readonly pending = new Map<string, DimensionUpdate>();
|
||||
private readonly pending = new Map<string, webviewMessages.DimensionUpdate>();
|
||||
|
||||
update(id: string, height: number, options: { init?: boolean; isOutput?: boolean }) {
|
||||
if (!this.pending.size) {
|
||||
|
@ -221,7 +221,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
return;
|
||||
}
|
||||
|
||||
postNotebookMessage<IDimensionMessage>('dimension', {
|
||||
postNotebookMessage<webviewMessages.IDimensionMessage>('dimension', {
|
||||
updates: Array.from(this.pending.values())
|
||||
});
|
||||
this.pending.clear();
|
||||
|
@ -300,7 +300,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
if (event.defaultPrevented || scrollWillGoToParent(event)) {
|
||||
return;
|
||||
}
|
||||
postNotebookMessage<IWheelMessage>('did-scroll-wheel', {
|
||||
postNotebookMessage<webviewMessages.IWheelMessage>('did-scroll-wheel', {
|
||||
payload: {
|
||||
deltaMode: event.deltaMode,
|
||||
deltaX: event.deltaX,
|
||||
|
@ -324,7 +324,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
const element = document.createElement('div');
|
||||
element.tabIndex = 0;
|
||||
element.addEventListener('focus', () => {
|
||||
postNotebookMessage<IBlurOutputMessage>('focus-editor', {
|
||||
postNotebookMessage<webviewMessages.IBlurOutputMessage>('focus-editor', {
|
||||
id: outputId,
|
||||
focusNext
|
||||
});
|
||||
|
@ -335,12 +335,12 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
|
||||
function addMouseoverListeners(element: HTMLElement, outputId: string): void {
|
||||
element.addEventListener('mouseenter', () => {
|
||||
postNotebookMessage<IMouseEnterMessage>('mouseenter', {
|
||||
postNotebookMessage<webviewMessages.IMouseEnterMessage>('mouseenter', {
|
||||
id: outputId,
|
||||
});
|
||||
});
|
||||
element.addEventListener('mouseleave', () => {
|
||||
postNotebookMessage<IMouseLeaveMessage>('mouseleave', {
|
||||
postNotebookMessage<webviewMessages.IMouseLeaveMessage>('mouseleave', {
|
||||
id: outputId,
|
||||
});
|
||||
});
|
||||
|
@ -376,7 +376,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
this._loosingFocus = false;
|
||||
if (!this._hasFocus) {
|
||||
this._hasFocus = true;
|
||||
postNotebookMessage<IOutputFocusMessage>('outputFocus', {
|
||||
postNotebookMessage<webviewMessages.IOutputFocusMessage>('outputFocus', {
|
||||
id: this._outputId,
|
||||
});
|
||||
}
|
||||
|
@ -389,7 +389,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
if (this._loosingFocus) {
|
||||
this._loosingFocus = false;
|
||||
this._hasFocus = false;
|
||||
postNotebookMessage<IOutputBlurMessage>('outputBlur', {
|
||||
postNotebookMessage<webviewMessages.IOutputBlurMessage>('outputBlur', {
|
||||
id: this._outputId,
|
||||
});
|
||||
}
|
||||
|
@ -507,79 +507,45 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
window.addEventListener('wheel', handleWheel);
|
||||
|
||||
window.addEventListener('message', async rawEvent => {
|
||||
const event = rawEvent as ({ data: ToWebviewMessage; });
|
||||
const event = rawEvent as ({ data: webviewMessages.ToWebviewMessage; });
|
||||
|
||||
switch (event.data.type) {
|
||||
case 'initializeMarkdownPreview':
|
||||
{
|
||||
await ensureMarkdownPreviewCells(event.data.cells);
|
||||
dimensionUpdater.updateImmediately();
|
||||
postNotebookMessage('initializedMarkdownPreview', {});
|
||||
}
|
||||
case 'initializeMarkup':
|
||||
await notebookDocument.ensureMarkupCells(event.data.cells);
|
||||
dimensionUpdater.updateImmediately();
|
||||
postNotebookMessage('initializedMarkup', {});
|
||||
break;
|
||||
case 'createMarkdownPreview':
|
||||
ensureMarkdownPreviewCells([event.data.cell]);
|
||||
break;
|
||||
case 'showMarkdownPreview':
|
||||
{
|
||||
const data = event.data;
|
||||
|
||||
const cellContainer = document.getElementById(data.id);
|
||||
if (cellContainer) {
|
||||
cellContainer.style.visibility = 'visible';
|
||||
cellContainer.style.top = `${data.top}px`;
|
||||
updateMarkdownPreview(cellContainer, data.id, data.content);
|
||||
}
|
||||
}
|
||||
case 'createMarkupCell':
|
||||
notebookDocument.ensureMarkupCells([event.data.cell]);
|
||||
break;
|
||||
case 'hideMarkdownPreviews':
|
||||
{
|
||||
for (const id of event.data.ids) {
|
||||
const cellContainer = document.getElementById(id);
|
||||
if (cellContainer) {
|
||||
cellContainer.style.visibility = 'hidden';
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'unhideMarkdownPreviews':
|
||||
{
|
||||
for (const id of event.data.ids) {
|
||||
const cellContainer = document.getElementById(id);
|
||||
if (cellContainer) {
|
||||
cellContainer.style.visibility = 'visible';
|
||||
updateMarkdownPreview(cellContainer, id, undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'deleteMarkdownPreview':
|
||||
{
|
||||
for (const id of event.data.ids) {
|
||||
const cellContainer = document.getElementById(id);
|
||||
cellContainer?.remove();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'updateSelectedMarkdownPreviews':
|
||||
{
|
||||
const selectedCellIds = new Set<string>(event.data.selectedCellIds);
|
||||
|
||||
for (const oldSelected of document.querySelectorAll('.preview.selected')) {
|
||||
const id = oldSelected.id;
|
||||
if (!selectedCellIds.has(id)) {
|
||||
oldSelected.classList.remove('selected');
|
||||
}
|
||||
}
|
||||
case 'showMarkupCell':
|
||||
notebookDocument.showMarkupCell(event.data.id, event.data.top, event.data.content);
|
||||
break;
|
||||
|
||||
for (const newSelected of selectedCellIds) {
|
||||
const previewContainer = document.getElementById(newSelected);
|
||||
if (previewContainer) {
|
||||
previewContainer.classList.add('selected');
|
||||
}
|
||||
}
|
||||
case 'hideMarkupCells':
|
||||
for (const id of event.data.ids) {
|
||||
notebookDocument.hideMarkupCell(id);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'unhideMarkupCells':
|
||||
for (const id of event.data.ids) {
|
||||
notebookDocument.unhideMarkupCell(id);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'deleteMarkupCell':
|
||||
for (const id of event.data.ids) {
|
||||
notebookDocument.deleteMarkupCell(id);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'updateSelectedMarkupCells':
|
||||
notebookDocument.updateSelectedCells(event.data.selectedCellIds);
|
||||
break;
|
||||
|
||||
case 'html': {
|
||||
const data = event.data;
|
||||
outputs.enqueue(event.data.outputId, async (state) => {
|
||||
|
@ -829,10 +795,9 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
|
||||
// Update markdown previews
|
||||
for (const markdownContainer of document.querySelectorAll('.preview')) {
|
||||
setMarkdownContainerDraggable(markdownContainer, currentOptions.dragAndDropEnabled);
|
||||
setMarkupContainerDraggable(markdownContainer, currentOptions.dragAndDropEnabled);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
@ -1021,47 +986,254 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
this._renderers.get(rendererId)?.api?.disposeOutputItem?.(outputId);
|
||||
}
|
||||
|
||||
public async renderCustom(rendererId: string, info: IOutputItem, element: HTMLElement) {
|
||||
const api = await this.load(rendererId);
|
||||
if (!api) {
|
||||
throw new Error(`renderer ${rendererId} did not return an API`);
|
||||
}
|
||||
public async render(info: IOutputItem, element: HTMLElement) {
|
||||
const renderers = Array.from(this._renderers.values())
|
||||
.filter(renderer => renderer.data.mimeTypes.includes(info.mime) && !renderer.data.extends);
|
||||
|
||||
api.renderOutputItem(info, element);
|
||||
}
|
||||
|
||||
public async renderMarkdown(id: string, element: HTMLElement, content: string): Promise<void> {
|
||||
const markdownRenderers = Array.from(this._renderers.values())
|
||||
.filter(renderer => renderer.data.mimeTypes.includes('text/markdown') && !renderer.data.extends);
|
||||
|
||||
if (!markdownRenderers.length) {
|
||||
if (!renderers.length) {
|
||||
throw new Error('Could not find renderer');
|
||||
}
|
||||
|
||||
await Promise.all(markdownRenderers.map(x => x.load()));
|
||||
await Promise.all(renderers.map(x => x.load()));
|
||||
|
||||
markdownRenderers[0].api?.renderOutputItem({
|
||||
id,
|
||||
element,
|
||||
mime: 'text/markdown',
|
||||
metadata: undefined,
|
||||
metadata2: undefined,
|
||||
outputId: undefined,
|
||||
text() { return content; },
|
||||
json() { return undefined; },
|
||||
bytes() { return this.data(); },
|
||||
data() { return new TextEncoder().encode(content); },
|
||||
blob() { return new Blob([this.data()], { type: this.mime }); },
|
||||
}, element);
|
||||
renderers[0].api?.renderOutputItem(info, element);
|
||||
}
|
||||
}();
|
||||
|
||||
let hasPostedRenderedMathTelemetry = false;
|
||||
const unsupportedKatexTermsRegex = /(\\(?:abovewithdelims|array|Arrowvert|arrowvert|atopwithdelims|bbox|bracevert|buildrel|cancelto|cases|class|cssId|ddddot|dddot|DeclareMathOperator|definecolor|displaylines|enclose|eqalign|eqalignno|eqref|hfil|hfill|idotsint|iiiint|label|leftarrowtail|leftroot|leqalignno|lower|mathtip|matrix|mbox|mit|mmlToken|moveleft|moveright|mspace|newenvironment|Newextarrow|notag|oldstyle|overparen|overwithdelims|pmatrix|raise|ref|renewenvironment|require|root|Rule|scr|shoveleft|shoveright|sideset|skew|Space|strut|style|texttip|Tiny|toggle|underparen|unicode|uproot)\b)/gi;
|
||||
|
||||
const notebookDocument = new class {
|
||||
|
||||
private readonly _markupCells = new Map<string, MarkupCell>();
|
||||
|
||||
private async createMarkupCell(init: webviewMessages.IMarkupCellInitialization, top: number): Promise<MarkupCell> {
|
||||
const existing = this._markupCells.get(init.cellId);
|
||||
if (existing) {
|
||||
console.error(`Trying to create markup that already exists: ${init.cellId}`);
|
||||
return existing;
|
||||
}
|
||||
|
||||
const markdownCell = new MarkupCell(init.cellId, init.mime, init.content, top);
|
||||
this._markupCells.set(init.cellId, markdownCell);
|
||||
|
||||
await markdownCell.ready;
|
||||
return markdownCell;
|
||||
}
|
||||
|
||||
public async ensureMarkupCells(update: readonly webviewMessages.IMarkupCellInitialization[]): Promise<void> {
|
||||
await Promise.all(update.map(async info => {
|
||||
let cell = this._markupCells.get(info.cellId);
|
||||
if (cell) {
|
||||
await cell.updateContentAndRender(info.content);
|
||||
} else {
|
||||
cell = await this.createMarkupCell(info, info.offset);
|
||||
}
|
||||
cell.element.style.visibility = info.visible ? 'visible' : 'hidden';
|
||||
}));
|
||||
}
|
||||
|
||||
public deleteMarkupCell(id: string) {
|
||||
const cell = this.getExpectedMarkupCell(id);
|
||||
if (cell) {
|
||||
cell.element.remove();
|
||||
this._markupCells.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
public async updateMarkupContent(id: string, newContent: string): Promise<void> {
|
||||
const cell = this.getExpectedMarkupCell(id);
|
||||
await cell?.updateContentAndRender(newContent);
|
||||
}
|
||||
|
||||
public showMarkupCell(id: string, top: number, newContent: string | undefined): void {
|
||||
const cell = this.getExpectedMarkupCell(id);
|
||||
cell?.show(id, top, newContent);
|
||||
}
|
||||
|
||||
public hideMarkupCell(id: string): void {
|
||||
const cell = this.getExpectedMarkupCell(id);
|
||||
cell?.hide();
|
||||
}
|
||||
|
||||
public unhideMarkupCell(id: string): void {
|
||||
const cell = this.getExpectedMarkupCell(id);
|
||||
cell?.unhide();
|
||||
}
|
||||
|
||||
private getExpectedMarkupCell(id: string): MarkupCell | undefined {
|
||||
const cell = this._markupCells.get(id);
|
||||
if (!cell) {
|
||||
console.log(`Could not find markup cell '${id}'`);
|
||||
return undefined;
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
|
||||
public updateSelectedCells(selectedCellIds: readonly string[]) {
|
||||
const selectedCellSet = new Set<string>(selectedCellIds);
|
||||
for (const cell of this._markupCells.values()) {
|
||||
cell.setSelected(selectedCellSet.has(cell.id));
|
||||
}
|
||||
}
|
||||
}();
|
||||
|
||||
class MarkupCell implements IOutputItem {
|
||||
|
||||
public readonly ready: Promise<void>;
|
||||
|
||||
/// Internal field that holds markdown text
|
||||
private _content: string;
|
||||
|
||||
constructor(id: string, mime: string, content: string, top: number) {
|
||||
this.id = id;
|
||||
this.mime = mime;
|
||||
this._content = content;
|
||||
|
||||
let resolveReady: () => void;
|
||||
this.ready = new Promise<void>(r => resolveReady = r);
|
||||
|
||||
const root = document.getElementById('container')!;
|
||||
|
||||
this.element = document.createElement('div');
|
||||
this.element.id = this.id;
|
||||
this.element.classList.add('preview');
|
||||
this.element.style.position = 'absolute';
|
||||
this.element.style.top = top + 'px';
|
||||
root.appendChild(this.element);
|
||||
|
||||
this.addEventListeners();
|
||||
|
||||
this.updateContentAndRender(this._content).then(() => {
|
||||
resizeObserver.observe(this.element, this.id, false);
|
||||
resolveReady();
|
||||
});
|
||||
}
|
||||
|
||||
//#region IOutputItem
|
||||
public readonly id: string;
|
||||
public readonly mime;
|
||||
public readonly element: HTMLElement;
|
||||
|
||||
// deprecated fields
|
||||
public readonly metadata = undefined;
|
||||
public readonly metadata2 = undefined;
|
||||
public readonly outputId?: string | undefined;
|
||||
|
||||
text() { return this._content; }
|
||||
json() { return undefined; }
|
||||
bytes() { return this.data(); }
|
||||
data() { return new TextEncoder().encode(this._content); }
|
||||
blob() { return new Blob([this.data()], { type: this.mime }); }
|
||||
//#endregion
|
||||
|
||||
private addEventListeners() {
|
||||
this.element.addEventListener('dblclick', () => {
|
||||
postNotebookMessage<webviewMessages.IToggleMarkupPreviewMessage>('toggleMarkupPreview', { cellId: this.id });
|
||||
});
|
||||
|
||||
this.element.addEventListener('click', e => {
|
||||
postNotebookMessage<webviewMessages.IClickMarkupCellMessage>('clickMarkupCell', {
|
||||
cellId: this.id,
|
||||
altKey: e.altKey,
|
||||
ctrlKey: e.ctrlKey,
|
||||
metaKey: e.metaKey,
|
||||
shiftKey: e.shiftKey,
|
||||
});
|
||||
});
|
||||
|
||||
this.element.addEventListener('contextmenu', e => {
|
||||
postNotebookMessage<webviewMessages.IContextMenuMarkupCellMessage>('contextMenuMarkupCell', {
|
||||
cellId: this.id,
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY,
|
||||
});
|
||||
});
|
||||
|
||||
this.element.addEventListener('mouseenter', () => {
|
||||
postNotebookMessage<webviewMessages.IMouseEnterMarkupCellMessage>('mouseEnterMarkupCell', { cellId: this.id });
|
||||
});
|
||||
|
||||
this.element.addEventListener('mouseleave', () => {
|
||||
postNotebookMessage<webviewMessages.IMouseLeaveMarkupCellMessage>('mouseLeaveMarkupCell', { cellId: this.id });
|
||||
});
|
||||
|
||||
setMarkupContainerDraggable(this.element, currentOptions.dragAndDropEnabled);
|
||||
|
||||
this.element.addEventListener('dragstart', e => {
|
||||
markdownPreviewDragManager.startDrag(e, this.id);
|
||||
});
|
||||
|
||||
this.element.addEventListener('drag', e => {
|
||||
markdownPreviewDragManager.updateDrag(e, this.id);
|
||||
});
|
||||
|
||||
this.element.addEventListener('dragend', e => {
|
||||
markdownPreviewDragManager.endDrag(e, this.id);
|
||||
});
|
||||
}
|
||||
|
||||
public async updateContentAndRender(newContent: string): Promise<void> {
|
||||
this._content = newContent;
|
||||
|
||||
await renderers.render(this, this.element);
|
||||
|
||||
if (!hasPostedRenderedMathTelemetry) {
|
||||
const hasRenderedMath = this.element.querySelector('.katex');
|
||||
if (hasRenderedMath) {
|
||||
hasPostedRenderedMathTelemetry = true;
|
||||
postNotebookMessage<webviewMessages.ITelemetryFoundRenderedMarkdownMath>('telemetryFoundRenderedMarkdownMath', {});
|
||||
}
|
||||
}
|
||||
|
||||
const matches = this.element.innerText.match(unsupportedKatexTermsRegex);
|
||||
if (matches) {
|
||||
postNotebookMessage<webviewMessages.ITelemetryFoundUnrenderedMarkdownMath>('telemetryFoundUnrenderedMarkdownMath', {
|
||||
latexDirective: matches[0],
|
||||
});
|
||||
}
|
||||
|
||||
dimensionUpdater.update(this.id, this.element.clientHeight, {
|
||||
isOutput: false
|
||||
});
|
||||
}
|
||||
|
||||
public show(id: string, top: number, newContent: string | undefined): void {
|
||||
this.element.style.visibility = 'visible';
|
||||
this.element.style.top = `${top}px`;
|
||||
if (typeof newContent === 'string') {
|
||||
this.updateContentAndRender(newContent);
|
||||
} else {
|
||||
this.updateMarkupDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
public hide() {
|
||||
this.element.style.visibility = 'hidden';
|
||||
}
|
||||
|
||||
public unhide() {
|
||||
this.element.style.visibility = 'visible';
|
||||
this.updateMarkupDimensions();
|
||||
}
|
||||
|
||||
private async updateMarkupDimensions() {
|
||||
dimensionUpdater.update(this.id, this.element.clientHeight, {
|
||||
isOutput: false
|
||||
});
|
||||
}
|
||||
|
||||
public setSelected(selected: boolean) {
|
||||
this.element.classList.toggle('selected', selected);
|
||||
}
|
||||
}
|
||||
|
||||
vscode.postMessage({
|
||||
__vscode_notebook_message: true,
|
||||
type: 'initialized'
|
||||
});
|
||||
|
||||
function setMarkdownContainerDraggable(element: Element, isDraggable: boolean) {
|
||||
function setMarkupContainerDraggable(element: Element, isDraggable: boolean) {
|
||||
if (isDraggable) {
|
||||
element.classList.add('draggable');
|
||||
element.setAttribute('draggable', 'true');
|
||||
|
@ -1071,102 +1243,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
}
|
||||
}
|
||||
|
||||
async function createMarkdownPreview(cellId: string, content: string, top: number): Promise<HTMLElement> {
|
||||
const container = document.getElementById('container')!;
|
||||
const cellContainer = document.createElement('div');
|
||||
|
||||
const existing = document.getElementById(cellId);
|
||||
if (existing) {
|
||||
console.error(`Trying to create markdown preview that already exists: ${cellId}`);
|
||||
return existing;
|
||||
}
|
||||
|
||||
cellContainer.id = cellId;
|
||||
cellContainer.classList.add('preview');
|
||||
|
||||
cellContainer.style.position = 'absolute';
|
||||
cellContainer.style.top = top + 'px';
|
||||
container.appendChild(cellContainer);
|
||||
|
||||
cellContainer.addEventListener('dblclick', () => {
|
||||
postNotebookMessage<IToggleMarkdownPreviewMessage>('toggleMarkdownPreview', { cellId });
|
||||
});
|
||||
|
||||
cellContainer.addEventListener('click', e => {
|
||||
postNotebookMessage<IClickMarkdownPreviewMessage>('clickMarkdownPreview', {
|
||||
cellId,
|
||||
altKey: e.altKey,
|
||||
ctrlKey: e.ctrlKey,
|
||||
metaKey: e.metaKey,
|
||||
shiftKey: e.shiftKey,
|
||||
});
|
||||
});
|
||||
|
||||
cellContainer.addEventListener('contextmenu', e => {
|
||||
postNotebookMessage<IContextMenuMarkdownPreviewMessage>('contextMenuMarkdownPreview', {
|
||||
cellId,
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY,
|
||||
});
|
||||
});
|
||||
|
||||
cellContainer.addEventListener('mouseenter', () => {
|
||||
postNotebookMessage<IMouseEnterMarkdownPreviewMessage>('mouseEnterMarkdownPreview', { cellId });
|
||||
});
|
||||
|
||||
cellContainer.addEventListener('mouseleave', () => {
|
||||
postNotebookMessage<IMouseLeaveMarkdownPreviewMessage>('mouseLeaveMarkdownPreview', { cellId });
|
||||
});
|
||||
|
||||
setMarkdownContainerDraggable(cellContainer, currentOptions.dragAndDropEnabled);
|
||||
|
||||
cellContainer.addEventListener('dragstart', e => {
|
||||
markdownPreviewDragManager.startDrag(e, cellId);
|
||||
});
|
||||
|
||||
cellContainer.addEventListener('drag', e => {
|
||||
markdownPreviewDragManager.updateDrag(e, cellId);
|
||||
});
|
||||
|
||||
cellContainer.addEventListener('dragend', e => {
|
||||
markdownPreviewDragManager.endDrag(e, cellId);
|
||||
});
|
||||
|
||||
const previewRoot = cellContainer.attachShadow({ mode: 'open' });
|
||||
|
||||
// Add default webview style
|
||||
const defaultStyles = document.getElementById('_defaultStyles') as HTMLStyleElement;
|
||||
previewRoot.appendChild(defaultStyles.cloneNode(true));
|
||||
|
||||
// Add default preview style
|
||||
const previewStyles = document.getElementById('preview-styles') as HTMLTemplateElement;
|
||||
previewRoot.appendChild(previewStyles.content.cloneNode(true));
|
||||
|
||||
const previewNode = document.createElement('div');
|
||||
previewNode.id = 'preview';
|
||||
previewRoot.appendChild(previewNode);
|
||||
|
||||
await updateMarkdownPreview(cellContainer, cellId, content);
|
||||
|
||||
resizeObserver.observe(cellContainer, cellId, false);
|
||||
|
||||
return cellContainer;
|
||||
}
|
||||
|
||||
async function ensureMarkdownPreviewCells(update: readonly IMarkdownCellInitialization[]): Promise<void> {
|
||||
await Promise.all(update.map(async cell => {
|
||||
let container = document.getElementById(cell.cellId);
|
||||
if (container) {
|
||||
await updateMarkdownPreview(container, cell.cellId, cell.content);
|
||||
} else {
|
||||
container = await createMarkdownPreview(cell.cellId, cell.content, cell.offset);
|
||||
}
|
||||
|
||||
container.style.visibility = cell.visible ? 'visible' : 'hidden';
|
||||
}));
|
||||
}
|
||||
|
||||
function postNotebookMessage<T extends FromWebviewMessage>(
|
||||
function postNotebookMessage<T extends webviewMessages.FromWebviewMessage>(
|
||||
type: T['type'],
|
||||
properties: Omit<T, '__vscode_notebook_message' | 'type'>
|
||||
) {
|
||||
|
@ -1177,46 +1254,6 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
});
|
||||
}
|
||||
|
||||
let hasPostedRenderedMathTelemetry = false;
|
||||
const unsupportedKatexTermsRegex = /(\\(?:abovewithdelims|array|Arrowvert|arrowvert|atopwithdelims|bbox|bracevert|buildrel|cancelto|cases|class|cssId|ddddot|dddot|DeclareMathOperator|definecolor|displaylines|enclose|eqalign|eqalignno|eqref|hfil|hfill|idotsint|iiiint|label|leftarrowtail|leftroot|leqalignno|lower|mathtip|matrix|mbox|mit|mmlToken|moveleft|moveright|mspace|newenvironment|Newextarrow|notag|oldstyle|overparen|overwithdelims|pmatrix|raise|ref|renewenvironment|require|root|Rule|scr|shoveleft|shoveright|sideset|skew|Space|strut|style|texttip|Tiny|toggle|underparen|unicode|uproot)\b)/gi;
|
||||
|
||||
async function updateMarkdownPreview(previewContainerNode: HTMLElement, cellId: string, content: string | undefined) {
|
||||
const previewRoot = previewContainerNode.shadowRoot;
|
||||
const previewNode = previewRoot?.getElementById('preview');
|
||||
if (!previewNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof content === 'string') {
|
||||
if (content.trim().length === 0) {
|
||||
previewContainerNode.classList.add('emptyMarkdownCell');
|
||||
previewNode.innerText = '';
|
||||
} else {
|
||||
previewContainerNode.classList.remove('emptyMarkdownCell');
|
||||
await renderers.renderMarkdown(cellId, previewNode, content);
|
||||
|
||||
if (!hasPostedRenderedMathTelemetry) {
|
||||
const hasRenderedMath = previewNode.querySelector('.katex');
|
||||
if (hasRenderedMath) {
|
||||
hasPostedRenderedMathTelemetry = true;
|
||||
postNotebookMessage<ITelemetryFoundRenderedMarkdownMath>('telemetryFoundRenderedMarkdownMath', {});
|
||||
}
|
||||
}
|
||||
|
||||
const matches = previewNode.innerText.match(unsupportedKatexTermsRegex);
|
||||
if (matches) {
|
||||
postNotebookMessage<ITelemetryFoundUnrenderedMarkdownMath>('telemetryFoundUnrenderedMarkdownMath', {
|
||||
latexDirective: matches[0],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dimensionUpdater.update(cellId, previewContainerNode.clientHeight, {
|
||||
isOutput: false
|
||||
});
|
||||
}
|
||||
|
||||
const markdownPreviewDragManager = new class MarkdownPreviewDragManager {
|
||||
|
||||
private currentDrag: { cellId: string, clientY: number } | undefined;
|
||||
|
@ -1236,7 +1273,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
}
|
||||
|
||||
this.currentDrag = undefined;
|
||||
postNotebookMessage<ICellDropMessage>('cell-drop', {
|
||||
postNotebookMessage<webviewMessages.ICellDropMessage>('cell-drop', {
|
||||
cellId: drag.cellId,
|
||||
ctrlKey: e.ctrlKey,
|
||||
altKey: e.altKey,
|
||||
|
@ -1258,7 +1295,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
|
||||
(e.target as HTMLElement).classList.add('dragging');
|
||||
|
||||
postNotebookMessage<ICellDragStartMessage>('cell-drag-start', {
|
||||
postNotebookMessage<webviewMessages.ICellDragStartMessage>('cell-drag-start', {
|
||||
cellId: cellId,
|
||||
dragOffsetY: e.clientY,
|
||||
});
|
||||
|
@ -1270,7 +1307,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
return;
|
||||
}
|
||||
|
||||
postNotebookMessage<ICellDragMessage>('cell-drag', {
|
||||
postNotebookMessage<webviewMessages.ICellDragMessage>('cell-drag', {
|
||||
cellId: cellId,
|
||||
dragOffsetY: this.currentDrag.clientY,
|
||||
});
|
||||
|
@ -1289,7 +1326,7 @@ async function webviewPreloads(style: PreloadStyles, options: PreloadOptions, re
|
|||
endDrag(e: DragEvent, cellId: string) {
|
||||
this.currentDrag = undefined;
|
||||
(e.target as HTMLElement).classList.remove('dragging');
|
||||
postNotebookMessage<ICellDragEndMessage>('cell-drag-end', {
|
||||
postNotebookMessage<webviewMessages.ICellDragEndMessage>('cell-drag-end', {
|
||||
cellId: cellId
|
||||
});
|
||||
}
|
||||
|
|
|
@ -19,19 +19,24 @@ import { BaseCellViewModel } from './baseCellViewModel';
|
|||
|
||||
export class CodeCellViewModel extends BaseCellViewModel implements ICellViewModel {
|
||||
readonly cellKind = CellKind.Code;
|
||||
protected readonly _onDidChangeOutputs = new Emitter<NotebookCellOutputsSplice[]>();
|
||||
|
||||
protected readonly _onDidChangeOutputs = this._register(new Emitter<NotebookCellOutputsSplice[]>());
|
||||
readonly onDidChangeOutputs = this._onDidChangeOutputs.event;
|
||||
private readonly _onDidRemoveOutputs = new Emitter<readonly ICellOutputViewModel[]>();
|
||||
|
||||
private readonly _onDidRemoveOutputs = this._register(new Emitter<readonly ICellOutputViewModel[]>());
|
||||
readonly onDidRemoveOutputs = this._onDidRemoveOutputs.event;
|
||||
private readonly _onDidHideInput = new Emitter<void>();
|
||||
|
||||
private readonly _onDidHideInput = this._register(new Emitter<void>());
|
||||
readonly onDidHideInput = this._onDidHideInput.event;
|
||||
private readonly _onDidHideOutputs = new Emitter<readonly ICellOutputViewModel[]>();
|
||||
|
||||
private readonly _onDidHideOutputs = this._register(new Emitter<readonly ICellOutputViewModel[]>());
|
||||
readonly onDidHideOutputs = this._onDidHideOutputs.event;
|
||||
|
||||
private _outputCollection: number[] = [];
|
||||
|
||||
private _outputsTop: PrefixSumComputer | null = null;
|
||||
|
||||
protected readonly _onDidChangeLayout = new Emitter<CodeCellLayoutChangeEvent>();
|
||||
protected readonly _onDidChangeLayout = this._register(new Emitter<CodeCellLayoutChangeEvent>());
|
||||
readonly onDidChangeLayout = this._onDidChangeLayout.event;
|
||||
|
||||
private _editorHeight = 0;
|
||||
|
|
|
@ -17,6 +17,8 @@ import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/mode
|
|||
import { CellKind, INotebookSearchOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { dirname } from 'vs/base/common/resources';
|
||||
|
||||
export class MarkdownCellViewModel extends BaseCellViewModel implements ICellViewModel {
|
||||
readonly cellKind = CellKind.Markup;
|
||||
|
@ -97,17 +99,22 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie
|
|||
private readonly _onDidHideInput = new Emitter<void>();
|
||||
readonly onDidHideInput = this._onDidHideInput.event;
|
||||
|
||||
private readonly _mdRenderer: MarkdownRenderer;
|
||||
|
||||
constructor(
|
||||
viewType: string,
|
||||
model: NotebookCellTextModel,
|
||||
initialNotebookLayoutInfo: NotebookLayoutInfo | null,
|
||||
readonly foldingDelegate: EditorFoldingStateDelegate,
|
||||
readonly viewContext: ViewContext,
|
||||
private readonly _mdRenderer: MarkdownRenderer,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@ITextModelService textModelService: ITextModelService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
) {
|
||||
super(viewType, model, UUID.generateUuid(), viewContext, configurationService, textModelService);
|
||||
|
||||
this._mdRenderer = this._register(instantiationService.createInstance(MarkdownRenderer, { baseUrl: dirname(model.uri) }));
|
||||
|
||||
const { bottomToolbarGap } = this.viewContext.notebookOptions.computeBottomToolbarDimensions(this.viewType);
|
||||
|
||||
this._layoutInfo = {
|
||||
|
|
|
@ -8,10 +8,8 @@ import { onUnexpectedError } from 'vs/base/common/errors';
|
|||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { clamp } from 'vs/base/common/numbers';
|
||||
import { dirname } from 'vs/base/common/resources';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { MarkdownRenderer } from 'vs/editor/browser/core/markdownRenderer';
|
||||
import { IBulkEditService, ResourceEdit, ResourceTextEdit } from 'vs/editor/browser/services/bulkEditService';
|
||||
import { IPosition, Position } from 'vs/editor/common/core/position';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
|
@ -1188,7 +1186,6 @@ export function createCellViewModel(instantiationService: IInstantiationService,
|
|||
if (cell.cellKind === CellKind.Code) {
|
||||
return instantiationService.createInstance(CodeCellViewModel, notebookViewModel.viewType, cell, notebookViewModel.layoutInfo, notebookViewModel.viewContext);
|
||||
} else {
|
||||
const mdRenderer = instantiationService.createInstance(MarkdownRenderer, { baseUrl: dirname(notebookViewModel.uri) });
|
||||
return instantiationService.createInstance(MarkdownCellViewModel, notebookViewModel.viewType, cell, notebookViewModel.layoutInfo, notebookViewModel, notebookViewModel.viewContext, mdRenderer);
|
||||
return instantiationService.createInstance(MarkdownCellViewModel, notebookViewModel.viewType, cell, notebookViewModel.layoutInfo, notebookViewModel, notebookViewModel.viewContext);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event';
|
|||
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import { INotebookTextModel, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, notebookDocumentMetadataDefaults, diff, NotebookCellsChangeType, ICellDto2, TransientOptions, NotebookTextModelChangedEvent, NotebookRawContentEvent, IOutputDto, ICellOutput, IOutputItemDto, ISelectionState, NullablePartialNotebookCellMetadata, NotebookCellInternalMetadata, NullablePartialNotebookCellInternalMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookTextModel, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, CellEditType, CellUri, diff, NotebookCellsChangeType, ICellDto2, TransientOptions, NotebookTextModelChangedEvent, NotebookRawContentEvent, IOutputDto, ICellOutput, IOutputItemDto, ISelectionState, NullablePartialNotebookCellMetadata, NotebookCellInternalMetadata, NullablePartialNotebookCellInternalMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { IUndoRedoService, UndoRedoElementType, IUndoRedoElement, IResourceUndoRedoElement, UndoRedoGroup, IWorkspaceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo';
|
||||
import { MoveCellEdit, SpliceCellsEdit, CellMetadataEdit } from 'vs/workbench/contrib/notebook/common/model/cellEdit';
|
||||
import { ISequence, LcsDiff } from 'vs/base/common/diff/diff';
|
||||
|
@ -197,7 +197,7 @@ export class NotebookTextModel extends Disposable implements INotebookTextModel
|
|||
private _cellListeners: Map<number, IDisposable> = new Map();
|
||||
private _cells: NotebookCellTextModel[] = [];
|
||||
|
||||
metadata: NotebookDocumentMetadata = notebookDocumentMetadataDefaults;
|
||||
metadata: NotebookDocumentMetadata = {};
|
||||
transientOptions: TransientOptions = { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false };
|
||||
private _versionId = 0;
|
||||
|
||||
|
|
|
@ -60,14 +60,7 @@ export enum NotebookRunState {
|
|||
Idle = 2
|
||||
}
|
||||
|
||||
export const notebookDocumentMetadataDefaults: Required<NotebookDocumentMetadata> = {
|
||||
custom: {},
|
||||
};
|
||||
|
||||
export interface NotebookDocumentMetadata {
|
||||
custom?: { [key: string]: unknown; };
|
||||
[key: string]: unknown;
|
||||
}
|
||||
export type NotebookDocumentMetadata = Record<string, unknown>;
|
||||
|
||||
// Aligns with the vscode.d.ts version
|
||||
export enum NotebookCellExecutionState {
|
||||
|
|
|
@ -20,7 +20,7 @@ import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/v
|
|||
import { NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
|
||||
import { ViewContext } from 'vs/workbench/contrib/notebook/browser/viewModel/viewContext';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { CellKind, diff, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellKind, diff } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NotebookOptions } from 'vs/workbench/contrib/notebook/common/notebookOptions';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { NotebookEditorTestModel, setupInstantiationService, withTestNotebook } from 'vs/workbench/contrib/notebook/test/testNotebookEditor';
|
||||
|
@ -37,7 +37,7 @@ suite('NotebookViewModel', () => {
|
|||
instantiationService.stub(IThemeService, new TestThemeService());
|
||||
|
||||
test('ctor', function () {
|
||||
const notebook = new NotebookTextModel('notebook', URI.parse('test'), [], notebookDocumentMetadataDefaults, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false }, undoRedoService, modelService, modeService);
|
||||
const notebook = new NotebookTextModel('notebook', URI.parse('test'), [], {}, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false }, undoRedoService, modelService, modeService);
|
||||
const model = new NotebookEditorTestModel(notebook);
|
||||
const viewContext = new ViewContext(new NotebookOptions(instantiationService.get(IConfigurationService)), new NotebookEventDispatcher());
|
||||
const viewModel = new NotebookViewModel('notebook', model.notebook, viewContext, null, instantiationService, bulkEditService, undoRedoService, textModelService);
|
||||
|
|
|
@ -21,7 +21,7 @@ import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/v
|
|||
import { CellViewModel, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
|
||||
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { CellKind, CellUri, INotebookDiffEditorModel, INotebookEditorModel, IOutputDto, IResolvedNotebookEditorModel, NotebookCellMetadata, notebookDocumentMetadataDefaults } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellKind, CellUri, INotebookDiffEditorModel, INotebookEditorModel, IOutputDto, IResolvedNotebookEditorModel, NotebookCellMetadata, } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
import { TextModelResolverService } from 'vs/workbench/services/textmodelResolver/common/textModelResolverService';
|
||||
import { IModelService } from 'vs/editor/common/services/modelService';
|
||||
|
@ -176,7 +176,7 @@ function _createTestNotebookEditor(instantiationService: TestInstantiationServic
|
|||
outputs: cell[3] ?? [],
|
||||
metadata: cell[4]
|
||||
};
|
||||
}), notebookDocumentMetadataDefaults, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false });
|
||||
}), {}, { transientCellMetadata: {}, transientDocumentMetadata: {}, transientOutputs: false });
|
||||
|
||||
const model = new NotebookEditorTestModel(notebook);
|
||||
const viewContext = new ViewContext(new NotebookOptions(instantiationService.get(IConfigurationService)), new NotebookEventDispatcher());
|
||||
|
|
|
@ -314,7 +314,9 @@ class OnAutoForwardedAction extends Disposable {
|
|||
}
|
||||
|
||||
private linkMessage() {
|
||||
return nls.localize('remote.tunnelsView.notificationLink', "[See all forwarded ports](command:{0}.focus)", TunnelPanel.ID);
|
||||
return nls.localize(
|
||||
{ key: 'remote.tunnelsView.notificationLink2', comment: ['[See all forwarded ports]({0}) is a link. Only translate `See all forwarded ports`. Do not change brackets and parentheses or {0}'] },
|
||||
"[See all forwarded ports]({0})", `command:${TunnelPanel.ID}.focus`);
|
||||
}
|
||||
|
||||
private async showNotification(tunnel: RemoteTunnel) {
|
||||
|
|
|
@ -301,7 +301,11 @@ export class RemoteStatusIndicator extends Disposable implements IWorkbenchContr
|
|||
const workspaceLabel = this.getWorkspaceLabel();
|
||||
if (workspaceLabel) {
|
||||
const toolTip: IMarkdownString = {
|
||||
value: nls.localize('workspace.tooltip', "Virtual workspace on {0}\n\n[Some features](command:{1}) are not available for resources located on a virtual file system.", workspaceLabel, LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID),
|
||||
value: nls.localize(
|
||||
{ key: 'workspace.tooltip2', comment: ['{0} is a remote location name, e.g. GitHub', '[Some features]({1}) is a link. Only translate `Some features`. Do not change brackets and parentheses or {1}'] },
|
||||
"Virtual workspace on {0}\n\n[Some features]({1}) are not available for resources located on a virtual file system.",
|
||||
workspaceLabel, `command:${LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID}`
|
||||
),
|
||||
isTrusted: true
|
||||
};
|
||||
this.renderRemoteStatusIndicator(`$(remote) ${truncate(workspaceLabel, RemoteStatusIndicator.REMOTE_STATUS_LABEL_MAX_LENGTH)}`, toolTip);
|
||||
|
|
|
@ -327,7 +327,7 @@ suite('SearchModel', () => {
|
|||
}
|
||||
|
||||
function stub(arg1: any, arg2: any, arg3: any): sinon.SinonStub {
|
||||
const stub = sinon.stub(arg1, arg2, arg3);
|
||||
const stub = sinon.stub(arg1, arg2).callsFake(arg3);
|
||||
restoreStubs.push(stub);
|
||||
return stub;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { renderStringAsPlaintext } from 'vs/base/browser/markdownRenderer';
|
||||
import { Action, IAction, Separator } from 'vs/base/common/actions';
|
||||
import { Action, IAction, Separator, SubmenuAction } from 'vs/base/common/actions';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { MarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { Disposable, dispose, IDisposable, IReference, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
|
@ -19,6 +19,7 @@ import { IModelDeltaDecoration, OverviewRulerLane, TrackedRangeStickiness } from
|
|||
import { overviewRulerError, overviewRulerInfo, overviewRulerWarning } from 'vs/editor/common/view/editorColorRegistry';
|
||||
import { localize } from 'vs/nls';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IThemeService, themeColorFromId, ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
|
@ -28,7 +29,10 @@ import { BREAKPOINT_EDITOR_CONTRIBUTION_ID, IBreakpointEditorContribution } from
|
|||
import { testingRunAllIcon, testingRunIcon, testingStatesToIcons } from 'vs/workbench/contrib/testing/browser/icons';
|
||||
import { TestingOutputPeekController } from 'vs/workbench/contrib/testing/browser/testingOutputPeek';
|
||||
import { testMessageSeverityColors } from 'vs/workbench/contrib/testing/browser/theme';
|
||||
import { IncrementalTestCollectionItem, IRichLocation, ITestMessage, TestDiffOpType, TestResultItem } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { DefaultGutterClickAction, getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration';
|
||||
import { labelForTestInState } from 'vs/workbench/contrib/testing/common/constants';
|
||||
import { IncrementalTestCollectionItem, InternalTestItem, IRichLocation, ITestMessage, TestDiffOpType, TestResultItem } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { maxPriority } from 'vs/workbench/contrib/testing/common/testingStates';
|
||||
import { buildTestUri, TestUriType } from 'vs/workbench/contrib/testing/common/testingUri';
|
||||
import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
import { IMainThreadTestCollection, ITestService } from 'vs/workbench/contrib/testing/common/testService';
|
||||
|
@ -173,8 +177,15 @@ export class TestingDecorations extends Disposable implements IEditorContributio
|
|||
for (const test of ref.object.all) {
|
||||
const stateLookup = this.results.getStateById(test.item.extId);
|
||||
if (test.item.range) {
|
||||
newDecorations.push(this.instantiationService.createInstance(
|
||||
RunTestDecoration, test, ref.object, test.item.range, this.editor, stateLookup?.[1]));
|
||||
const line = test.item.range.startLineNumber;
|
||||
const resultItem = stateLookup?.[1];
|
||||
const existing = newDecorations.findIndex(d => d instanceof RunTestDecoration && d.line === line);
|
||||
if (existing !== -1) {
|
||||
newDecorations[existing] = (newDecorations[existing] as RunTestDecoration).merge(test, ref.object, resultItem);
|
||||
} else {
|
||||
newDecorations.push(this.instantiationService.createInstance(
|
||||
RunSingleTestDecoration, test, ref.object, this.editor, stateLookup?.[1]));
|
||||
}
|
||||
}
|
||||
|
||||
if (!stateLookup) {
|
||||
|
@ -249,116 +260,179 @@ const firstLineRange = (originalRange: IRange) => ({
|
|||
endColumn: 1,
|
||||
});
|
||||
|
||||
class RunTestDecoration extends Disposable implements ITestDecoration {
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
id = '';
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public readonly editorDecoration: IModelDeltaDecoration;
|
||||
|
||||
private line: number;
|
||||
|
||||
constructor(
|
||||
private readonly test: IncrementalTestCollectionItem,
|
||||
private readonly collection: IMainThreadTestCollection,
|
||||
range: IRange,
|
||||
private readonly editor: ICodeEditor,
|
||||
stateItem: TestResultItem | undefined,
|
||||
@ITestService private readonly testService: ITestService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
) {
|
||||
super();
|
||||
this.line = range.startLineNumber;
|
||||
|
||||
const icon = stateItem?.computedState !== undefined && stateItem.computedState !== TestResultState.Unset
|
||||
? testingStatesToIcons.get(stateItem.computedState)!
|
||||
: test.children.size > 0 ? testingRunAllIcon : testingRunIcon;
|
||||
|
||||
const hoverMessage = new MarkdownString('', true).appendText(localize('failedHoverMessage', '{0} has failed. ', test.item.label));
|
||||
if (stateItem?.tasks.some(s => s.messages.length > 0)) {
|
||||
const args = encodeURIComponent(JSON.stringify([test.item.extId]));
|
||||
hoverMessage.appendMarkdown(`[${localize('failedPeekAction', 'Peek Error')}](command:vscode.peekTestError?${args})`);
|
||||
}
|
||||
|
||||
let glyphMarginClassName = ThemeIcon.asClassName(icon) + ' testing-run-glyph';
|
||||
if (stateItem?.retired) {
|
||||
glyphMarginClassName += ' retired';
|
||||
}
|
||||
|
||||
this.editorDecoration = {
|
||||
range: firstLineRange(range),
|
||||
options: {
|
||||
description: 'run-test-decoration',
|
||||
isWholeLine: true,
|
||||
hoverMessage,
|
||||
glyphMarginClassName,
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
||||
glyphMarginHoverMessage: new MarkdownString().appendText(localize('testing.clickToRun', 'Click to run tests, right click for more options')),
|
||||
}
|
||||
};
|
||||
const createRunTestDecoration = (tests: readonly IncrementalTestCollectionItem[], states: readonly (TestResultItem | undefined)[]): IModelDeltaDecoration => {
|
||||
const range = tests[0]?.item.range;
|
||||
if (!range) {
|
||||
throw new Error('Test decorations can only be created for tests with a range');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
let computedState = TestResultState.Unset;
|
||||
let hoverMessageParts: string[] = [];
|
||||
let testIdWithMessages: string | undefined;
|
||||
let retired = false;
|
||||
for (let i = 0; i < tests.length; i++) {
|
||||
const test = tests[i];
|
||||
const resultItem = states[i];
|
||||
const state = resultItem?.computedState ?? TestResultState.Unset;
|
||||
hoverMessageParts.push(labelForTestInState(test.item.label, state));
|
||||
computedState = maxPriority(computedState, state);
|
||||
retired = retired || !!resultItem?.retired;
|
||||
if (!testIdWithMessages && resultItem?.tasks.some(t => t.messages.length)) {
|
||||
testIdWithMessages = test.item.extId;
|
||||
}
|
||||
}
|
||||
|
||||
const hasMultipleTests = tests.length > 1 || tests[0].children.size > 0;
|
||||
const icon = computedState === TestResultState.Unset
|
||||
? (hasMultipleTests ? testingRunAllIcon : testingRunIcon)
|
||||
: testingStatesToIcons.get(computedState)!;
|
||||
|
||||
const hoverMessage = new MarkdownString('', true).appendText(hoverMessageParts.join(', ') + '.');
|
||||
if (testIdWithMessages) {
|
||||
const args = encodeURIComponent(JSON.stringify([testIdWithMessages]));
|
||||
hoverMessage.appendMarkdown(`[${localize('peekTestOutout', 'Peek Test Output')}](command:vscode.peekTestError?${args})`);
|
||||
}
|
||||
|
||||
let glyphMarginClassName = ThemeIcon.asClassName(icon) + ' testing-run-glyph';
|
||||
if (retired) {
|
||||
glyphMarginClassName += ' retired';
|
||||
}
|
||||
|
||||
return {
|
||||
range: firstLineRange(range),
|
||||
options: {
|
||||
description: 'run-test-decoration',
|
||||
isWholeLine: true,
|
||||
hoverMessage,
|
||||
glyphMarginClassName,
|
||||
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
abstract class RunTestDecoration extends Disposable {
|
||||
/** @inheritdoc */
|
||||
public id = '';
|
||||
|
||||
public get line() {
|
||||
return this.editorDecoration.range.startLineNumber;
|
||||
}
|
||||
|
||||
constructor(
|
||||
public editorDecoration: IModelDeltaDecoration,
|
||||
protected readonly editor: ICodeEditor,
|
||||
@ITestService protected readonly testService: ITestService,
|
||||
@IContextMenuService protected readonly contextMenuService: IContextMenuService,
|
||||
@ICommandService protected readonly commandService: ICommandService,
|
||||
@IConfigurationService protected readonly configurationService: IConfigurationService,
|
||||
) {
|
||||
super();
|
||||
editorDecoration.options.glyphMarginHoverMessage = new MarkdownString().appendText(this.getGutterLabel());
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public click(e: IEditorMouseEvent): boolean {
|
||||
if (e.target.position?.lineNumber !== this.line || e.target.type !== MouseTargetType.GUTTER_GLYPH_MARGIN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.event.rightButton) {
|
||||
const actions = this.getContextMenu();
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => ({ x: e.event.posx, y: e.event.posy }),
|
||||
getActions: () => actions,
|
||||
onHide: () => dispose(actions),
|
||||
});
|
||||
} else {
|
||||
// todo: customize click behavior
|
||||
this.testService.runTests({
|
||||
tests: [{ testId: this.test.item.extId, src: this.test.src }],
|
||||
debug: false,
|
||||
});
|
||||
this.showContextMenu(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (getTestingConfiguration(this.configurationService, TestingConfigKeys.DefaultGutterClickAction)) {
|
||||
case DefaultGutterClickAction.ContextMenu:
|
||||
this.showContextMenu(e);
|
||||
break;
|
||||
case DefaultGutterClickAction.Debug:
|
||||
this.defaultDebug();
|
||||
break;
|
||||
case DefaultGutterClickAction.Run:
|
||||
default:
|
||||
this.defaultRun();
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override dispose() {
|
||||
// no-op
|
||||
/**
|
||||
* Adds the test to this decoration.
|
||||
*/
|
||||
public abstract merge(other: IncrementalTestCollectionItem, collection: IMainThreadTestCollection, resultItem: TestResultItem | undefined): RunTestDecoration;
|
||||
|
||||
/**
|
||||
* Called when the decoration is clicked on.
|
||||
*/
|
||||
protected abstract getContextMenuActions(e: IEditorMouseEvent): IAction[];
|
||||
|
||||
/**
|
||||
* Default run action.
|
||||
*/
|
||||
protected abstract defaultRun(): void;
|
||||
|
||||
/**
|
||||
* Default debug action.
|
||||
*/
|
||||
protected abstract defaultDebug(): void;
|
||||
|
||||
private showContextMenu(e: IEditorMouseEvent) {
|
||||
let actions = this.getContextMenuActions(e);
|
||||
|
||||
const model = this.editor.getModel();
|
||||
if (model) {
|
||||
actions = Separator.join(
|
||||
actions,
|
||||
this.editor
|
||||
.getContribution<IBreakpointEditorContribution>(BREAKPOINT_EDITOR_CONTRIBUTION_ID)
|
||||
.getContextMenuActionsAtPosition(this.line, model)
|
||||
);
|
||||
}
|
||||
|
||||
this.contextMenuService.showContextMenu({
|
||||
getAnchor: () => ({ x: e.event.posx, y: e.event.posy }),
|
||||
getActions: () => actions,
|
||||
onHide: () => dispose(actions),
|
||||
});
|
||||
}
|
||||
|
||||
private getContextMenu() {
|
||||
const model = this.editor.getModel();
|
||||
if (!model) {
|
||||
return [];
|
||||
private getGutterLabel() {
|
||||
switch (getTestingConfiguration(this.configurationService, TestingConfigKeys.DefaultGutterClickAction)) {
|
||||
case DefaultGutterClickAction.ContextMenu:
|
||||
return localize('testing.gutterMsg.contextMenu', 'Click for test options');
|
||||
case DefaultGutterClickAction.Debug:
|
||||
return localize('testing.gutterMsg.debug', 'Click to debug tests, right click for more options');
|
||||
case DefaultGutterClickAction.Run:
|
||||
default:
|
||||
return localize('testing.gutterMsg.run', 'Click to run tests, right click for more options');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets context menu actions relevant for a singel test.
|
||||
*/
|
||||
protected getTestContextMenuActions(collection: IMainThreadTestCollection, test: InternalTestItem) {
|
||||
const testActions: IAction[] = [];
|
||||
if (this.test.item.runnable) {
|
||||
testActions.push(new Action('testing.run', localize('run test', 'Run Test'), undefined, undefined, () => this.testService.runTests({
|
||||
if (test.item.runnable) {
|
||||
testActions.push(new Action('testing.gutter.run', localize('run test', 'Run Test'), undefined, undefined, () => this.testService.runTests({
|
||||
debug: false,
|
||||
tests: [{ src: this.test.src, testId: this.test.item.extId }],
|
||||
tests: [{ src: test.src, testId: test.item.extId }],
|
||||
})));
|
||||
}
|
||||
|
||||
if (this.test.item.debuggable) {
|
||||
testActions.push(new Action('testing.debug', localize('debug test', 'Debug Test'), undefined, undefined, () => this.testService.runTests({
|
||||
if (test.item.debuggable) {
|
||||
testActions.push(new Action('testing.gutter.debug', localize('debug test', 'Debug Test'), undefined, undefined, () => this.testService.runTests({
|
||||
debug: true,
|
||||
tests: [{ src: this.test.src, testId: this.test.item.extId }],
|
||||
tests: [{ src: test.src, testId: test.item.extId }],
|
||||
})));
|
||||
}
|
||||
|
||||
testActions.push(new Action('testing.reveal', localize('reveal test', 'Reveal in Test Explorer'), undefined, undefined, async () => {
|
||||
const path = [this.test];
|
||||
testActions.push(new Action('testing.gutter.reveal', localize('reveal test', 'Reveal in Test Explorer'), undefined, undefined, async () => {
|
||||
const path = [test];
|
||||
while (true) {
|
||||
const parentId = path[0].parent;
|
||||
const parent = parentId && this.collection.getNodeById(parentId);
|
||||
const parent = parentId && collection.getNodeById(parentId);
|
||||
if (!parent) {
|
||||
break;
|
||||
}
|
||||
|
@ -369,11 +443,112 @@ class RunTestDecoration extends Disposable implements ITestDecoration {
|
|||
await this.commandService.executeCommand('vscode.revealTestInExplorer', path.map(t => t.item.extId));
|
||||
}));
|
||||
|
||||
const breakpointActions = this.editor
|
||||
.getContribution<IBreakpointEditorContribution>(BREAKPOINT_EDITOR_CONTRIBUTION_ID)
|
||||
.getContextMenuActionsAtPosition(this.line, model);
|
||||
return testActions;
|
||||
}
|
||||
}
|
||||
|
||||
return breakpointActions.length ? [...testActions, new Separator(), ...breakpointActions] : testActions;
|
||||
class MultiRunTestDecoration extends RunTestDecoration implements ITestDecoration {
|
||||
constructor(
|
||||
private readonly tests: {
|
||||
test: IncrementalTestCollectionItem,
|
||||
collection: IMainThreadTestCollection,
|
||||
resultItem: TestResultItem | undefined,
|
||||
}[],
|
||||
editor: ICodeEditor,
|
||||
@ITestService testService: ITestService,
|
||||
@ICommandService commandService: ICommandService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
) {
|
||||
super(createRunTestDecoration(tests.map(t => t.test), tests.map(t => t.resultItem)), editor, testService, contextMenuService, commandService, configurationService);
|
||||
}
|
||||
|
||||
public override merge(test: IncrementalTestCollectionItem, collection: IMainThreadTestCollection, resultItem: TestResultItem | undefined): RunTestDecoration {
|
||||
this.tests.push({ collection, test, resultItem });
|
||||
this.editorDecoration = createRunTestDecoration(this.tests.map(t => t.test), this.tests.map(t => t.resultItem));
|
||||
return this;
|
||||
}
|
||||
|
||||
protected override getContextMenuActions() {
|
||||
const allActions: IAction[] = [];
|
||||
if (this.tests.some(({ test }) => test.item.runnable)) {
|
||||
allActions.push(new Action('testing.gutter.runAll', localize('run all test', 'Run All Tests'), undefined, undefined, () => this.defaultRun()));
|
||||
}
|
||||
|
||||
if (this.tests.some(({ test }) => test.item.debuggable)) {
|
||||
allActions.push(new Action('testing.gutter.debugAll', localize('debug all test', 'Debug All Tests'), undefined, undefined, () => this.defaultDebug()));
|
||||
}
|
||||
|
||||
const testSubmenus = this.tests.map(({ collection, test }) =>
|
||||
new SubmenuAction(test.item.extId, test.item.label, this.getTestContextMenuActions(collection, test)));
|
||||
|
||||
return Separator.join(allActions, testSubmenus);
|
||||
}
|
||||
|
||||
protected override defaultRun() {
|
||||
return this.testService.runTests({
|
||||
tests: this.tests
|
||||
.filter(({ test }) => test.item.runnable)
|
||||
.map(({ test }) => ({ testId: test.item.extId, src: test.src })),
|
||||
debug: false,
|
||||
});
|
||||
}
|
||||
|
||||
protected override defaultDebug() {
|
||||
return this.testService.runTests({
|
||||
tests: this.tests
|
||||
.filter(({ test }) => test.item.debuggable)
|
||||
.map(({ test }) => ({ testId: test.item.extId, src: test.src })),
|
||||
debug: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class RunSingleTestDecoration extends RunTestDecoration implements ITestDecoration {
|
||||
constructor(
|
||||
private readonly test: IncrementalTestCollectionItem,
|
||||
private readonly collection: IMainThreadTestCollection,
|
||||
editor: ICodeEditor,
|
||||
private readonly resultItem: TestResultItem | undefined,
|
||||
@ITestService testService: ITestService,
|
||||
@ICommandService commandService: ICommandService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
) {
|
||||
super(createRunTestDecoration([test], [resultItem]), editor, testService, contextMenuService, commandService, configurationService);
|
||||
}
|
||||
|
||||
public override merge(test: IncrementalTestCollectionItem, collection: IMainThreadTestCollection, resultItem: TestResultItem | undefined): RunTestDecoration {
|
||||
return new MultiRunTestDecoration([
|
||||
{ collection: this.collection, test: this.test, resultItem: this.resultItem },
|
||||
{ collection, test, resultItem },
|
||||
], this.editor, this.testService, this.commandService, this.contextMenuService, this.configurationService);
|
||||
}
|
||||
|
||||
protected override getContextMenuActions(e: IEditorMouseEvent) {
|
||||
return this.getTestContextMenuActions(this.collection, this.test);
|
||||
}
|
||||
|
||||
protected override defaultRun() {
|
||||
if (!this.test.item.runnable) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this.testService.runTests({
|
||||
tests: [{ testId: this.test.item.extId, src: this.test.src }],
|
||||
debug: false,
|
||||
});
|
||||
}
|
||||
|
||||
protected override defaultDebug() {
|
||||
if (!this.test.item.debuggable) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this.testService.runTests({
|
||||
tests: [{ testId: this.test.item.extId, src: this.test.src }],
|
||||
debug: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,12 +51,12 @@ import { HierarchicalByNameProjection } from 'vs/workbench/contrib/testing/brows
|
|||
import { IActionableTestTreeElement, isActionableTestTreeElement, ITestTreeProjection, TestExplorerTreeElement, TestItemTreeElement, TestTreeErrorMessage, TestTreeWorkspaceFolder } from 'vs/workbench/contrib/testing/browser/explorerProjections/index';
|
||||
import { testingHiddenIcon, testingStatesToIcons } from 'vs/workbench/contrib/testing/browser/icons';
|
||||
import { ITestExplorerFilterState, TestExplorerFilterState, TestingExplorerFilter } from 'vs/workbench/contrib/testing/browser/testingExplorerFilter';
|
||||
import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener';
|
||||
import { ITestingProgressUiService } from 'vs/workbench/contrib/testing/browser/testingProgressUiService';
|
||||
import { getTestingConfiguration, TestingConfigKeys } from 'vs/workbench/contrib/testing/common/configuration';
|
||||
import { TestExplorerStateFilter, TestExplorerViewMode, TestExplorerViewSorting, Testing, testStateNames } from 'vs/workbench/contrib/testing/common/constants';
|
||||
import { labelForTestInState, TestExplorerStateFilter, TestExplorerViewMode, TestExplorerViewSorting, Testing, testStateNames } from 'vs/workbench/contrib/testing/common/constants';
|
||||
import { TestIdPath, TestItemExpandState } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingContextKeys';
|
||||
import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener';
|
||||
import { cmpPriority, isFailedState, isStateWithResult } from 'vs/workbench/contrib/testing/common/testingStates';
|
||||
import { getPathForTestInResult, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { ITestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
|
@ -830,10 +830,7 @@ class TestExplorerActionRunner extends ActionRunner {
|
|||
}
|
||||
|
||||
const getLabelForTestTreeElement = (element: IActionableTestTreeElement) => {
|
||||
let label = localize({
|
||||
key: 'testing.treeElementLabel',
|
||||
comment: ['label then the unit tests state, for example "Addition Tests (Running)"'],
|
||||
}, '{0} ({1})', element.label, testStateNames[element.state]);
|
||||
let label = labelForTestInState(element.label, element.state);
|
||||
|
||||
if (element instanceof TestItemTreeElement) {
|
||||
if (element.duration !== undefined) {
|
||||
|
|
|
@ -64,7 +64,7 @@ import { TestingContextKeys } from 'vs/workbench/contrib/testing/common/testingC
|
|||
import { ITestingPeekOpener } from 'vs/workbench/contrib/testing/common/testingPeekOpener';
|
||||
import { isFailedState } from 'vs/workbench/contrib/testing/common/testingStates';
|
||||
import { buildTestUri, ParsedTestUri, parseTestUri, TestUriType } from 'vs/workbench/contrib/testing/common/testingUri';
|
||||
import { getPathForTestInResult, ITestResult, maxCountPriority, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { getPathForTestInResult, ITestResult, maxCountPriority, resultItemParents, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { ITestResultService, ResultChangeEvent } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
import { getAllTestsInHierarchy, ITestService } from 'vs/workbench/contrib/testing/common/testService';
|
||||
import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
@ -196,9 +196,11 @@ export class TestingPeekOpener extends Disposable implements ITestingPeekOpener
|
|||
|
||||
// don't show the peek if the user asked to only auto-open peeks for visible tests,
|
||||
// and this test is not in any of the editors' models.
|
||||
const testUri = evt.item.item.uri?.toString();
|
||||
if (cfg === AutoOpenPeekViewWhen.FailureVisible && (!testUri || !editors.some(e => e.getModel()?.uri.toString() === testUri))) {
|
||||
return;
|
||||
if (cfg === AutoOpenPeekViewWhen.FailureVisible) {
|
||||
const editorUris = new Set(editors.map(e => e.getModel()?.uri.toString()));
|
||||
if (!Iterable.some(resultItemParents(evt.result, evt.item), i => i.item.uri && editorUris.has(i.item.uri.toString()))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const controllers = editors.map(TestingOutputPeekController.get);
|
||||
|
@ -912,20 +914,12 @@ export class TestCaseElement implements ITreeElement {
|
|||
private readonly results: ITestResult,
|
||||
public readonly test: TestResultItem,
|
||||
) {
|
||||
for (const parent of this.parents()) {
|
||||
this.description = this.description
|
||||
? parent.item.label + flatTestItemDelimiter + this.description
|
||||
: parent.item.label;
|
||||
}
|
||||
}
|
||||
|
||||
private *parents() {
|
||||
for (
|
||||
let parent = this.test.parent && this.results.getStateById(this.test.parent);
|
||||
parent;
|
||||
parent = parent.parent && this.results.getStateById(parent.parent)
|
||||
) {
|
||||
yield parent;
|
||||
for (const parent of resultItemParents(results, test)) {
|
||||
if (parent !== test) {
|
||||
this.description = this.description
|
||||
? parent.item.label + flatTestItemDelimiter + this.description
|
||||
: parent.item.label;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ export const enum TestingConfigKeys {
|
|||
AutoOpenPeekView = 'testing.automaticallyOpenPeekView',
|
||||
AutoOpenPeekViewDuringAutoRun = 'testing.automaticallyOpenPeekViewDuringAutoRun',
|
||||
FollowRunningTest = 'testing.followRunningTest',
|
||||
DefaultGutterClickAction = 'testing.defaultGutterClickAction',
|
||||
}
|
||||
|
||||
export const enum AutoOpenPeekViewWhen {
|
||||
|
@ -25,6 +26,12 @@ export const enum AutoRunMode {
|
|||
OnlyPreviouslyRun = 'rerun',
|
||||
}
|
||||
|
||||
export const enum DefaultGutterClickAction {
|
||||
Run = 'run',
|
||||
Debug = 'debug',
|
||||
ContextMenu = 'contextMenu',
|
||||
}
|
||||
|
||||
export const testingConfiguation: IConfigurationNode = {
|
||||
id: 'testing',
|
||||
order: 21,
|
||||
|
@ -71,6 +78,20 @@ export const testingConfiguation: IConfigurationNode = {
|
|||
type: 'boolean',
|
||||
default: true,
|
||||
},
|
||||
[TestingConfigKeys.DefaultGutterClickAction]: {
|
||||
description: localize('testing.defaultGutterClickAction', 'Controls the action to take when left-clicking on a test decoration in the gutter.'),
|
||||
enum: [
|
||||
DefaultGutterClickAction.Run,
|
||||
DefaultGutterClickAction.Debug,
|
||||
DefaultGutterClickAction.ContextMenu,
|
||||
],
|
||||
enumDescriptions: [
|
||||
localize('testing.defaultGutterClickAction.run', 'Run the test.'),
|
||||
localize('testing.defaultGutterClickAction.debug', 'Debug the test.'),
|
||||
localize('testing.defaultGutterClickAction.contextMenu', 'Open the context menu for more options.'),
|
||||
],
|
||||
default: DefaultGutterClickAction.Run,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -80,6 +101,7 @@ export interface ITestingConfiguration {
|
|||
[TestingConfigKeys.AutoOpenPeekView]: AutoOpenPeekViewWhen;
|
||||
[TestingConfigKeys.AutoOpenPeekViewDuringAutoRun]: boolean;
|
||||
[TestingConfigKeys.FollowRunningTest]: boolean;
|
||||
[TestingConfigKeys.DefaultGutterClickAction]: DefaultGutterClickAction;
|
||||
}
|
||||
|
||||
export const getTestingConfiguration = <K extends TestingConfigKeys>(config: IConfigurationService, key: K) => config.getValue<ITestingConfiguration[K]>(key);
|
||||
|
|
|
@ -38,5 +38,10 @@ export const testStateNames: { [K in TestResultState]: string } = {
|
|||
[TestResultState.Queued]: localize('testState.queued', 'Queued'),
|
||||
[TestResultState.Running]: localize('testState.running', 'Running'),
|
||||
[TestResultState.Skipped]: localize('testState.skipped', 'Skipped'),
|
||||
[TestResultState.Unset]: localize('testState.unset', 'Unset'),
|
||||
[TestResultState.Unset]: localize('testState.unset', 'Not yet run'),
|
||||
};
|
||||
|
||||
export const labelForTestInState = (label: string, state: TestResultState) => localize({
|
||||
key: 'testing.treeElementLabel',
|
||||
comment: ['label then the unit tests state, for example "Addition Tests (Running)"'],
|
||||
}, '{0} ({1})', label, testStateNames[state]);
|
||||
|
|
|
@ -69,19 +69,21 @@ export interface ITestResult {
|
|||
toJSON(): ISerializedTestResults | undefined;
|
||||
}
|
||||
|
||||
export const getPathForTestInResult = (test: TestResultItem, results: ITestResult): TestIdPath => {
|
||||
const path = [test];
|
||||
while (true) {
|
||||
const parentId = path[0].parent;
|
||||
const parent = parentId && results.getStateById(parentId);
|
||||
if (!parent) {
|
||||
break;
|
||||
}
|
||||
export const resultItemParents = function* (results: ITestResult, item: TestResultItem) {
|
||||
let i: TestResultItem | undefined = item;
|
||||
while (i) {
|
||||
yield i;
|
||||
i = i.parent ? results.getStateById(i.parent) : undefined;
|
||||
}
|
||||
};
|
||||
|
||||
path.unshift(parent);
|
||||
export const getPathForTestInResult = (test: TestResultItem, results: ITestResult): TestIdPath => {
|
||||
const path: TestIdPath = [];
|
||||
for (const node of resultItemParents(results, test)) {
|
||||
path.unshift(node.item.extId);
|
||||
}
|
||||
|
||||
return path.map(t => t.item.extId);
|
||||
return path;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -69,10 +69,10 @@ export interface IMainThreadTestCollection extends AbstractIncrementalTestCollec
|
|||
* Iterates through the item and its parents to the root.
|
||||
*/
|
||||
export const getCollectionItemParents = function* (collection: IMainThreadTestCollection, item: InternalTestItem) {
|
||||
let p: InternalTestItem | undefined = item;
|
||||
while (p) {
|
||||
yield p;
|
||||
p = p.parent ? collection.getNodeById(p.parent) : undefined;
|
||||
let i: InternalTestItem | undefined = item;
|
||||
while (i) {
|
||||
yield i;
|
||||
i = i.parent ? collection.getNodeById(i.parent) : undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import { Lazy } from 'vs/base/common/lazy';
|
|||
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { ITestTaskState, TestResultItem } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { HydratedTestResult, LiveOutputController, LiveTestResult, makeEmptyCounts, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { getPathForTestInResult, HydratedTestResult, LiveOutputController, LiveTestResult, makeEmptyCounts, resultItemParents, TestResultItemChange, TestResultItemChangeReason } from 'vs/workbench/contrib/testing/common/testResult';
|
||||
import { TestResultService } from 'vs/workbench/contrib/testing/common/testResultService';
|
||||
import { InMemoryResultStorage, ITestResultStorage } from 'vs/workbench/contrib/testing/common/testResultStorage';
|
||||
import { Convert, ReExportedTestRunState as TestRunState, TestItemImpl, TestResultState, testStubs, testStubsChain } from 'vs/workbench/contrib/testing/common/testStubs';
|
||||
|
@ -291,4 +291,24 @@ suite('Workbench - Test Results Service', () => {
|
|||
assert.deepStrictEqual(results.results, [r, hydrated1, hydrated2]);
|
||||
});
|
||||
});
|
||||
|
||||
test('resultItemParents', () => {
|
||||
assert.deepStrictEqual([...resultItemParents(r, r.getStateById('id-aa')!)], [
|
||||
r.getStateById('id-aa'),
|
||||
r.getStateById('id-a'),
|
||||
r.getStateById('id-root'),
|
||||
]);
|
||||
|
||||
assert.deepStrictEqual([...resultItemParents(r, r.getStateById('id-root')!)], [
|
||||
r.getStateById('id-root'),
|
||||
]);
|
||||
});
|
||||
|
||||
test('getPathForTestInResult', () => {
|
||||
assert.deepStrictEqual([...getPathForTestInResult(r.getStateById('id-aa')!, r)], [
|
||||
'id-root',
|
||||
'id-a',
|
||||
'id-aa',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import 'vs/css!./gettingStarted';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IInstantiationService, optional } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEditorInputSerializer, IEditorOpenContext } from 'vs/workbench/common/editor';
|
||||
import { Disposable, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
|
@ -17,7 +17,7 @@ import { IThemeService, registerThemingParticipant, ThemeIcon } from 'vs/platfor
|
|||
import { welcomePageBackground, welcomePageProgressBackground, welcomePageProgressForeground, welcomePageTileBackground, welcomePageTileHoverBackground, welcomePageTileShadow } from 'vs/workbench/contrib/welcome/page/browser/welcomePageColors';
|
||||
import { activeContrastBorder, buttonBackground, buttonForeground, buttonHoverBackground, contrastBorder, descriptionForeground, focusBorder, foreground, textLinkActiveForeground, textLinkForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { ITelemetryService, lastSessionDateStorageKey } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { firstSessionDateStorageKey, ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
|
||||
import { gettingStartedCheckedCodicon, gettingStartedUncheckedCodicon } from 'vs/workbench/contrib/welcome/gettingStarted/browser/gettingStartedIcons';
|
||||
import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener';
|
||||
|
@ -27,7 +27,6 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag
|
|||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ContextKeyExpr, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ITASExperimentService } from 'vs/workbench/services/experiment/common/experimentService';
|
||||
import { IRecentFolder, IRecentlyOpened, IRecentWorkspace, isRecentFolder, isRecentWorkspace, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
|
@ -103,7 +102,6 @@ export class GettingStartedPage extends EditorPane {
|
|||
private container: HTMLElement;
|
||||
|
||||
private contextService: IContextKeyService;
|
||||
private tasExperimentService?: ITASExperimentService;
|
||||
private previousSelection?: string;
|
||||
private recentlyOpened: Promise<IRecentlyOpened>;
|
||||
private selectedStepElement?: HTMLDivElement;
|
||||
|
@ -144,7 +142,6 @@ export class GettingStartedPage extends EditorPane {
|
|||
@IHostService private readonly hostService: IHostService,
|
||||
@IWebviewService private readonly webviewService: IWebviewService,
|
||||
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
|
||||
@optional(ITASExperimentService) tasExperimentService: ITASExperimentService,
|
||||
) {
|
||||
|
||||
super(GettingStartedPage.ID, telemetryService, themeService, storageService);
|
||||
|
@ -158,9 +155,6 @@ export class GettingStartedPage extends EditorPane {
|
|||
this.stepMediaComponent = $('.getting-started-media');
|
||||
this.stepMediaComponent.id = generateUuid();
|
||||
|
||||
|
||||
this.tasExperimentService = tasExperimentService;
|
||||
|
||||
this.contextService = this._register(contextService.createScoped(this.container));
|
||||
inGettingStartedContext.bindTo(this.contextService).set(true);
|
||||
|
||||
|
@ -797,28 +791,19 @@ export class GettingStartedPage extends EditorPane {
|
|||
const someStepsComplete = this.gettingStartedCategories.some(categry => categry.content.type === 'steps' && categry.content.stepsComplete);
|
||||
if (!someStepsComplete && !this.hasScrolledToFirstCategory) {
|
||||
|
||||
const fistContentBehaviour =
|
||||
!this.storageService.get(lastSessionDateStorageKey, StorageScope.GLOBAL) // isNewUser ?
|
||||
? 'openToFirstCategory'
|
||||
: await Promise.race([
|
||||
this.tasExperimentService?.getTreatment<'index' | 'openToFirstCategory'>('GettingStartedFirstContent'),
|
||||
new Promise<'index'>(resolve => setTimeout(() => resolve('index'), 1000)),
|
||||
]);
|
||||
const firstSessionDateString = this.storageService.get(firstSessionDateStorageKey, StorageScope.GLOBAL) || new Date().toUTCString();
|
||||
const daysSinceFirstSession = ((+new Date()) - (+new Date(firstSessionDateString))) / 1000 / 60 / 60 / 24;
|
||||
const fistContentBehaviour = daysSinceFirstSession < 1 ? 'openToFirstCategory' : 'index';
|
||||
|
||||
if (this.gettingStartedCategories.some(category => category.content.type === 'steps' && category.content.stepsComplete)) {
|
||||
this.setSlide('categories');
|
||||
return;
|
||||
} else {
|
||||
if (fistContentBehaviour === 'openToFirstCategory') {
|
||||
const first = this.gettingStartedCategories.find(category => category.content.type === 'steps');
|
||||
this.hasScrolledToFirstCategory = true;
|
||||
if (first) {
|
||||
this.currentCategory = first;
|
||||
this.editorInput.selectedCategory = this.currentCategory?.id;
|
||||
this.buildCategorySlide(this.editorInput.selectedCategory);
|
||||
this.setSlide('details');
|
||||
return;
|
||||
}
|
||||
if (fistContentBehaviour === 'openToFirstCategory') {
|
||||
const first = this.gettingStartedCategories.find(category => category.content.type === 'steps');
|
||||
this.hasScrolledToFirstCategory = true;
|
||||
if (first) {
|
||||
this.currentCategory = first;
|
||||
this.editorInput.selectedCategory = this.currentCategory?.id;
|
||||
this.buildCategorySlide(this.editorInput.selectedCategory);
|
||||
this.setSlide('details');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ import { localize } from 'vs/nls';
|
|||
import { IStartEntry, IWalkthrough } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
|
||||
const titleTranslated = localize('title', "Title");
|
||||
|
||||
export const walkthroughsExtensionPoint = ExtensionsRegistry.registerExtensionPoint<IWalkthrough[]>({
|
||||
extensionPoint: 'walkthroughs',
|
||||
jsonSchema: {
|
||||
|
@ -64,10 +66,10 @@ export const walkthroughsExtensionPoint = ExtensionsRegistry.registerExtensionPo
|
|||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
description: localize('walkthroughs.steps.description', "Description of step. Supports ``preformatted``, __italic__, and **bold** text. Use markdown-style links for commands or external links: [Title](command:myext.command), [Title](command:toSide:myext.command), or [Title](https://aka.ms). Links on their own line will be rendered as buttons.")
|
||||
description: localize('walkthroughs.steps.description.interpolated', "Description of step. Supports ``preformatted``, __italic__, and **bold** text. Use markdown-style links for commands or external links: {0}, {1}, or {2}. Links on their own line will be rendered as buttons.", `[${titleTranslated}](command:myext.command)`, `[${titleTranslated}](command:toSide:myext.command)`, `[${titleTranslated}](https://aka.ms)`)
|
||||
},
|
||||
button: {
|
||||
deprecationMessage: localize('walkthroughs.steps.button.deprecated', "Deprecated. Use markdown links in the description instead, i.e. [Title](command:myext.command), [Title](command:toSide:myext.command), or [Title](https://aka.ms), "),
|
||||
deprecationMessage: localize('walkthroughs.steps.button.deprecated.interpolated', "Deprecated. Use markdown links in the description instead, i.e. {0}, {1}, or {2}", `[${titleTranslated}](command:myext.command)`, `[${titleTranslated}](command:toSide:myext.command)`, `[${titleTranslated}](https://aka.ms)`),
|
||||
},
|
||||
media: {
|
||||
type: 'object',
|
||||
|
|
|
@ -118,6 +118,8 @@ export const startEntries: GettingStartedStartEntryContent = [
|
|||
},
|
||||
];
|
||||
|
||||
const Button = (title: string, href: string) => `[${title}](${href})`;
|
||||
|
||||
export const walkthroughs: GettingStartedWalkthroughContent = [
|
||||
{
|
||||
id: 'Setup',
|
||||
|
@ -131,14 +133,17 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'pickColorTheme',
|
||||
title: localize('gettingStarted.pickColor.title', "Choose the look you want"),
|
||||
description: localize('gettingStarted.pickColor.description', "The right color palette helps you focus on your code, is easy on your eyes, and is simply more fun to use.\n[Browse Color Themes](command:workbench.action.selectTheme)"),
|
||||
completionEvents: ['onSettingChanged:workbench.colorTheme'],
|
||||
description: localize('gettingStarted.pickColor.description.interpolated', "The right color palette helps you focus on your code, is easy on your eyes, and is simply more fun to use.\n{0}", Button(localize('titleID', "Browse Color Themes"), 'command:workbench.action.selectTheme')),
|
||||
completionEvents: [
|
||||
'onSettingChanged:workbench.colorTheme',
|
||||
'onCommand:workbench.action.selectTheme'
|
||||
],
|
||||
media: { type: 'markdown', path: 'example_markdown_media', }
|
||||
},
|
||||
{
|
||||
id: 'findLanguageExtensions',
|
||||
title: localize('gettingStarted.findLanguageExts.title', "Rich support for all your languages"),
|
||||
description: localize('gettingStarted.findLanguageExts.description', "Code smarter with syntax highlighting, code completion, linting and debugging. While many languages are built-in, many more can be added as extensions.\n[Browse Language Extensions](command:workbench.extensions.action.showLanguageExtensions)"),
|
||||
description: localize('gettingStarted.findLanguageExts.description.interpolated', "Code smarter with syntax highlighting, code completion, linting and debugging. While many languages are built-in, many more can be added as extensions.\n{0}", Button(localize('browseLangExts', "Browse Language Extensions"), 'command:workbench.extensions.action.showLanguageExtensions')),
|
||||
media: {
|
||||
type: 'image', altText: 'Language extensions', path: {
|
||||
dark: 'dark/languageExtensions.png',
|
||||
|
@ -150,7 +155,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'commandPaletteTask',
|
||||
title: localize('gettingStarted.commandPalette.title', "One shortcut to access everything"),
|
||||
description: localize('gettingStarted.commandPalette.description', "Commands Palette is the keyboard way to accomplish any task in VS Code. **Practice** by looking up your frequently used commands to save time and keep in the flow.\n[Open Command Palette](command:workbench.action.showCommands)\n__Try searching for 'view toggle'.__"),
|
||||
description: localize('gettingStarted.commandPalette.description.interpolated', "Commands Palette is the keyboard way to accomplish any task in VS Code. **Practice** by looking up your frequently used commands to save time and keep in the flow.\n{0}\n__Try searching for 'view toggle'.__", Button(localize('commandPalette', "Open Command Palette"), 'command:workbench.action.showCommands')),
|
||||
media: {
|
||||
type: 'image', altText: 'Command Palette overlay for searching and executing commands.', path: {
|
||||
dark: 'dark/commandPalette.png',
|
||||
|
@ -162,7 +167,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'workspaceTrust',
|
||||
title: localize('gettingStarted.workspaceTrust.title', "Safely browse and edit code"),
|
||||
description: localize('gettingStarted.workspaceTrust.description', "[Workspace Trust](https://github.com/microsoft/vscode-docs/blob/workspaceTrust/docs/editor/workspace-trust.md) lets you decide whether your project folders should **allow or restrict** automatic code execution __(required for extensions, debugging, etc)__.\nOpening a file/folder will prompt to grant trust. You can always [enable trust](command:toSide:workbench.action.manageTrustedDomain) later."),
|
||||
description: localize('gettingStarted.workspaceTrust.description.interpolated', "{0} lets you decide whether your project folders should **allow or restrict** automatic code execution __(required for extensions, debugging, etc)__.\nOpening a file/folder will prompt to grant trust. You can always {1} later.", Button(localize('workspaceTrust', "Workspace Trust"), 'https://github.com/microsoft/vscode-docs/blob/workspaceTrust/docs/editor/workspace-trust.md'), Button(localize('enableTrust', "enable trust"), 'command:toSide:workbench.action.manageTrustedDomain')),
|
||||
when: '!isWorkspaceTrusted && workspaceFolderCount == 0',
|
||||
media: {
|
||||
type: 'image', altText: 'Workspace Trust editor in Restricted mode and a primary button for switching to Trusted mode.', path: {
|
||||
|
@ -175,7 +180,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'pickAFolderTask-Mac',
|
||||
title: localize('gettingStarted.setup.OpenFolder.title', "Open up your code"),
|
||||
description: localize('gettingStarted.setup.OpenFolder.description', "You're all set to start coding. Open a project folder to get your files into VS Code.\n[Pick a Folder](command:workbench.action.files.openFileFolder)"),
|
||||
description: localize('gettingStarted.setup.OpenFolder.description.interpolated', "You're all set to start coding. Open a project folder to get your files into VS Code.\n{0}", Button(localize('pickFolder', "Pick a Folder"), 'command:workbench.action.files.openFileFolder')),
|
||||
when: 'isMac && workspaceFolderCount == 0',
|
||||
media: {
|
||||
type: 'image', altText: 'Explorer view showing buttons for opening folder and cloning repository.', path: {
|
||||
|
@ -188,7 +193,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'pickAFolderTask-Other',
|
||||
title: localize('gettingStarted.setup.OpenFolder.title', "Open up your code"),
|
||||
description: localize('gettingStarted.setup.OpenFolder.description2', "You're all set to start coding. Open a project folder to get your files into VS Code.\n[Pick a Folder](command:workbench.action.files.openFolder)"),
|
||||
description: localize('gettingStarted.setup.OpenFolder.description.interpolated', "You're all set to start coding. Open a project folder to get your files into VS Code.\n{0}", Button(localize('pickFolder', "Pick a Folder"), 'command:workbench.action.files.openFolder')),
|
||||
when: '!isMac && workspaceFolderCount == 0',
|
||||
media: {
|
||||
type: 'image', altText: 'Explorer view showing buttons for opening folder and cloning repository.', path: {
|
||||
|
@ -201,7 +206,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'quickOpen',
|
||||
title: localize('gettingStarted.quickOpen.title', "Quickly navigate between your files"),
|
||||
description: localize('gettingStarted.quickOpen.description', "Navigate between files in an instant with one keystroke. Tip: Open multiple files by pressing the right arrow key.\n[Quick Open a File](command:toSide:workbench.action.quickOpen)"),
|
||||
description: localize('gettingStarted.quickOpen.description.interpolated', "Navigate between files in an instant with one keystroke. Tip: Open multiple files by pressing the right arrow key.\n{0}", Button(localize('quickOpen', "Quick Open a File"), 'command:toSide:workbench.action.quickOpen')),
|
||||
when: 'workspaceFolderCount != 0',
|
||||
media: {
|
||||
type: 'image', altText: 'Go to file in quick search.', path: {
|
||||
|
@ -227,7 +232,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'playground',
|
||||
title: localize('gettingStarted.playground.title', "Redefine your editing skills"),
|
||||
description: localize('gettingStarted.playground.description', "Want to code faster and smarter? Practice powerful code editing features in the interactive playground.\n[Open Interactive Playground](command:toSide:workbench.action.showInteractivePlayground)"),
|
||||
description: localize('gettingStarted.playground.description.interpolated', "Want to code faster and smarter? Practice powerful code editing features in the interactive playground.\n{0}", Button(localize('openInteractivePlayground', "Open Interactive Playground"), 'command:toSide:workbench.action.showInteractivePlayground')),
|
||||
media: {
|
||||
type: 'image', altText: 'Interactive Playground.', path: {
|
||||
dark: 'dark/playground.png',
|
||||
|
@ -239,7 +244,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'terminal',
|
||||
title: localize('gettingStarted.terminal.title', "Convenient built-in terminal"),
|
||||
description: localize('gettingStarted.terminal.description', "Quickly run shell commands and monitor build output, right next to your code.\n[Show Terminal Panel](command:workbench.action.terminal.toggleTerminal)"),
|
||||
description: localize('gettingStarted.terminal.description.interpolated', "Quickly run shell commands and monitor build output, right next to your code.\n{0}", Button(localize('showTerminal', "Show Terminal Panel"), 'command:workbench.action.terminal.toggleTerminal')),
|
||||
when: 'remoteName != codespaces && !terminalIsOpen',
|
||||
media: {
|
||||
type: 'image', altText: 'Integrated terminal running a few npm commands', path: {
|
||||
|
@ -252,7 +257,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'extensions',
|
||||
title: localize('gettingStarted.extensions.title', "Limitless extensibility"),
|
||||
description: localize('gettingStarted.extensions.description', "Extensions are VS Code's power-ups. They range from handy productivity hacks, expanding out-of-the-box features, to adding completely new capabilities.\n[Browse Recommended Extensions](command:workbench.extensions.action.showRecommendedExtensions)"),
|
||||
description: localize('gettingStarted.extensions.description.interpolated', "Extensions are VS Code's power-ups. They range from handy productivity hacks, expanding out-of-the-box features, to adding completely new capabilities.\n{0}", Button(localize('browseRecommended', "Browse Recommended Extensions"), 'command:workbench.extensions.action.showRecommendedExtensions')),
|
||||
media: {
|
||||
type: 'image', altText: 'VS Code extension marketplace with featured language extensions', path: {
|
||||
dark: 'dark/extensions.png',
|
||||
|
@ -264,7 +269,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'settings',
|
||||
title: localize('gettingStarted.settings.title', "Tune your settings"),
|
||||
description: localize('gettingStarted.settings.description', "Tweak every aspect of VS Code and your extensions to your liking. Commonly used settings are listed first to get you started.\n[Tweak my Settings](command:toSide:workbench.action.openSettings)"),
|
||||
description: localize('gettingStarted.settings.description.interpolated', "Tweak every aspect of VS Code and your extensions to your liking. Commonly used settings are listed first to get you started.\n{0}", Button(localize('tweakSettings', "Tweak my Settings"), 'command:toSide:workbench.action.openSettings')),
|
||||
media: {
|
||||
type: 'image', altText: 'VS Code Settings', path: {
|
||||
dark: 'dark/settings.png',
|
||||
|
@ -276,7 +281,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'settingsSync',
|
||||
title: localize('gettingStarted.settingsSync.title', "Sync your stuff across devices"),
|
||||
description: localize('gettingStarted.settingsSync.description', "Never lose the perfect VS Code setup! Settings Sync will back up and share settings, keybindings & extensions across several installations.\n[Enable Settings Sync](command:workbench.userDataSync.actions.turnOn)"),
|
||||
description: localize('gettingStarted.settingsSync.description.interpolated', "Never lose the perfect VS Code setup! Settings Sync will back up and share settings, keybindings & extensions across several installations.\n{0}", Button(localize('enableSync', "Enable Settings Sync"), 'command:workbench.userDataSync.actions.turnOn')),
|
||||
when: 'syncStatus != uninitialized',
|
||||
completionEvents: ['onEvent:sync-enabled'],
|
||||
media: {
|
||||
|
@ -290,7 +295,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'videoTutorial',
|
||||
title: localize('gettingStarted.videoTutorial.title', "Lean back and learn"),
|
||||
description: localize('gettingStarted.videoTutorial.description', "Watch the first in a series of short & practical video tutorials for VS Code's key features.\n[Watch Tutorial](https://aka.ms/vscode-getting-started-video)"),
|
||||
description: localize('gettingStarted.videoTutorial.description.interpolated', "Watch the first in a series of short & practical video tutorials for VS Code's key features.\n{0}", Button(localize('watch', "Watch Tutorial"), 'https://aka.ms/vscode-getting-started-video')),
|
||||
media: { type: 'image', altText: 'VS Code Settings', path: 'tutorialVideo.png' },
|
||||
}
|
||||
]
|
||||
|
@ -308,7 +313,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'splitview',
|
||||
title: localize('gettingStarted.splitview.title', "Side by side editing"),
|
||||
description: localize('gettingStarted.splitview.description', "Make the most of your screen estate by opening files side by side, vertically and horizontally.\n[Split Editor](command:workbench.action.splitEditor)"),
|
||||
description: localize('gettingStarted.splitview.description.interpolated', "Make the most of your screen estate by opening files side by side, vertically and horizontally.\n{0}", Button(localize('splitEditor', "Split Editor"), 'command:workbench.action.splitEditor')),
|
||||
media: {
|
||||
type: 'image', altText: 'Multiple editors in split view.', path: {
|
||||
dark: 'dark/splitview.png',
|
||||
|
@ -320,7 +325,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'debugging',
|
||||
title: localize('gettingStarted.debug.title', "Watch your code in action"),
|
||||
description: localize('gettingStarted.debug.description', "Accelerate your edit, build, test, and debug loop by setting up a launch configuration.\n[Run your Project](command:workbench.action.debug.selectandstart)"),
|
||||
description: localize('gettingStarted.debug.description.interpolated', "Accelerate your edit, build, test, and debug loop by setting up a launch configuration.\n{0}", Button(localize('runProject', "Run your Project"), 'command:workbench.action.debug.selectandstart')),
|
||||
when: 'workspaceFolderCount != 0',
|
||||
media: {
|
||||
type: 'image', altText: 'Run and debug view.', path: {
|
||||
|
@ -333,7 +338,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'scmClone',
|
||||
title: localize('gettingStarted.scm.title', "Track your code with Git"),
|
||||
description: localize('gettingStarted.scmClone.description', "Set up the built-in version control for your project to track your changes and collaborate with others.\n[Clone Repository](command:git.clone)"),
|
||||
description: localize('gettingStarted.scmClone.description.interpolated', "Set up the built-in version control for your project to track your changes and collaborate with others.\n{0}", Button(localize('cloneRepo', "Clone Repository"), 'command:git.clone')),
|
||||
when: 'config.git.enabled && !git.missing && workspaceFolderCount == 0',
|
||||
media: {
|
||||
type: 'image', altText: 'Source Control view.', path: {
|
||||
|
@ -346,7 +351,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'scmSetup',
|
||||
title: localize('gettingStarted.scm.title', "Track your code with Git"),
|
||||
description: localize('gettingStarted.scmSetup.description', "Set up the built-in version control for your project to track your changes and collaborate with others.\n[Initialize Git Repository](command:git.init)"),
|
||||
description: localize('gettingStarted.scmSetup.description.interpolated', "Set up the built-in version control for your project to track your changes and collaborate with others.\n{0}", Button(localize('initRepo', "Initialize Git Repository"), 'command:git.init')),
|
||||
when: 'config.git.enabled && !git.missing && workspaceFolderCount != 0 && gitOpenRepositoryCount == 0',
|
||||
media: {
|
||||
type: 'image', altText: 'Source Control view.', path: {
|
||||
|
@ -359,7 +364,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'scm',
|
||||
title: localize('gettingStarted.scm.title', "Track your code with Git"),
|
||||
description: localize('gettingStarted.scm.description', "No more looking up Git commands! Git and GitHub workflows are seamlessly integrated.\n[Open Source Control](command:workbench.view.scm)"),
|
||||
description: localize('gettingStarted.scm.description.interpolated', "No more looking up Git commands! Git and GitHub workflows are seamlessly integrated.\n{0}", Button(localize('openSCM', "Open Source Control"), 'command:workbench.view.scm')),
|
||||
when: 'config.git.enabled && !git.missing && workspaceFolderCount != 0 && gitOpenRepositoryCount != 0 && activeViewlet != \'workbench.view.scm\'',
|
||||
media: {
|
||||
type: 'image', altText: 'Source Control view.', path: {
|
||||
|
@ -373,7 +378,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
id: 'tasks',
|
||||
title: localize('gettingStarted.tasks.title', "Automate your project tasks"),
|
||||
when: 'workspaceFolderCount != 0',
|
||||
description: localize('gettingStarted.tasks.description', "Create tasks for your common workflows and enjoy the integrated experience of running scripts and automatically checking results.\n[Run Auto-detected Tasks](command:workbench.action.tasks.runTask)"),
|
||||
description: localize('gettingStarted.tasks.description.interpolated', "Create tasks for your common workflows and enjoy the integrated experience of running scripts and automatically checking results.\n{0}", Button(localize('runTasks', "Run Auto-detected Tasks"), 'command:workbench.action.tasks.runTask')),
|
||||
media: {
|
||||
type: 'image', altText: 'Task runner.', path: {
|
||||
dark: 'dark/tasks.png',
|
||||
|
@ -385,7 +390,7 @@ export const walkthroughs: GettingStartedWalkthroughContent = [
|
|||
{
|
||||
id: 'shortcuts',
|
||||
title: localize('gettingStarted.shortcuts.title', "Customize your shortcuts"),
|
||||
description: localize('gettingStarted.shortcuts.description', "Once you have discovered your favorite commands, create custom keyboard shortcuts for instant access.\n[Keyboard Shortcuts](command:toSide:workbench.action.openGlobalKeybindings)"),
|
||||
description: localize('gettingStarted.shortcuts.description.interpolated', "Once you have discovered your favorite commands, create custom keyboard shortcuts for instant access.\n{0}", Button(localize('keyboardShortcuts', "Keyboard Shortcuts"), 'command:toSide:workbench.action.openGlobalKeybindings')),
|
||||
media: {
|
||||
type: 'image', altText: 'Interactive shortcuts.', path: {
|
||||
dark: 'dark/shortcuts.png',
|
||||
|
|
|
@ -25,7 +25,7 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
|
|||
'enumDescriptions': [
|
||||
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.none' }, "Start without an editor."),
|
||||
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.welcomePage' }, "Open the legacy Welcome page."),
|
||||
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.readme' }, "Open the README when opening a folder that contains one, fallback to 'welcomePage' otherwise."),
|
||||
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.readme' }, "Open the README when opening a folder that contains one, fallback to 'welcomePage' otherwise. Note: This is only observed as a global ccnfiguration, it will be ignored if set in a workspace or folder configuration."),
|
||||
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.newUntitledFile' }, "Open a new untitled file (only applies when opening an empty window)."),
|
||||
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.welcomePageInEmptyWorkbench' }, "Open the legacy Welcome page when opening an empty workbench."),
|
||||
localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'workbench.startupEditor.gettingStarted' }, "Open the new Welcome Page with content to aid in getting started with VS Code and extensions."),
|
||||
|
|
|
@ -374,7 +374,12 @@ export class WorkspaceTrustUXHandler extends Disposable implements IWorkbenchCon
|
|||
ariaLabel = trusted ? localize('status.ariaTrustedWindow', "This window is trusted.") :
|
||||
localize('status.ariaUntrustedWindow', "Restricted Mode: Some features are disabled because this window is not trusted.");
|
||||
toolTip = trusted ? ariaLabel : {
|
||||
value: localize('status.tooltipUntrustedWindow', "Running in Restricted Mode\n\n\Some [features are disabled](command:{0}) because this [window is not trusted](command:{1}).", LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID, MANAGE_TRUST_COMMAND_ID),
|
||||
value: localize(
|
||||
{ key: 'status.tooltipUntrustedWindow2', comment: ['[abc]({n}) are links. Only translate `features are disabled` and `window is not trusted`. Do not change brackets and parentheses or {n}'] },
|
||||
"Running in Restricted Mode\n\nSome [features are disabled]({0}) because this [window is not trusted]({1}).",
|
||||
`command:${LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID}`,
|
||||
`command:${MANAGE_TRUST_COMMAND_ID}`
|
||||
),
|
||||
isTrusted: true,
|
||||
supportThemeIcons: true
|
||||
};
|
||||
|
@ -384,7 +389,12 @@ export class WorkspaceTrustUXHandler extends Disposable implements IWorkbenchCon
|
|||
ariaLabel = trusted ? localize('status.ariaTrustedFolder', "This folder is trusted.") :
|
||||
localize('status.ariaUntrustedFolder', "Restricted Mode: Some features are disabled because this folder is not trusted.");
|
||||
toolTip = trusted ? ariaLabel : {
|
||||
value: localize('status.tooltipUntrustedFolder', "Running in Restricted Mode\n\n\Some [features are disabled](command:{0}) because this [folder is not trusted](command:{1}).", LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID, MANAGE_TRUST_COMMAND_ID),
|
||||
value: localize(
|
||||
{ key: 'status.tooltipUntrustedFolder2', comment: ['[abc]({n}) are links. Only translate `features are disabled` and `folder is not trusted`. Do not change brackets and parentheses or {n}'] },
|
||||
"Running in Restricted Mode\n\nSome [features are disabled]({0}) because this [folder is not trusted]({1}).",
|
||||
`command:${LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID}`,
|
||||
`command:${MANAGE_TRUST_COMMAND_ID}`
|
||||
),
|
||||
isTrusted: true,
|
||||
supportThemeIcons: true
|
||||
};
|
||||
|
@ -394,7 +404,12 @@ export class WorkspaceTrustUXHandler extends Disposable implements IWorkbenchCon
|
|||
ariaLabel = trusted ? localize('status.ariaTrustedWorkspace', "This workspace is trusted.") :
|
||||
localize('status.ariaUntrustedWorkspace', "Restricted Mode: Some features are disabled because this workspace is not trusted.");
|
||||
toolTip = trusted ? ariaLabel : {
|
||||
value: localize('status.tooltipUntrustedWorkspace', "Running in Restricted Mode\n\n\Some [features are disabled](command:{0}) because this [workspace is not trusted](command:{1}).", LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID, MANAGE_TRUST_COMMAND_ID),
|
||||
value: localize(
|
||||
{ key: 'status.tooltipUntrustedWorkspace2', comment: ['[abc]({n}) are links. Only translate `features are disabled` and `workspace is not trusted`. Do not change brackets and parentheses or {n}'] },
|
||||
"Running in Restricted Mode\n\nSome [features are disabled]({0}) because this [workspace is not trusted]({1}).",
|
||||
`command:${LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID}`,
|
||||
`command:${MANAGE_TRUST_COMMAND_ID}`
|
||||
),
|
||||
isTrusted: true,
|
||||
supportThemeIcons: true
|
||||
};
|
||||
|
@ -637,7 +652,7 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
|
|||
},
|
||||
[WORKSPACE_TRUST_EMPTY_WINDOW]: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
default: true,
|
||||
included: !isWeb,
|
||||
markdownDescription: localize('workspace.trust.emptyWindow.description', "Controls whether or not the empty window is trusted by default within VS Code. When used with `#{0}#`, you can enable the full functionality of VS Code without prompting in an empty window.", WORKSPACE_TRUST_UNTRUSTED_FILES),
|
||||
scope: ConfigurationScope.APPLICATION
|
||||
|
|
|
@ -823,13 +823,13 @@ export class WorkspaceTrustEditor extends EditorPane {
|
|||
[
|
||||
localize('untrustedTasks', "Tasks are disabled"),
|
||||
localize('untrustedDebugging', "Debugging is disabled"),
|
||||
localize('untrustedExtensions', "[{0} extensions](command:{1}) are disabled or have limited functionality", numExtensions, LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID)
|
||||
localize('untrustedExtensions', "[{0} extensions]({1}) are disabled or have limited functionality", numExtensions, `command:${LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID}`)
|
||||
] :
|
||||
[
|
||||
localize('untrustedTasks', "Tasks are disabled"),
|
||||
localize('untrustedDebugging', "Debugging is disabled"),
|
||||
numSettings ? localize('untrustedSettings', "[{0} workspace settings](command:{1}) are not applied", numSettings, 'settings.filterUntrusted') : localize('no untrustedSettings', "Workspace settings requiring trust are not applied"),
|
||||
localize('untrustedExtensions', "[{0} extensions](command:{1}) are disabled or have limited functionality", numExtensions, LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID)
|
||||
numSettings ? localize('untrustedSettings', "[{0} workspace settings]({1}) are not applied", numSettings, 'command:settings.filterUntrusted') : localize('no untrustedSettings', "Workspace settings requiring trust are not applied"),
|
||||
localize('untrustedExtensions', "[{0} extensions]({1}) are disabled or have limited functionality", numExtensions, `command:${LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID}`)
|
||||
];
|
||||
this.renderLimitationsListElement(untrustedContainer, untrustedContainerItems, xListIcon.classNamesArray);
|
||||
|
||||
|
|
|
@ -235,8 +235,8 @@ export class WorkspaceTrustManagementService extends Disposable implements IWork
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!this._initialized) {
|
||||
return false;
|
||||
if (this.environmentService.extensionTestsLocationURI) {
|
||||
return true; // trust running tests with vscode-test
|
||||
}
|
||||
|
||||
// Remote - remote authority explicitly sets workspace trust
|
||||
|
@ -244,16 +244,16 @@ export class WorkspaceTrustManagementService extends Disposable implements IWork
|
|||
return this._remoteAuthority.options.isTrusted;
|
||||
}
|
||||
|
||||
if (this.environmentService.extensionTestsLocationURI) {
|
||||
return true; // trust running tests with vscode-test
|
||||
}
|
||||
|
||||
if (this.workspaceService.getWorkbenchState() === WorkbenchState.EMPTY) {
|
||||
// Use memento if present, otherwise default to restricted mode
|
||||
// Workspace may transition to trusted based on the opened editors
|
||||
return this._trustState.isTrusted ?? false;
|
||||
}
|
||||
|
||||
if (!this._initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.getUrisTrust(this.getWorkspaceUris());
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/
|
|||
import { MainThreadCommands } from 'vs/workbench/api/browser/mainThreadCommands';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { mock } from 'vs/base/test/common/mock';
|
||||
import { TreeItemCollapsibleState, ITreeItem } from 'vs/workbench/common/views';
|
||||
import { TreeItemCollapsibleState, ITreeItem, IRevealOptions } from 'vs/workbench/common/views';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import type { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
@ -35,7 +35,7 @@ suite('ExtHostTreeView', function () {
|
|||
});
|
||||
}
|
||||
|
||||
override $reveal(): Promise<void> {
|
||||
override $reveal(treeViewId: string, itemInfo: { item: ITreeItem, parentChain: ITreeItem[] } | undefined, options: IRevealOptions): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
@ -515,8 +515,8 @@ suite('ExtHostTreeView', function () {
|
|||
.then(() => {
|
||||
assert.ok(revealTarget.calledOnce);
|
||||
assert.deepStrictEqual('treeDataProvider', revealTarget.args[0][0]);
|
||||
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1].item));
|
||||
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1].parentChain)).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1]!.item));
|
||||
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1]!.parentChain)).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepStrictEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][2]);
|
||||
});
|
||||
});
|
||||
|
@ -534,8 +534,8 @@ suite('ExtHostTreeView', function () {
|
|||
.then(() => {
|
||||
assert.ok(revealTarget.calledOnce);
|
||||
assert.deepStrictEqual('treeDataProvider', revealTarget.args[0][0]);
|
||||
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1].item));
|
||||
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1].parentChain)).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1]!.item));
|
||||
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1]!.parentChain)).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepStrictEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][2]);
|
||||
}));
|
||||
});
|
||||
|
@ -561,8 +561,8 @@ suite('ExtHostTreeView', function () {
|
|||
.then(() => {
|
||||
assert.ok(revealTarget.calledOnce);
|
||||
assert.deepStrictEqual('treeDataProvider', revealTarget.args[0][0]);
|
||||
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1].item));
|
||||
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1].parentChain)).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1]!.item));
|
||||
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1]!.parentChain)).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepStrictEqual({ select: false, focus: false, expand: false }, revealTarget.args[0][2]);
|
||||
});
|
||||
});
|
||||
|
@ -592,8 +592,8 @@ suite('ExtHostTreeView', function () {
|
|||
.then(() => {
|
||||
assert.ok(revealTarget.calledOnce);
|
||||
assert.deepStrictEqual('treeDataProvider', revealTarget.args[0][0]);
|
||||
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1].item));
|
||||
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1].parentChain)).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepStrictEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1]!.item));
|
||||
assert.deepStrictEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1]!.parentChain)).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepStrictEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][2]);
|
||||
});
|
||||
});
|
||||
|
@ -633,8 +633,8 @@ suite('ExtHostTreeView', function () {
|
|||
.then(() => {
|
||||
assert.ok(revealTarget.calledOnce);
|
||||
assert.deepStrictEqual('treeDataProvider', revealTarget.args[0][0]);
|
||||
assert.deepStrictEqual({ handle: '0/0:b/0:bc', label: { label: 'bc' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:b' }, removeUnsetKeys(revealTarget.args[0][1].item));
|
||||
assert.deepStrictEqual([{ handle: '0/0:b', label: { label: 'b' }, collapsibleState: TreeItemCollapsibleState.Collapsed }], (<Array<any>>revealTarget.args[0][1].parentChain).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepStrictEqual({ handle: '0/0:b/0:bc', label: { label: 'bc' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:b' }, removeUnsetKeys(revealTarget.args[0][1]!.item));
|
||||
assert.deepStrictEqual([{ handle: '0/0:b', label: { label: 'b' }, collapsibleState: TreeItemCollapsibleState.Collapsed }], (<Array<any>>revealTarget.args[0][1]!.parentChain).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepStrictEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][2]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -53,7 +53,8 @@
|
|||
paths: {
|
||||
vs: new URL(`../../../${!!isBuild ? 'out-build' : 'out'}/vs`, baseUrl).href,
|
||||
assert: new URL('../assert.js', baseUrl).href,
|
||||
sinon: new URL('../../../node_modules/sinon/pkg/sinon-1.17.7.js', baseUrl).href,
|
||||
sinon: new URL('../../../node_modules/sinon/pkg/sinon.js', baseUrl).href,
|
||||
'sinon-test': new URL('../../../node_modules/sinon-test/dist/sinon-test.js', baseUrl).href,
|
||||
xterm: new URL('../../../node_modules/xterm/lib/xterm.js', baseUrl).href,
|
||||
'iconv-lite-umd': new URL('../../../node_modules/iconv-lite-umd/lib/iconv-lite-umd.js', baseUrl).href,
|
||||
jschardet: new URL('../../../node_modules/jschardet/dist/jschardet.min.js', baseUrl).href
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
baseUrl: '/out',
|
||||
paths: {
|
||||
assert: '/test/unit/assert.js',
|
||||
sinon: '/node_modules/sinon/pkg/sinon-1.17.7.js'
|
||||
sinon: '/node_modules/sinon/pkg/sinon.js',
|
||||
'sinon-test': '/node_modules/sinon-test/dist/sinon-test.js'
|
||||
}
|
||||
});
|
||||
|
||||
|
|
176
yarn.lock
176
yarn.lock
|
@ -338,6 +338,34 @@
|
|||
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
|
||||
integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
|
||||
|
||||
"@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.3":
|
||||
version "1.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d"
|
||||
integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==
|
||||
dependencies:
|
||||
type-detect "4.0.8"
|
||||
|
||||
"@sinonjs/fake-timers@^7.0.4", "@sinonjs/fake-timers@^7.1.0":
|
||||
version "7.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz#2524eae70c4910edccf99b2f4e6efc5894aff7b5"
|
||||
integrity sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.7.0"
|
||||
|
||||
"@sinonjs/samsam@^6.0.2":
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-6.0.2.tgz#a0117d823260f282c04bff5f8704bdc2ac6910bb"
|
||||
integrity sha512-jxPRPp9n93ci7b8hMfJOFDPRLFYadN6FSpeROFTR4UNF4i5b+EK6m4QXPO46BDhFgRy1JuS87zAnFOzCUwMJcQ==
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.6.0"
|
||||
lodash.get "^4.4.2"
|
||||
type-detect "^4.0.8"
|
||||
|
||||
"@sinonjs/text-encoding@^0.7.1":
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
|
||||
integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
|
||||
|
||||
"@szmarczak/http-timer@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
|
||||
|
@ -350,14 +378,15 @@
|
|||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
|
||||
integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
|
||||
|
||||
"@ts-morph/common@~0.9.0":
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.9.0.tgz#a306355bad82cff22a1881f7f2f2c710bbb4d69d"
|
||||
integrity sha512-yPcW6koNVK1hVKUu+KhPzhfgMb0uwzr2FewF+q8kxLerl0b+YZwmjvFMU2qbIawytIHT2VBI4bi+C09EFPB4aw==
|
||||
"@ts-morph/common@~0.10.0":
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.10.0.tgz#d032ea6f6d4115b72fa50ad56009baebcc1e71b8"
|
||||
integrity sha512-6wC+CovwzxLP+bQZcqHJEbZ7ViaIfsid8VzsVjJRkdfCQ8C8K5mm1+9/wkgmn814BPATtgSgFuDmVJnIb8/leg==
|
||||
dependencies:
|
||||
fast-glob "^3.2.5"
|
||||
minimatch "^3.0.4"
|
||||
mkdirp "^1.0.4"
|
||||
path-browserify "^1.0.1"
|
||||
|
||||
"@types/anymatch@*":
|
||||
version "1.3.1"
|
||||
|
@ -519,10 +548,19 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45"
|
||||
integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==
|
||||
|
||||
"@types/sinon@^1.16.36":
|
||||
version "1.16.36"
|
||||
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-1.16.36.tgz#74bb6ed7928597c1b3fb1b009005e94dc6eae357"
|
||||
integrity sha1-dLtu15KFl8Gz+xsAkAXpTcbq41c=
|
||||
"@types/sinon-test@^2.4.2":
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/sinon-test/-/sinon-test-2.4.2.tgz#f55bdf5486e7b7a4dd7257789fcc2b7b125c4164"
|
||||
integrity sha512-3BX9mk5+o//Xzs5N4bFYxPT+QlPLrqbyNfDWkIGtk9pVIp2Nl8ctsIGXsY3F01DsCd1Zlin3FqAk6V5XqkCyJA==
|
||||
dependencies:
|
||||
"@types/sinon" "*"
|
||||
|
||||
"@types/sinon@*", "@types/sinon@^10.0.2":
|
||||
version "10.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.2.tgz#f360d2f189c0fd433d14aeb97b9d705d7e4cc0e4"
|
||||
integrity sha512-BHn8Bpkapj8Wdfxvh2jWIUoaYB/9/XhsL0oOvBfRagJtKlSl9NWPcFOz2lRukI9szwGxFtYZCTejJSqsGDbdmw==
|
||||
dependencies:
|
||||
"@sinonjs/fake-timers" "^7.1.0"
|
||||
|
||||
"@types/source-list-map@*":
|
||||
version "0.1.2"
|
||||
|
@ -2868,6 +2906,11 @@ diff@4.0.2:
|
|||
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
|
||||
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
|
||||
|
||||
diff@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b"
|
||||
integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==
|
||||
|
||||
diffie-hellman@^5.0.0:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"
|
||||
|
@ -3939,13 +3982,6 @@ form-data@~2.3.2:
|
|||
combined-stream "^1.0.6"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
formatio@1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9"
|
||||
integrity sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=
|
||||
dependencies:
|
||||
samsam "~1.1"
|
||||
|
||||
fragment-cache@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
|
||||
|
@ -5670,6 +5706,11 @@ just-debounce@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea"
|
||||
integrity sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=
|
||||
|
||||
just-extend@^4.0.2:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.2.1.tgz#ef5e589afb61e5d66b24eca749409a8939a8c744"
|
||||
integrity sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==
|
||||
|
||||
keytar@7.2.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/keytar/-/keytar-7.2.0.tgz#4db2bec4f9700743ffd9eda22eebb658965c8440"
|
||||
|
@ -5867,6 +5908,11 @@ lodash.clone@^4.3.2:
|
|||
resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6"
|
||||
integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=
|
||||
|
||||
lodash.get@^4.4.2:
|
||||
version "4.4.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
|
||||
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
|
||||
|
||||
lodash.isequal@^4.0.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||
|
@ -5914,11 +5960,6 @@ log-symbols@4.0.0:
|
|||
dependencies:
|
||||
chalk "^4.0.0"
|
||||
|
||||
lolex@1.3.2:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31"
|
||||
integrity sha1-fD2mL/yzDw9agKJWbKJORdigHzE=
|
||||
|
||||
lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
|
||||
|
@ -6519,6 +6560,17 @@ nice-try@^1.0.4:
|
|||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||
|
||||
nise@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.0.tgz#713ef3ed138252daef20ec035ab62b7a28be645c"
|
||||
integrity sha512-W5WlHu+wvo3PaKLsJJkgPup2LrsXCcm7AWwyNZkUnn5rwPkuPBi3Iwk5SQtN0mv+K65k7nKKjwNQ30wg3wLAQQ==
|
||||
dependencies:
|
||||
"@sinonjs/commons" "^1.7.0"
|
||||
"@sinonjs/fake-timers" "^7.0.4"
|
||||
"@sinonjs/text-encoding" "^0.7.1"
|
||||
just-extend "^4.0.2"
|
||||
path-to-regexp "^1.7.0"
|
||||
|
||||
node-abi@^2.21.0:
|
||||
version "2.21.0"
|
||||
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.21.0.tgz#c2dc9ebad6f4f53d6ea9b531e7b8faad81041d48"
|
||||
|
@ -7093,6 +7145,11 @@ path-browserify@0.0.1:
|
|||
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a"
|
||||
integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==
|
||||
|
||||
path-browserify@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
|
||||
integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==
|
||||
|
||||
path-dirname@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
|
||||
|
@ -7147,6 +7204,13 @@ path-root@^0.1.1:
|
|||
dependencies:
|
||||
path-root-regex "^0.1.0"
|
||||
|
||||
path-to-regexp@^1.7.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
|
||||
integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
|
||||
dependencies:
|
||||
isarray "0.0.1"
|
||||
|
||||
path-type@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
|
||||
|
@ -8366,16 +8430,6 @@ safe-regex@^1.1.0:
|
|||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
samsam@1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567"
|
||||
integrity sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=
|
||||
|
||||
samsam@~1.1:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.3.tgz#9f5087419b4d091f232571e7fa52e90b0f552621"
|
||||
integrity sha1-n1CHQZtNCR8jJXHn+lLpCw9VJiE=
|
||||
|
||||
sax@0.5.x:
|
||||
version "0.5.8"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1"
|
||||
|
@ -8551,15 +8605,22 @@ simple-swizzle@^0.2.2:
|
|||
dependencies:
|
||||
is-arrayish "^0.3.1"
|
||||
|
||||
sinon@^1.17.2:
|
||||
version "1.17.7"
|
||||
resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.7.tgz#4542a4f49ba0c45c05eb2e9dd9d203e2b8efe0bf"
|
||||
integrity sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=
|
||||
sinon-test@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/sinon-test/-/sinon-test-3.1.0.tgz#25a3f4d9a9deb172252407041d577d67b73fefd5"
|
||||
integrity sha512-aGQwq6Xl9eJg/8Ugv4Ko4LQWUqjwRYNI8UtxnKa9hmcMEz3HBTR3nnzYrbW4isuRLsJWFuJTUcPGuz7f4XvODg==
|
||||
|
||||
sinon@^11.1.1:
|
||||
version "11.1.1"
|
||||
resolved "https://registry.yarnpkg.com/sinon/-/sinon-11.1.1.tgz#99a295a8b6f0fadbbb7e004076f3ae54fc6eab91"
|
||||
integrity sha512-ZSSmlkSyhUWbkF01Z9tEbxZLF/5tRC9eojCdFh33gtQaP7ITQVaMWQHGuFM7Cuf/KEfihuh1tTl3/ABju3AQMg==
|
||||
dependencies:
|
||||
formatio "1.1.1"
|
||||
lolex "1.3.2"
|
||||
samsam "1.1.2"
|
||||
util ">=0.10.3 <1"
|
||||
"@sinonjs/commons" "^1.8.3"
|
||||
"@sinonjs/fake-timers" "^7.1.0"
|
||||
"@sinonjs/samsam" "^6.0.2"
|
||||
diff "^5.0.0"
|
||||
nise "^5.1.0"
|
||||
supports-color "^7.2.0"
|
||||
|
||||
slash@^3.0.0:
|
||||
version "3.0.0"
|
||||
|
@ -9077,7 +9138,7 @@ sumchecker@^3.0.1:
|
|||
dependencies:
|
||||
debug "^4.1.0"
|
||||
|
||||
supports-color@7.2.0:
|
||||
supports-color@7.2.0, supports-color@^7.2.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
|
||||
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||
|
@ -9449,12 +9510,12 @@ ts-loader@^6.2.1:
|
|||
micromatch "^4.0.0"
|
||||
semver "^6.0.0"
|
||||
|
||||
ts-morph@^10.0.2:
|
||||
version "10.0.2"
|
||||
resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-10.0.2.tgz#292418207db467326231b2be92828b5e295e7946"
|
||||
integrity sha512-TVuIfEqtr9dW25K3Jajqpqx7t/zLRFxKu2rXQZSDjTm4MO4lfmuj1hn8WEryjeDDBFcNOCi+yOmYUYR4HucrAg==
|
||||
ts-morph@^11.0.0:
|
||||
version "11.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-11.0.0.tgz#511b3caa194739fef0619367f8e65de9b475e1d4"
|
||||
integrity sha512-u5y0jaft5c0sRFnU0K8cZhhsvPUtXjZK5L31JLIhP17qcqo9MDjwsSYLg3UryQDzlktv8wyf/UtoqpFLDYHijg==
|
||||
dependencies:
|
||||
"@ts-morph/common" "~0.9.0"
|
||||
"@ts-morph/common" "~0.10.0"
|
||||
code-block-writer "^10.1.1"
|
||||
|
||||
tsec@0.1.4:
|
||||
|
@ -9511,6 +9572,11 @@ type-check@~0.3.2:
|
|||
dependencies:
|
||||
prelude-ls "~1.1.2"
|
||||
|
||||
type-detect@4.0.8, type-detect@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
|
||||
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
|
||||
|
||||
type-fest@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1"
|
||||
|
@ -9722,7 +9788,7 @@ util.promisify@~1.0.0:
|
|||
has-symbols "^1.0.1"
|
||||
object.getownpropertydescriptors "^2.1.0"
|
||||
|
||||
util@0.10.3, "util@>=0.10.3 <1":
|
||||
util@0.10.3:
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
|
||||
integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk=
|
||||
|
@ -9979,14 +10045,6 @@ vscode-regexpp@^3.1.0:
|
|||
resolved "https://registry.yarnpkg.com/vscode-regexpp/-/vscode-regexpp-3.1.0.tgz#42d059b6fffe99bd42939c0d013f632f0cad823f"
|
||||
integrity sha512-pqtN65VC1jRLawfluX4Y80MMG0DHJydWhe5ZwMHewZD6sys4LbU6lHwFAHxeuaVE6Y6+xZOtAw+9hvq7/0ejkg==
|
||||
|
||||
vscode-ripgrep@^1.11.2:
|
||||
version "1.11.2"
|
||||
resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.11.2.tgz#a1d9c717a20f625b7e14680cc7db25ffafd132d4"
|
||||
integrity sha512-qMARNpPh/m6h9NbAQs4unGUnlAP2vrxt3a3nzbscrJcd5X9onoSdAYKG9vCkcxFJtOcQQm44a2Vf369mrrz8Sw==
|
||||
dependencies:
|
||||
https-proxy-agent "^4.0.0"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
vscode-ripgrep@^1.11.3:
|
||||
version "1.11.3"
|
||||
resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.11.3.tgz#a997f4f4535dfeb9d775f04053c1247454d7a37a"
|
||||
|
@ -10002,14 +10060,14 @@ vscode-sqlite3@4.0.11:
|
|||
dependencies:
|
||||
nan "^2.14.0"
|
||||
|
||||
vscode-telemetry-extractor@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-telemetry-extractor/-/vscode-telemetry-extractor-1.7.0.tgz#f99b1a90a4cad0f75454f2f57615a155e55eb960"
|
||||
integrity sha512-UC/N/uqPuQIuNnXg52XJnejeId2+Nuq04rj4H1rSZsqj9a56pigs6ogLPdZSi+OVLI21LU9PnJ/ZKrBrLm1roA==
|
||||
vscode-telemetry-extractor@^1.8.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-telemetry-extractor/-/vscode-telemetry-extractor-1.8.0.tgz#5562106fe2eebfce0593f336c91f5a5ddc154cee"
|
||||
integrity sha512-jWe+caeLyB/F3V0EqsdkCC98wXx9+XLbm6EoPngz0sC4GOM7lcDSnVhUXzrIhZD/TSRPSPGlxp5r4/CrvhbmMQ==
|
||||
dependencies:
|
||||
command-line-args "^5.1.1"
|
||||
ts-morph "^10.0.2"
|
||||
vscode-ripgrep "^1.11.2"
|
||||
ts-morph "^11.0.0"
|
||||
vscode-ripgrep "^1.11.3"
|
||||
|
||||
vscode-textmate@5.4.0:
|
||||
version "5.4.0"
|
||||
|
|
Loading…
Reference in a new issue