Add Markdown Keybindings (#17359)

* add markdown keybindings

* remove add link keybinding

* move files

* fix layering
This commit is contained in:
Vasu Bhog
2021-10-15 11:40:19 -07:00
committed by GitHub
parent fbdb434f3a
commit c368fcab25
6 changed files with 104 additions and 47 deletions

View File

@@ -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": [

View File

@@ -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",

View File

@@ -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");

View File

@@ -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();
}
}
}

View File

@@ -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:

View 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');
}
}