From 989d20c474499552d20a11c3b41b8564912f6bcc Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Mon, 19 Sep 2022 10:40:15 +0200 Subject: [PATCH] #417 - New `hyperlink` wysiwyg option --- CHANGELOG.md | 1 + package.json | 8 ++++- src/commands/Wysiwyg.ts | 60 ++++++++++++++++++++++++++++++++++++-- src/constants/Extension.ts | 1 + 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ec61d90..52c7959b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ - [#394](https://github.com/estruyf/vscode-front-matter/issues/394): Ordering of snippet fields is based on their field definition - [#395](https://github.com/estruyf/vscode-front-matter/issues/395): Added support for custom snippet fields on media snippets - [#402](https://github.com/estruyf/vscode-front-matter/issues/402): Custom sorting of content now supports `number` fields +- [#417](https://github.com/estruyf/vscode-front-matter/issues/417): New `hyperlink` wysiwyg option - [#418](https://github.com/estruyf/vscode-front-matter/issues/418): New `heading` and `divider` fields for your content-type definition ### ⚡️ Optimizations diff --git a/package.json b/package.json index a218db53..674d724b 100644 --- a/package.json +++ b/package.json @@ -1498,6 +1498,12 @@ "dark": "assets/icons/codeblock-dark.svg" } }, + { + "command": "frontMatter.markup.hyperlink", + "title": "Hyperlink", + "category": "Front Matter", + "icon": "$(link)" + }, { "command": "frontMatter.collapseSections", "title": "Collapse sections", @@ -1746,7 +1752,7 @@ "when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg" }, { - "command": "frontMatter.markup.strikethrough", + "command": "frontMatter.markup.hyperlink", "group": "navigation@-130", "when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg" }, diff --git a/src/commands/Wysiwyg.ts b/src/commands/Wysiwyg.ts index 3792ca95..fb636aae 100644 --- a/src/commands/Wysiwyg.ts +++ b/src/commands/Wysiwyg.ts @@ -1,4 +1,4 @@ -import { commands, window, Selection, QuickPickItem } from "vscode"; +import { commands, window, Selection, QuickPickItem, TextEditor } from "vscode"; import { COMMAND_NAME, CONTEXT, SETTING_CONTENT_WYSIWYG } from "../constants"; import { Settings } from "../helpers"; @@ -12,7 +12,8 @@ enum MarkupType { heading, unorderedList, orderedList, - taskList + taskList, + hyperlink, } export class Wysiwyg { @@ -46,6 +47,9 @@ export class Wysiwyg { subscriptions.push(commands.registerCommand(COMMAND_NAME.orderedlist, () => this.addMarkup(MarkupType.orderedList))); subscriptions.push(commands.registerCommand(COMMAND_NAME.taskList, () => this.addMarkup(MarkupType.taskList))); + // Other markup + subscriptions.push(commands.registerCommand(COMMAND_NAME.hyperlink, () => this.addMarkup(MarkupType.hyperlink))); + // Options subscriptions.push(commands.registerCommand(COMMAND_NAME.options, async () => { const qpItems: QuickPickItem[] = [ @@ -55,6 +59,7 @@ export class Wysiwyg { { label: "$(code) Code", detail: "Add inline code snippet", alwaysShow: true }, { label: "$(symbol-namespace) Code block", detail: "Add a code block", alwaysShow: true }, { label: "$(quote) Blockquote", detail: "Add a blockquote", alwaysShow: true }, + { label: "$(symbol-text) Strikethrough", detail: "Add a strikethrough", alwaysShow: true }, ] const option = await window.showQuickPick([ ...qpItems ], { @@ -77,6 +82,8 @@ export class Wysiwyg { await this.addMarkup(MarkupType.codeblock); } else if (option.label === qpItems[5].label) { await this.addMarkup(MarkupType.blockquote); + } else if (option.label === qpItems[6].label) { + await this.addMarkup(MarkupType.strikethrough); } } })); @@ -96,6 +103,10 @@ export class Wysiwyg { const selection = editor.selection; const hasTextSelection = !selection.isEmpty; + if (type === MarkupType.hyperlink) { + return this.addHyperlink(editor, selection); + } + const markers = this.getMarkers(type); if (!markers) { return; @@ -130,6 +141,51 @@ export class Wysiwyg { } } + /** + * Add a hyperlink to the content + * @returns void + */ + private static async addHyperlink(editor: TextEditor, selection: Selection) { + const hasTextSelection = !selection.isEmpty; + const linkText = hasTextSelection ? editor.document.getText(selection) : ""; + + const link = await window.showInputBox({ + title: "WYSIWYG Hyperlink", + placeHolder: "Enter the URL", + prompt: "Enter the URL", + value: linkText, + ignoreFocusOut: true + }); + + const text = await window.showInputBox({ + title: "WYSIWYG Text", + prompt: "Enter the text for the hyperlink", + placeHolder: "Enter the text for the hyperlink", + value: linkText, + ignoreFocusOut: true + }); + + if (link) { + const txt = `[${text || link}](${link})`; + + if (hasTextSelection) { + editor.edit(builder => { + builder.replace(selection, txt); + }); + } else { + const crntSelection = selection.active; + const markerLength = txt.length; + const newPosition = crntSelection.with(crntSelection.line, crntSelection.character + markerLength); + + await editor.edit(builder => { + builder.insert(newPosition, txt); + }); + + editor.selection = new Selection(newPosition, newPosition); + } + } + } + /** * Check if the text will be wrapped * @param type diff --git a/src/constants/Extension.ts b/src/constants/Extension.ts index b2eff6c8..6e0eb252 100644 --- a/src/constants/Extension.ts +++ b/src/constants/Extension.ts @@ -56,6 +56,7 @@ export const COMMAND_NAME = { unorderedlist: getCommandName("markup.unorderedlist"), orderedlist: getCommandName("markup.orderedlist"), taskList: getCommandName("markup.tasklist"), + hyperlink: getCommandName("markup.hyperlink"), options: getCommandName("markup.options"), // Content types