未验证 提交 dfc6bf78 编写于 作者: A Andre Weinand 提交者: GitHub

Merge branch 'master' into connor4312/fix-js-debug-web-ext-host

......@@ -45,6 +45,16 @@
"pattern": "^([a-z0-9A-Z][a-z0-9\\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\\-A-Z]*)$",
"errorMessage": "Expected format '${publisher}.${name}'. Example: 'vscode.csharp'."
}
},
"postAttachCommand": {
"type": [
"string",
"array"
],
"description": "A command to run after attaching to the container. If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell.",
"items": {
"type": "string"
}
}
}
}
......
......@@ -68,9 +68,33 @@
"type": "string"
}
},
"postStartCommand": {
"type": [
"string",
"array"
],
"description": "A command to run after starting the container. If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell.",
"items": {
"type": "string"
}
},
"postAttachCommand": {
"type": [
"string",
"array"
],
"description": "A command to run after attaching to the container. If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell.",
"items": {
"type": "string"
}
},
"devPort": {
"type": "integer",
"description": "The port VS Code can use to connect to its backend."
},
"codespaces": {
"type": "object",
"description": "Codespaces-specific configuration."
}
}
},
......
......@@ -212,9 +212,12 @@ suite('API tests', () => {
}
]
});
await vscode.commands.executeCommand('workbench.action.files.save');
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
});
test('notebook editor active/visible', async function () {
test.skip('notebook editor active/visible', async function () {
const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
const firstEditor = vscode.notebook.activeNotebookEditor;
......@@ -230,6 +233,7 @@ suite('API tests', () => {
assert.equal(vscode.notebook.visibleNotebookEditors.length, 2);
await vscode.commands.executeCommand('workbench.action.files.newUntitledFile');
// TODO@rebornix, this is not safe, we might need to listen to visible editor change event.
assert.equal(firstEditor?.visible, true);
assert.equal(firstEditor?.active, false);
assert.equal(secondEditor?.visible, false);
......@@ -594,7 +598,8 @@ suite('notebook working copy', () => {
assert.deepEqual(vscode.notebook.activeNotebookEditor?.document.cells.length, 1);
assert.equal(vscode.notebook.activeNotebookEditor?.selection?.source, 'test');
await vscode.commands.executeCommand('workbench.action.closeActiveEditor');
await vscode.commands.executeCommand('workbench.action.files.saveAll');
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
});
test('multiple tabs: dirty + clean', async function () {
......@@ -754,18 +759,18 @@ suite('regression', () => {
suite('webview', () => {
// for web, `asWebUri` gets `https`?
test('asWebviewUri', async function () {
if (vscode.env.uiKind === vscode.UIKind.Web) {
return;
}
// test('asWebviewUri', async function () {
// if (vscode.env.uiKind === vscode.UIKind.Web) {
// return;
// }
const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
const uri = vscode.notebook.activeNotebookEditor!.asWebviewUri(vscode.Uri.file('./hello.png'));
assert.equal(uri.scheme, 'vscode-resource');
await vscode.commands.executeCommand('workbench.action.closeAllEditors');
});
// const resource = vscode.Uri.file(join(vscode.workspace.rootPath || '', './first.vsctestnb'));
// await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
// assert.equal(vscode.notebook.activeNotebookEditor !== undefined, true, 'notebook first');
// const uri = vscode.notebook.activeNotebookEditor!.asWebviewUri(vscode.Uri.file('./hello.png'));
// assert.equal(uri.scheme, 'vscode-resource');
// await vscode.commands.executeCommand('workbench.action.closeAllEditors');
// });
// 404 on web
......
{
"name": "code-oss-dev",
"version": "1.46.0",
"distro": "df59b25a868325db7f34a57b3f86dd5950661544",
"distro": "ebf621f403497559e97da316516d55d16e4bf964",
"author": {
"name": "Microsoft Corporation"
},
......@@ -181,4 +181,4 @@
"windows-mutex": "0.3.0",
"windows-process-tree": "0.2.4"
}
}
}
\ No newline at end of file
......@@ -90,7 +90,7 @@
},
{
"name": "ms-vscode.js-debug-nightly",
"version": "2020.5.2717",
"version": "2020.6.208",
"repo": "https://github.com/Microsoft/vscode-js-debug",
"metadata": {
"id": "7acbb4ce-c85a-49d4-8d95-a8054406ae97",
......@@ -105,7 +105,7 @@
},
{
"name": "ms-vscode.vscode-js-profile-table",
"version": "0.0.4",
"version": "0.0.5",
"repo": "https://github.com/Microsoft/vscode-js-debug",
"metadata": {
"id": "7e52b41b-71ad-457b-ab7e-0620f1fc4feb",
......
......@@ -2,6 +2,10 @@
#
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
if [ "$VSCODE_WSL_DEBUG_INFO" = true ]; then
set -x
fi
COMMIT="@@COMMIT@@"
APP_NAME="@@APPNAME@@"
QUALITY="@@QUALITY@@"
......@@ -11,7 +15,7 @@ VSCODE_PATH="$(dirname "$(dirname "$(realpath "$0")")")"
ELECTRON="$VSCODE_PATH/$NAME.exe"
if grep -qi Microsoft /proc/version; then
# in a wsl shell
WSL_BUILD=$(uname -r | sed -E 's/^[0-9.]+-([0-9]+)-Microsoft|([0-9]+).([0-9]+).([0-9]+)-microsoft-standard|.*/\1\2\3\4/')
WSL_BUILD=$(uname -r | sed -E 's/^[0-9.]+-([0-9]+)-Microsoft.*|([0-9]+).([0-9]+).([0-9]+)-microsoft-standard.*|.*/\1\2\3\4/')
if [ -z "$WSL_BUILD" ]; then
WSL_BUILD=0
fi
......
......@@ -89,7 +89,6 @@ protocol.registerSchemesAsPrivileged([
scheme: 'vscode-resource',
privileges: {
secure: true,
standard: true,
supportFetchAPI: true,
corsEnabled: true,
}
......
......@@ -719,13 +719,13 @@ class QuickPick<T extends IQuickPickItem> extends QuickInput implements IQuickPi
break;
case KeyCode.Home:
if (event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) {
if ((event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey) {
this.ui.list.focus(QuickInputListFocus.First);
dom.EventHelper.stop(event, true);
}
break;
case KeyCode.End:
if (event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) {
if ((event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey) {
this.ui.list.focus(QuickInputListFocus.Last);
dom.EventHelper.stop(event, true);
}
......
......@@ -161,7 +161,7 @@ export class ActivitybarPart extends Part implements IActivityBarService {
actions.push(this.instantiationService.createInstance(ToggleActivityBarVisibilityAction, ToggleActivityBarVisibilityAction.ID, nls.localize('hideActivitBar', "Hide Activity Bar")));
return actions;
},
getContextMenuActionsForComposite: () => [],
getContextMenuActionsForComposite: compositeId => this.getContextMenuActionsForComposite(compositeId),
getDefaultCompositeId: () => this.viewDescriptorService.getDefaultViewContainer(this.location)!.id,
hidePart: () => this.layoutService.setSideBarHidden(true),
dndHandler: new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Sidebar,
......@@ -182,6 +182,31 @@ export class ActivitybarPart extends Part implements IActivityBarService {
this.compositeBar.focus();
}
private getContextMenuActionsForComposite(compositeId: string): Action[] {
const viewContainer = this.viewDescriptorService.getViewContainerById(compositeId)!;
const actions = [];
const defaultLocation = this.viewDescriptorService.getDefaultViewContainerLocation(viewContainer)!;
if (defaultLocation !== this.viewDescriptorService.getViewContainerLocation(viewContainer)) {
actions.push(new Action('resetLocationAction', nls.localize('resetLocation', "Reset Location"), undefined, true, async () => {
this.viewDescriptorService.moveViewContainerToLocation(viewContainer, defaultLocation);
}));
} else {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
if (viewContainerModel.allViewDescriptors.length === 1) {
const viewToReset = viewContainerModel.allViewDescriptors[0];
const defaultContainer = this.viewDescriptorService.getDefaultContainerById(viewToReset.id)!;
if (defaultContainer !== viewContainer) {
actions.push(new Action('resetLocationAction', nls.localize('resetLocation', "Reset Location"), undefined, true, async () => {
this.viewDescriptorService.moveViewsToContainer([viewToReset], defaultContainer);
}));
}
}
}
return actions;
}
private registerListeners(): void {
// View Container Changes
......
......@@ -154,6 +154,11 @@ export class BreakpointsView extends ViewPane {
this.onBreakpointsChange();
}
}));
const containerModel = this.viewDescriptorService.getViewContainerModel(this.viewDescriptorService.getViewContainerByViewId(this.id)!)!;
this._register(containerModel.onDidChangeAllViewDescriptors(() => {
this.updateSize();
}));
}
public focus(): void {
......@@ -237,9 +242,11 @@ export class BreakpointsView extends ViewPane {
}
private updateSize(): void {
const containerModel = this.viewDescriptorService.getViewContainerModel(this.viewDescriptorService.getViewContainerByViewId(this.id)!)!;
// Adjust expanded body size
this.minimumBodySize = this.orientation === Orientation.VERTICAL ? getExpandedBodySize(this.debugService.getModel(), MAX_VISIBLE_BREAKPOINTS) : 170;
this.maximumBodySize = this.orientation === Orientation.VERTICAL ? getExpandedBodySize(this.debugService.getModel(), Number.POSITIVE_INFINITY) : Number.POSITIVE_INFINITY;
this.maximumBodySize = this.orientation === Orientation.VERTICAL && containerModel.visibleViewDescriptors.length > 1 ? getExpandedBodySize(this.debugService.getModel(), Number.POSITIVE_INFINITY) : Number.POSITIVE_INFINITY;
}
private onBreakpointsChange(): void {
......
......@@ -1085,25 +1085,25 @@ export class FileDragAndDrop implements ITreeDragAndDrop<ExplorerItem> {
private async doUploadWebFileEntryBuffered(resource: URI, file: File): Promise<void> {
const writeableStream = newWriteableBufferStream();
const writeFilePromise = this.fileService.writeFile(resource, writeableStream);
// Read the file in chunks using File.stream() web APIs
(async () => {
try {
const reader: ReadableStreamDefaultReader<Uint8Array> = file.stream().getReader();
try {
const reader: ReadableStreamDefaultReader<Uint8Array> = file.stream().getReader();
let res = await reader.read();
while (!res.done) {
writeableStream.write(VSBuffer.wrap(res.value));
let res = await reader.read();
while (!res.done) {
writeableStream.write(VSBuffer.wrap(res.value));
res = await reader.read();
}
writeableStream.end(res.value instanceof Uint8Array ? VSBuffer.wrap(res.value) : undefined);
} catch (error) {
writeableStream.end(error);
res = await reader.read();
}
})();
writeableStream.end(res.value instanceof Uint8Array ? VSBuffer.wrap(res.value) : undefined);
} catch (error) {
writeableStream.end(error);
}
await this.fileService.writeFile(resource, writeableStream);
// Wait for file being written to target
await writeFilePromise;
}
private doUploadWebFileEntryUnbuffered(resource: URI, file: File): Promise<void> {
......
......@@ -303,6 +303,11 @@ export class OpenEditorsView extends ViewPane {
this.listRefreshScheduler.schedule(0);
}
}));
const containerModel = this.viewDescriptorService.getViewContainerModel(this.viewDescriptorService.getViewContainerByViewId(this.id)!)!;
this._register(containerModel.onDidChangeAllViewDescriptors(() => {
this.updateSize();
}));
}
getActions(): IAction[] {
......@@ -446,6 +451,11 @@ export class OpenEditorsView extends ViewPane {
}
private getMaxExpandedBodySize(): number {
const containerModel = this.viewDescriptorService.getViewContainerModel(this.viewDescriptorService.getViewContainerByViewId(this.id)!)!;
if (containerModel.visibleViewDescriptors.length <= 1) {
return Number.POSITIVE_INFINITY;
}
return this.elementCount * OpenEditorsDelegate.ITEM_HEIGHT;
}
......
......@@ -18,7 +18,7 @@ import { InputFocusedContext, InputFocusedContextKey } from 'vs/platform/context
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
import { BaseCellRenderTemplate, CellEditState, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_RUNNABLE, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { BaseCellRenderTemplate, CellEditState, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_RUNNABLE, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_IS_ACTIVE_EDITOR, NOTEBOOK_CELL_HAS_OUTPUTS } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellKind, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, NotebookCellRunState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
......@@ -1006,7 +1006,7 @@ registerAction2(class extends NotebookAction {
title: localize('focusOutput', 'Focus In Active Cell Output'),
category: NOTEBOOK_ACTIONS_CATEGORY,
keybinding: {
when: NOTEBOOK_EDITOR_FOCUSED,
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_CELL_HAS_OUTPUTS),
primary: KeyMod.CtrlCmd | KeyCode.DownArrow,
mac: { primary: KeyMod.WinCtrl | KeyMod.CtrlCmd | KeyCode.DownArrow, },
weight: KeybindingWeight.WorkbenchContrib
......@@ -1019,7 +1019,7 @@ registerAction2(class extends NotebookAction {
async runWithContext(accessor: ServicesAccessor, context: INotebookCellActionContext): Promise<void> {
const editor = context.notebookEditor;
const activeCell = context.cell;
await editor.focusNotebookCell(activeCell, 'output');
editor.focusNotebookCell(activeCell, 'output');
}
});
......
......@@ -141,6 +141,9 @@ export class NotebookEditor extends BaseEditor {
// make sure the editor widget is removed from the view
const existingEditorWidgetForInput = NotebookRegistry.getNotebookEditorWidget(this.input as NotebookEditorInput);
if (existingEditorWidgetForInput) {
// the editor widget is only referenced by the editor input
// clear its state
existingEditorWidgetForInput?.onWillHide();
existingEditorWidgetForInput?.getDomNode().remove();
existingEditorWidgetForInput?.dispose();
NotebookRegistry.releaseNotebookEditorWidget(this.input as NotebookEditorInput);
......
......@@ -23,6 +23,7 @@ import { CellRevealPosition, CellRevealType, CursorAtBoundary, getVisibleCells,
import { CellViewModel, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { diff, IProcessedOutput, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { clamp } from 'vs/base/common/numbers';
import { SCROLLABLE_ELEMENT_PADDING_TOP } from 'vs/workbench/contrib/notebook/browser/constants';
export class NotebookCellList extends WorkbenchList<CellViewModel> implements IDisposable, IStyleController, INotebookCellList {
get onWillScroll(): Event<ScrollEvent> { return this.view.onWillScroll; }
......@@ -546,28 +547,35 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
super.domFocus();
}
getViewScrollTop() {
return this.view.getScrollTop();
}
getViewScrollBottom() {
return this.getViewScrollTop() + this.view.renderHeight - SCROLLABLE_ELEMENT_PADDING_TOP;
}
private _revealRange(viewIndex: number, range: Range, revealType: CellRevealType, newlyCreated: boolean, alignToBottom: boolean) {
const element = this.view.element(viewIndex);
const scrollTop = this.view.getScrollTop();
const wrapperBottom = scrollTop + this.view.renderHeight;
const startLineNumber = range.startLineNumber;
const lineOffset = element.getLineScrollTopOffset(startLineNumber);
const scrollTop = this.getViewScrollTop();
const wrapperBottom = this.getViewScrollBottom();
const positionOffset = element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
const elementTop = this.view.elementTop(viewIndex);
const lineTop = elementTop + lineOffset;
const positionTop = elementTop + positionOffset;
// TODO@rebornix 30 ---> line height * 1.5
if (lineTop < scrollTop) {
this.view.setScrollTop(lineTop - 30);
} else if (lineTop > wrapperBottom) {
this.view.setScrollTop(scrollTop + lineTop - wrapperBottom + 30);
if (positionTop < scrollTop) {
this.view.setScrollTop(positionTop - 30);
} else if (positionTop > wrapperBottom) {
this.view.setScrollTop(scrollTop + positionTop - wrapperBottom + 30);
} else if (newlyCreated) {
// newly scrolled into view
if (alignToBottom) {
// align to the bottom
this.view.setScrollTop(scrollTop + lineTop - wrapperBottom + 30);
this.view.setScrollTop(scrollTop + positionTop - wrapperBottom + 30);
} else {
// align to to top
this.view.setScrollTop(lineTop - 30);
this.view.setScrollTop(positionTop - 30);
}
}
......@@ -580,8 +588,8 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
// For example, we scroll item 10 into the view upwards, in the first round, items 7, 8, 9, 10 are all in the viewport. Then item 7 and 8 resize themselves to be larger and finally item 10 is removed from the view.
// To ensure that item 10 is always there, we need to scroll item 10 to the top edge of the viewport.
private _revealRangeInternal(viewIndex: number, range: Range, revealType: CellRevealType) {
const scrollTop = this.view.getScrollTop();
const wrapperBottom = scrollTop + this.view.renderHeight;
const scrollTop = this.getViewScrollTop();
const wrapperBottom = this.getViewScrollBottom();
const elementTop = this.view.elementTop(viewIndex);
const element = this.view.element(viewIndex);
......@@ -624,9 +632,9 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
private _revealRangeInCenterInternal(viewIndex: number, range: Range, revealType: CellRevealType) {
const reveal = (viewIndex: number, range: Range, revealType: CellRevealType) => {
const element = this.view.element(viewIndex);
let lineOffset = element.getLineScrollTopOffset(range.startLineNumber);
let lineOffsetInView = this.view.elementTop(viewIndex) + lineOffset;
this.view.setScrollTop(lineOffsetInView - this.view.renderHeight / 2);
let positionOffset = element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
let positionOffsetInView = this.view.elementTop(viewIndex) + positionOffset;
this.view.setScrollTop(positionOffsetInView - this.view.renderHeight / 2);
if (revealType === CellRevealType.Range) {
element.revealRangeInCenter(range);
......@@ -656,24 +664,25 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
private _revealRangeInCenterIfOutsideViewportInternal(viewIndex: number, range: Range, revealType: CellRevealType) {
const reveal = (viewIndex: number, range: Range, revealType: CellRevealType) => {
const element = this.view.element(viewIndex);
let lineOffset = element.getLineScrollTopOffset(range.startLineNumber);
let lineOffsetInView = this.view.elementTop(viewIndex) + lineOffset;
this.view.setScrollTop(lineOffsetInView - this.view.renderHeight / 2);
let positionOffset = element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
let positionOffsetInView = this.view.elementTop(viewIndex) + positionOffset;
this.view.setScrollTop(positionOffsetInView - this.view.renderHeight / 2);
if (revealType === CellRevealType.Range) {
element.revealRangeInCenter(range);
}
};
const scrollTop = this.view.getScrollTop();
const wrapperBottom = scrollTop + this.view.renderHeight;
const scrollTop = this.getViewScrollTop();
const wrapperBottom = this.getViewScrollBottom();
const elementTop = this.view.elementTop(viewIndex);
const viewItemOffset = elementTop;
const element = this.view.element(viewIndex);
const positionOffset = viewItemOffset + element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
if (viewItemOffset < scrollTop || viewItemOffset > wrapperBottom) {
if (positionOffset < scrollTop || positionOffset > wrapperBottom) {
// let it render
this.view.setScrollTop(viewItemOffset - this.view.renderHeight / 2);
this.view.setScrollTop(positionOffset - this.view.renderHeight / 2);
// after rendering, it might be pushed down due to markdown cell dynamic height
const elementTop = this.view.elementTop(viewIndex);
......@@ -708,8 +717,8 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
return;
}
const scrollTop = this.view.getScrollTop();
const wrapperBottom = scrollTop + this.view.renderHeight;
const scrollTop = this.getViewScrollTop();
const wrapperBottom = this.getViewScrollBottom();
const elementTop = this.view.elementTop(viewIndex);
if (ignoreIfInsideViewport && elementTop >= scrollTop && elementTop < wrapperBottom) {
......
......@@ -51,6 +51,7 @@ import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewMod
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { CellKind, NotebookCellRunState, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { containsDragType } from 'vs/workbench/browser/dnd';
const $ = DOM.$;
......@@ -513,6 +514,8 @@ interface CellDragEvent {
}
export class CellDragAndDropController extends Disposable {
private static DATA_TYPE = 'vscode_notebook_cell';
// TODO@roblourens - should probably use dataTransfer here, but any dataTransfer set makes the editor think I am dropping a file, need
// to figure out how to prevent that
private currentDraggedCell: ICellViewModel | undefined;
......@@ -619,6 +622,15 @@ export class CellDragAndDropController extends Disposable {
}
private onCellDragover(event: CellDragEvent): void {
if (!event.browserEvent.dataTransfer) {
return;
}
if (!this.currentDraggedCell || !containsDragType(event.browserEvent, CellDragAndDropController.DATA_TYPE)) {
event.browserEvent.dataTransfer.dropEffect = 'none';
return;
}
if (this.isScrolling || this.currentDraggedCell === event.draggedOverCell) {
this.setInsertIndicatorVisibility(false);
return;
......@@ -691,6 +703,8 @@ export class CellDragAndDropController extends Disposable {
return;
}
event.dataTransfer.setData(CellDragAndDropController.DATA_TYPE, 'true');
this.currentDraggedCell = templateData.currentRenderedCell!;
this.currentDraggedCell.dragging = true;
......
......@@ -174,6 +174,15 @@ export class StatefullMarkdownCell extends Disposable {
}
}));
this.localDisposables.add(viewCell.textBuffer.onDidChangeContent(() => {
this.markdownContainer.innerHTML = '';
viewCell.clearHTML();
let renderedHTML = viewCell.getHTML();
if (renderedHTML) {
this.markdownContainer.appendChild(renderedHTML);
}
}));
const clientHeight = templateData.container.clientHeight;
this.viewCell.totalHeight = clientHeight;
notebookEditor.layoutNotebookCell(viewCell, clientHeight);
......
......@@ -12,7 +12,7 @@ import { IPosition } from 'vs/editor/common/core/position';
import * as editorCommon from 'vs/editor/common/editorCommon';
import * as model from 'vs/editor/common/model';
import { SearchParams } from 'vs/editor/common/model/textModelSearch';
import { EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants';
import { EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
import { CellEditState, CellFocusMode, CursorAtBoundary, CellViewModelStateChangeEvent, IEditableCellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellKind, NotebookCellMetadata, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
......@@ -279,7 +279,15 @@ export abstract class BaseCellViewModel extends Disposable {
return 0;
}
return this._textEditor.getTopForLineNumber(line) + EDITOR_TOP_MARGIN + EDITOR_TOOLBAR_HEIGHT;
return this._textEditor.getTopForLineNumber(line) + EDITOR_TOP_PADDING;
}
getPositionScrollTopOffset(line: number, column: number): number {
if (!this._textEditor) {
return 0;
}
return this._textEditor.getTopForPosition(line, column) + EDITOR_TOP_PADDING;
}
cursorAtBoundary(): CursorAtBoundary {
......
......@@ -831,10 +831,10 @@ configurationRegistry.registerConfiguration({
default: false,
markdownDescription: nls.localize('search.searchEditor.reusePriorSearchConfiguration', "When enabled, new Search Editors will reuse the includes, excludes, and flags of the previously opened Search Editor")
},
'search.searchEditor.defaultShowContextValue': {
'search.searchEditor.defaultNumberOfContextLines': {
type: ['number', 'null'],
default: null,
markdownDescription: nls.localize('search.searchEditor.defaultShowContextValue', "The default number of surrounding context lines to show in Search Editor results. If defined, this overrides `#search.searchEditor.reusePriorSearchConfiguration#` for context line configuration.")
markdownDescription: nls.localize('search.searchEditor.defaultNumberOfContextLines', "The default number of surrounding context lines to use when creating new Search Editors with `Search Editor: Open new Search Editor` and `Search Editor: Open new Search Editor to the Side`. If defined, this overrides `#search.searchEditor.reusePriorSearchConfiguration#`.")
},
'search.sortOrder': {
'type': 'string',
......
......@@ -302,15 +302,19 @@ export const getOrMakeSearchEditorInput = (
const searchEditorSettings = configurationService.getValue<ISearchConfigurationProperties>('search').searchEditor;
const reuseOldSettings = searchEditorSettings.reusePriorSearchConfiguration;
const defaultShowContextValue = searchEditorSettings.defaultShowContextValue;
const defaultNumberOfContextLines = searchEditorSettings.defaultNumberOfContextLines;
const priorConfig: SearchConfiguration = reuseOldSettings ? new Memento(SearchEditorInput.ID, storageService).getMemento(StorageScope.WORKSPACE).searchConfig : {};
const defaultConfig = defaultSearchConfig();
let config = { ...defaultConfig, ...priorConfig, ...existingData.config };
if (defaultShowContextValue !== null && defaultShowContextValue !== undefined) {
config.contextLines = defaultShowContextValue;
if (defaultNumberOfContextLines !== null && defaultNumberOfContextLines !== undefined) {
config.contextLines = defaultNumberOfContextLines;
}
if (existingData.text) {
config.contextLines = 0;
}
const modelUri = existingData.modelUri ?? URI.from({ scheme: SearchEditorScheme, fragment: `${Math.random()}` });
......
......@@ -140,7 +140,7 @@ async function getRemotes(fileService: IFileService, textFileService: ITextFileS
const domains = new Set<string>();
let match: RegExpExecArray | null;
const RemoteMatcher = /^\s*url\s*=\s*(?:git@|https:\/\/)github\.com(?::|\/)(\S*)\.git\s*$/mg;
const RemoteMatcher = /^\s*url\s*=\s*(?:git@|https:\/\/)github\.com(?::|\/)(\S*)(?:\.git)?\s*$/mg;
while (match = RemoteMatcher.exec(content)) {
const repo = match[1];
if (repo) {
......
......@@ -157,15 +157,33 @@ function isLocalhostAuthority(authority: string) {
return rLocalhost.test(authority) || r127.test(authority);
}
/**
* Case-normalize some case-insinsitive URLs, such as github.
*/
function normalizeURL(url: string | URI): string {
const caseInsensitiveAuthorities = ['github.com'];
try {
const parsed = typeof url === 'string' ? URI.parse(url, true) : url;
if (caseInsensitiveAuthorities.includes(parsed.authority)) {
return parsed.with({ path: parsed.path.toLowerCase() }).toString(true);
} else {
return parsed.toString(true);
}
} catch { return url.toString(); }
}
/**
* Check whether a domain like https://www.microsoft.com matches
* the list of trusted domains.
*
* - Schemes must match
* - There's no subdomain matching. For example https://microsoft.com doesn't match https://www.microsoft.com
* - There's no subdomsain matching. For example https://microsoft.com doesn't match https://www.microsoft.com
* - Star matches all subdomains. For example https://*.microsoft.com matches https://www.microsoft.com and https://foo.bar.microsoft.com
*/
export function isURLDomainTrusted(url: URI, trustedDomains: string[]) {
url = URI.parse(normalizeURL(url));
trustedDomains = trustedDomains.map(normalizeURL);
if (isLocalhostAuthority(url.authority)) {
return true;
}
......
......@@ -78,4 +78,10 @@ suite('Link protection domain matching', () => {
linkAllowedByRules('https://github.com', ['https://github.com/foo/bar', 'https://github.com']);
});
test('case normalization', () => {
// https://github.com/microsoft/vscode/issues/99294
linkAllowedByRules('https://github.com/Microsoft/vscode/issues/new', ['https://github.com/microsoft']);
linkAllowedByRules('https://github.com/microsoft/vscode/issues/new', ['https://github.com/Microsoft']);
});
});
......@@ -298,7 +298,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
this.disableSync();
this.notificationService.notify({
severity: Severity.Error,
message: localize('error upgrade required', "Turned off sync because the current version ({0}, {1}) of {2} is not compatible with the Preferences Sync Service. Please update and turn on sync to continue syncing.", this.productService.version, this.productService.commit, this.productService.nameLong),
message: localize('error upgrade required', "Preferences sync is disabled because the current version ({0}, {1}) is not compatible with the sync service. Please update before turning on sync.", this.productService.version, this.productService.commit),
});
return true;
}
......
......@@ -229,7 +229,7 @@ export class UserDataSyncDataViews extends Disposable {
constructor() {
super({
id: `workbench.actions.sync.replaceCurrent`,
title: localize('workbench.actions.sync.replaceCurrent', "Download..."),
title: localize('workbench.actions.sync.replaceCurrent', "Revert"),
icon: { id: 'codicon/cloud-download' },
menu: {
id: MenuId.ViewItemContext,
......
......@@ -350,7 +350,7 @@ export interface ISearchConfigurationProperties {
searchEditor: {
doubleClickBehaviour: 'selectWord' | 'goToLocation' | 'openLocationToSide',
reusePriorSearchConfiguration: boolean,
defaultShowContextValue: number | null,
defaultNumberOfContextLines: number | null,
experimental: {}
};
sortOrder: SearchSortOrder;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册