mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-13 17:22:15 -05:00
Add Markdown Keybindings (#17359)
* add markdown keybindings * remove add link keybinding * move files * fix layering
This commit is contained in:
@@ -307,6 +307,10 @@
|
||||
{
|
||||
"command": "notebook.command.codeBlock",
|
||||
"title": "%notebook.command.codeBlock%"
|
||||
},
|
||||
{
|
||||
"command": "notebook.command.highlightText",
|
||||
"title": "%notebook.command.highlightText%"
|
||||
}
|
||||
],
|
||||
"languages": [
|
||||
@@ -457,6 +461,10 @@
|
||||
{
|
||||
"command": "notebook.command.codeBlock",
|
||||
"when": "activeEditor == workbench.editor.notebookEditor && editorLangId == markdown"
|
||||
},
|
||||
{
|
||||
"command": "notebook.command.highlightText",
|
||||
"when": "activeEditor == workbench.editor.notebookEditor && editorLangId == markdown"
|
||||
}
|
||||
],
|
||||
"touchBar": [
|
||||
@@ -639,6 +647,11 @@
|
||||
"command": "notebook.command.codeBlock",
|
||||
"key": "Ctrl+Shift+K",
|
||||
"when": "activeEditor == workbench.editor.notebookEditor && editorLangId == markdown"
|
||||
},
|
||||
{
|
||||
"command": "notebook.command.highlightText",
|
||||
"key": "Ctrl+Shift+H",
|
||||
"when": "activeEditor == workbench.editor.notebookEditor && editorLangId == markdown"
|
||||
}
|
||||
],
|
||||
"notebook.languagemagics": [
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"notebook.command.italicizeText": "Italicize Markdown Text",
|
||||
"notebook.command.underlineText": "Underline Markdown Text",
|
||||
"notebook.command.codeBlock": "Add Code Block",
|
||||
"notebook.command.highlightText": "Highlight Markdown Text",
|
||||
"title.analyzeJupyterNotebook": "Analyze in Notebook",
|
||||
"title.newJupyterNotebook": "New Notebook",
|
||||
"title.openJupyterNotebook": "Open Notebook",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import 'vs/css!./markdownToolbar';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { Button, IButtonStyles } from 'sql/base/browser/ui/button/button';
|
||||
import { Component, Input, Inject, ViewChild, ElementRef } from '@angular/core';
|
||||
import { Component, Input, Inject, ViewChild, ElementRef, HostListener } from '@angular/core';
|
||||
import { localize } from 'vs/nls';
|
||||
import { CellEditModes, ICellModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
|
||||
import { ITaskbarContent, Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
|
||||
@@ -36,6 +36,34 @@ const linksRegex = /\[(?<text>.+)\]\((?<url>[^ ]+)(?: "(?<title>.+)")?\)/;
|
||||
export class MarkdownToolbarComponent extends AngularDisposable {
|
||||
@ViewChild('mdtoolbar', { read: ElementRef }) private mdtoolbar: ElementRef;
|
||||
|
||||
@HostListener('document:keydown', ['$event'])
|
||||
async onkeydown(e: KeyboardEvent) {
|
||||
if (this.cellModel?.currentMode === CellEditModes.SPLIT || this.cellModel?.currentMode === CellEditModes.MARKDOWN) {
|
||||
let markdownTextTransformer = new MarkdownTextTransformer(this._notebookService, this.cellModel);
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === 'b') {
|
||||
// Bold Text
|
||||
DOM.EventHelper.stop(e, true);
|
||||
await markdownTextTransformer.transformText(MarkdownButtonType.BOLD);
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === 'i') {
|
||||
// Italicize text
|
||||
DOM.EventHelper.stop(e, true);
|
||||
await markdownTextTransformer.transformText(MarkdownButtonType.ITALIC);
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === 'u') {
|
||||
// Underline text
|
||||
DOM.EventHelper.stop(e, true);
|
||||
await markdownTextTransformer.transformText(MarkdownButtonType.UNDERLINE);
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'k') {
|
||||
// Code Block
|
||||
DOM.EventHelper.stop(e, true);
|
||||
await markdownTextTransformer.transformText(MarkdownButtonType.CODE);
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'h') {
|
||||
// Highlight Text
|
||||
DOM.EventHelper.stop(e, true);
|
||||
await markdownTextTransformer.transformText(MarkdownButtonType.HIGHLIGHT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public previewFeaturesEnabled: boolean = false;
|
||||
|
||||
public buttonBold = localize('buttonBold', "Bold");
|
||||
|
||||
@@ -30,6 +30,7 @@ import { CodeComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/
|
||||
import { NotebookRange, ICellEditorProvider, INotebookService } from 'sql/workbench/services/notebook/browser/notebookService';
|
||||
import { HTMLMarkdownConverter } from 'sql/workbench/contrib/notebook/browser/htmlMarkdownConverter';
|
||||
import { NotebookInput } from 'sql/workbench/contrib/notebook/browser/models/notebookInput';
|
||||
import { highlightSelectedText } from 'sql/workbench/contrib/notebook/browser/utils';
|
||||
|
||||
export const TEXT_SELECTOR: string = 'text-cell-component';
|
||||
const USER_SELECT_CLASS = 'actionselect';
|
||||
@@ -73,30 +74,34 @@ export class TextCellComponent extends CellView implements OnInit, OnChanges {
|
||||
// Select all text
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === 'a') {
|
||||
preventDefaultAndExecCommand(e, 'selectAll');
|
||||
// Redo text
|
||||
} else if ((e.metaKey && e.shiftKey && e.key === 'z') || (e.ctrlKey && e.key === 'y') && !this.markdownMode) {
|
||||
// Redo text
|
||||
this.redoRichTextChange();
|
||||
// Undo text
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === 'z') {
|
||||
// Undo text
|
||||
this.undoRichTextChange();
|
||||
// Outdent text
|
||||
} else if (e.shiftKey && e.key === 'Tab') {
|
||||
// Outdent text
|
||||
preventDefaultAndExecCommand(e, 'outdent');
|
||||
// Indent text
|
||||
} else if (e.key === 'Tab') {
|
||||
// Indent text
|
||||
preventDefaultAndExecCommand(e, 'indent');
|
||||
// Bold text
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === 'b') {
|
||||
// Bold text
|
||||
preventDefaultAndExecCommand(e, 'bold');
|
||||
// Italicize text
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === 'i') {
|
||||
// Italicize text
|
||||
preventDefaultAndExecCommand(e, 'italic');
|
||||
// Underline text
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.key === 'u') {
|
||||
// Underline text
|
||||
preventDefaultAndExecCommand(e, 'underline');
|
||||
// Code Block
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'k') {
|
||||
// Code Block
|
||||
preventDefaultAndExecCommand(e, 'formatBlock', false, 'pre');
|
||||
} else if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'h') {
|
||||
// Highlight Text
|
||||
DOM.EventHelper.stop(e, true);
|
||||
highlightSelectedText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import { EditOperation } from 'vs/editor/common/core/editOperation';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { MarkdownToolbarComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/markdownToolbar.component';
|
||||
import { IEditor } from 'vs/editor/common/editorCommon';
|
||||
import { highlightSelectedText } from 'sql/workbench/contrib/notebook/browser/utils';
|
||||
|
||||
export class TransformMarkdownAction extends Action {
|
||||
|
||||
@@ -58,44 +59,7 @@ export class TransformMarkdownAction extends Action {
|
||||
document.execCommand('formatBlock', false, 'H3');
|
||||
break;
|
||||
case MarkdownButtonType.HIGHLIGHT:
|
||||
let selectionFocusNode = document.getSelection()?.focusNode;
|
||||
// Find if element is wrapped in <mark></mark>
|
||||
while (selectionFocusNode?.parentNode?.nodeName?.toLowerCase() && selectionFocusNode?.parentNode?.nodeName?.toLowerCase() !== 'mark') {
|
||||
selectionFocusNode = selectionFocusNode.parentNode;
|
||||
}
|
||||
// Find if element is wrapped in <span background-color="yellow">
|
||||
if (selectionFocusNode?.parentNode?.nodeName?.toLowerCase() !== 'mark') {
|
||||
selectionFocusNode = document.getSelection()?.focusNode;
|
||||
while (selectionFocusNode?.parentNode?.nodeName?.toLowerCase() && selectionFocusNode?.parentNode?.nodeName?.toLowerCase() !== 'span' && selectionFocusNode?.parentElement?.style?.backgroundColor !== 'yellow') {
|
||||
selectionFocusNode = selectionFocusNode.parentNode;
|
||||
}
|
||||
}
|
||||
let nodeName = selectionFocusNode?.parentNode?.nodeName?.toLowerCase();
|
||||
let backgroundColor = selectionFocusNode?.parentElement?.style?.backgroundColor;
|
||||
if (nodeName === 'mark') {
|
||||
let oldParent = selectionFocusNode.parentNode;
|
||||
let newParent = selectionFocusNode.parentNode.parentNode;
|
||||
let oldParentNextSibling = oldParent.nextSibling;
|
||||
// Remove mark element, reparent
|
||||
while (oldParent.childNodes.length > 0) {
|
||||
// If no next sibling, then old parent was the final child node, so we can append
|
||||
if (!oldParentNextSibling) {
|
||||
newParent.appendChild(oldParent.firstChild);
|
||||
} else {
|
||||
newParent.insertBefore(oldParent.firstChild, oldParentNextSibling);
|
||||
}
|
||||
}
|
||||
// Empty span required to force an input so that HTML change is seen from text cell component
|
||||
// This span doesn't have any effect on the markdown generated.
|
||||
document.execCommand('formatBlock', false, 'span');
|
||||
} else if (selectionFocusNode?.parentNode?.nodeName?.toLowerCase() === 'span' && backgroundColor === 'yellow') {
|
||||
selectionFocusNode.parentElement.style.backgroundColor = '';
|
||||
// Empty span required to force an input so that HTML change is seen from text cell component
|
||||
// This span doesn't have any effect on the markdown generated.
|
||||
document.execCommand('formatBlock', false, 'span');
|
||||
} else {
|
||||
document.execCommand('hiliteColor', false, 'Yellow');
|
||||
}
|
||||
highlightSelectedText();
|
||||
break;
|
||||
case MarkdownButtonType.IMAGE:
|
||||
case MarkdownButtonType.IMAGE_PREVIEW:
|
||||
|
||||
46
src/sql/workbench/contrib/notebook/browser/utils.ts
Normal file
46
src/sql/workbench/contrib/notebook/browser/utils.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export function highlightSelectedText(): void {
|
||||
let selectionFocusNode = document.getSelection()?.focusNode;
|
||||
// Find if element is wrapped in <mark></mark>
|
||||
while (selectionFocusNode?.parentNode?.nodeName?.toLowerCase() && selectionFocusNode?.parentNode?.nodeName?.toLowerCase() !== 'mark') {
|
||||
selectionFocusNode = selectionFocusNode.parentNode;
|
||||
}
|
||||
// Find if element is wrapped in <span background-color="yellow">
|
||||
if (selectionFocusNode?.parentNode?.nodeName?.toLowerCase() !== 'mark') {
|
||||
selectionFocusNode = document.getSelection()?.focusNode;
|
||||
while (selectionFocusNode?.parentNode?.nodeName?.toLowerCase() && selectionFocusNode?.parentNode?.nodeName?.toLowerCase() !== 'span' && selectionFocusNode?.parentElement?.style?.backgroundColor !== 'yellow') {
|
||||
selectionFocusNode = selectionFocusNode.parentNode;
|
||||
}
|
||||
}
|
||||
let nodeName = selectionFocusNode?.parentNode?.nodeName?.toLowerCase();
|
||||
let backgroundColor = selectionFocusNode?.parentElement?.style?.backgroundColor;
|
||||
if (nodeName === 'mark') {
|
||||
let oldParent = selectionFocusNode.parentNode;
|
||||
let newParent = selectionFocusNode.parentNode.parentNode;
|
||||
let oldParentNextSibling = oldParent.nextSibling;
|
||||
// Remove mark element, reparent
|
||||
while (oldParent.childNodes.length > 0) {
|
||||
// If no next sibling, then old parent was the final child node, so we can append
|
||||
if (!oldParentNextSibling) {
|
||||
newParent.appendChild(oldParent.firstChild);
|
||||
} else {
|
||||
newParent.insertBefore(oldParent.firstChild, oldParentNextSibling);
|
||||
}
|
||||
}
|
||||
// Empty span required to force an input so that HTML change is seen from text cell component
|
||||
// This span doesn't have any effect on the markdown generated.
|
||||
document.execCommand('formatBlock', false, 'span');
|
||||
} else if (selectionFocusNode?.parentNode?.nodeName?.toLowerCase() === 'span' && backgroundColor === 'yellow') {
|
||||
selectionFocusNode.parentElement.style.backgroundColor = '';
|
||||
// Empty span required to force an input so that HTML change is seen from text cell component
|
||||
// This span doesn't have any effect on the markdown generated.
|
||||
document.execCommand('formatBlock', false, 'span');
|
||||
} else {
|
||||
document.execCommand('hiliteColor', false, 'Yellow');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user