mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 21:09:43 +00:00
Make markdown link pasting feature smarter (#187170)
* making markdown link pasting feature smarter * Update settings description Co-authored-by: Joyce Er <joyceerhl@gmail.com> * made checkPaste more concise * won't paste md link in fenced code or math --------- Co-authored-by: Joyce Er <joyceerhl@gmail.com>
This commit is contained in:
parent
261a75e3a4
commit
f07abd224b
|
@ -499,10 +499,20 @@
|
|||
]
|
||||
},
|
||||
"markdown.editor.pasteUrlAsFormattedLink.enabled": {
|
||||
"type": "boolean",
|
||||
"type": "string",
|
||||
"scope": "resource",
|
||||
"markdownDescription": "%configuration.markdown.editor.pasteUrlAsFormattedLink.enabled%",
|
||||
"default": true
|
||||
"default":"smart",
|
||||
"enum": [
|
||||
"always",
|
||||
"smart",
|
||||
"never"
|
||||
],
|
||||
"markdownEnumDescriptions": [
|
||||
"%configuration.pasteUrlAsFormattedLink.always%",
|
||||
"%configuration.pasteUrlAsFormattedLink.smart%",
|
||||
"%configuration.pasteUrlAsFormattedLink.never%"
|
||||
]
|
||||
},
|
||||
"markdown.validate.enabled": {
|
||||
"type": "boolean",
|
||||
|
|
|
@ -41,9 +41,12 @@
|
|||
"configuration.markdown.editor.drop.copyIntoWorkspace": "Controls if files outside of the workspace that are dropped into a Markdown editor should be copied into the workspace.\n\nUse `#markdown.copyFiles.destination#` to configure where copied dropped files should be created",
|
||||
"configuration.markdown.editor.filePaste.enabled": "Enable pasting files into a Markdown editor to create Markdown links. Requires enabling `#editor.pasteAs.enabled#`.",
|
||||
"configuration.markdown.editor.filePaste.copyIntoWorkspace": "Controls if files outside of the workspace that are pasted into a Markdown editor should be copied into the workspace.\n\nUse `#markdown.copyFiles.destination#` to configure where copied files should be created.",
|
||||
"configuration.markdown.editor.pasteUrlAsFormattedLink.enabled": "Controls if a Markdown link is created when a URL is pasted into the Markdown editor. Requires enabling `#editor.pasteAs.enabled#`.",
|
||||
"configuration.copyIntoWorkspace.mediaFiles": "Try to copy external image and video files into the workspace.",
|
||||
"configuration.copyIntoWorkspace.never": "Do not copy external files into the workspace.",
|
||||
"configuration.markdown.editor.pasteUrlAsFormattedLink.enabled": "Controls how a Markdown link is created when a URL is pasted into the Markdown editor. Requires enabling `#editor.pasteAs.enabled#`.",
|
||||
"configuration.pasteUrlAsFormattedLink.always": "Always create a Markdown link when a URL is pasted into the Markdown editor.",
|
||||
"configuration.pasteUrlAsFormattedLink.smart": "Does not create a Markdown link within a link snippet or code bracket.",
|
||||
"configuration.pasteUrlAsFormattedLink.never": "Never create a Markdown link when a URL is pasted into the Markdown editor.",
|
||||
"configuration.markdown.validate.enabled.description": "Enable all error reporting in Markdown files.",
|
||||
"configuration.markdown.validate.referenceLinks.enabled.description": "Validate reference links in Markdown files, for example: `[link][ref]`. Requires enabling `#markdown.validate.enabled#`.",
|
||||
"configuration.markdown.validate.fragmentLinks.enabled.description": "Validate fragment links to headers in the current Markdown file, for example: `[link](#header)`. Requires enabling `#markdown.validate.enabled#`.",
|
||||
|
|
|
@ -76,10 +76,10 @@ async function insertLink(activeEditor: vscode.TextEditor, selectedFiles: vscode
|
|||
await vscode.workspace.applyEdit(edit);
|
||||
}
|
||||
|
||||
function createInsertLinkEdit(activeEditor: vscode.TextEditor, selectedFiles: vscode.Uri[], insertAsMedia: boolean, title = '', placeholderValue = 0) {
|
||||
function createInsertLinkEdit(activeEditor: vscode.TextEditor, selectedFiles: vscode.Uri[], insertAsMedia: boolean, title = '', placeholderValue = 0, smartPaste = false) {
|
||||
const snippetEdits = coalesce(activeEditor.selections.map((selection, i): vscode.SnippetTextEdit | undefined => {
|
||||
const selectionText = activeEditor.document.getText(selection);
|
||||
const snippet = createUriListSnippet(activeEditor.document, selectedFiles, title, placeholderValue, {
|
||||
const snippet = createUriListSnippet(activeEditor.document, selectedFiles, title, placeholderValue, smartPaste, {
|
||||
insertAsMedia,
|
||||
placeholderText: selectionText,
|
||||
placeholderStartIndex: (i + 1) * selectedFiles.length,
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
import * as vscode from 'vscode';
|
||||
import { getMarkdownLink } from './shared';
|
||||
|
||||
class PasteLinkEditProvider implements vscode.DocumentPasteEditProvider {
|
||||
|
||||
readonly id = 'insertMarkdownLink';
|
||||
|
@ -15,8 +14,8 @@ class PasteLinkEditProvider implements vscode.DocumentPasteEditProvider {
|
|||
dataTransfer: vscode.DataTransfer,
|
||||
token: vscode.CancellationToken,
|
||||
): Promise<vscode.DocumentPasteEdit | undefined> {
|
||||
const enabled = vscode.workspace.getConfiguration('markdown', document).get('editor.pasteUrlAsFormattedLink.enabled', true);
|
||||
if (!enabled) {
|
||||
const enabled = vscode.workspace.getConfiguration('markdown', document).get<'always' | 'smart' | 'never'>('editor.pasteUrlAsFormattedLink.enabled', 'smart');
|
||||
if (enabled === 'never') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,15 +65,26 @@ export async function getMarkdownLink(document: vscode.TextDocument, ranges: rea
|
|||
if (ranges.length === 0) {
|
||||
return;
|
||||
}
|
||||
const enabled = vscode.workspace.getConfiguration('markdown', document).get<'always' | 'smart' | 'never'>('editor.pasteUrlAsFormattedLink.enabled', 'always');
|
||||
|
||||
const edits: vscode.SnippetTextEdit[] = [];
|
||||
let placeHolderValue: number = ranges.length;
|
||||
let label: string = '';
|
||||
let smartPaste: boolean = false;
|
||||
for (let i = 0; i < ranges.length; i++) {
|
||||
const snippet = await tryGetUriListSnippet(document, urlList, token, document.getText(ranges[i]), placeHolderValue);
|
||||
if (enabled === 'smart') {
|
||||
const inMarkdownLink = checkPaste(document, ranges, /\[([^\]]*)\]\(([^)]*)\)/g, i);
|
||||
const inFencedCode = checkPaste(document, ranges, /^```[\s\S]*?```$/gm, i);
|
||||
const inFencedMath = checkPaste(document, ranges, /^\$\$[\s\S]*?\$\$$/gm, i);
|
||||
smartPaste = (inMarkdownLink || inFencedCode || inFencedMath);
|
||||
}
|
||||
|
||||
const snippet = await tryGetUriListSnippet(document, urlList, token, document.getText(ranges[i]), placeHolderValue, smartPaste);
|
||||
if (!snippet) {
|
||||
return;
|
||||
}
|
||||
|
||||
smartPaste = false;
|
||||
placeHolderValue--;
|
||||
edits.push(new vscode.SnippetTextEdit(ranges[i], snippet.snippet));
|
||||
label = snippet.label;
|
||||
|
@ -85,7 +96,20 @@ export async function getMarkdownLink(document: vscode.TextDocument, ranges: rea
|
|||
return { additionalEdits, label };
|
||||
}
|
||||
|
||||
export async function tryGetUriListSnippet(document: vscode.TextDocument, urlList: String, token: vscode.CancellationToken, title = '', placeHolderValue = 0): Promise<{ snippet: vscode.SnippetString; label: string } | undefined> {
|
||||
function checkPaste(document: vscode.TextDocument, ranges: readonly vscode.Range[], regex: RegExp, index: number): boolean {
|
||||
const rangeStartOffset = document.offsetAt(ranges[index].start);
|
||||
const rangeEndOffset = document.offsetAt(ranges[index].end);
|
||||
const matches = [...document.getText().matchAll(regex)];
|
||||
for (const match of matches) {
|
||||
if (match.index !== undefined && rangeStartOffset > match.index && rangeEndOffset < match.index + match[0].length) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export async function tryGetUriListSnippet(document: vscode.TextDocument, urlList: String, token: vscode.CancellationToken, title = '', placeHolderValue = 0, smartPaste = false): Promise<{ snippet: vscode.SnippetString; label: string } | undefined> {
|
||||
if (token.isCancellationRequested) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -99,7 +123,7 @@ export async function tryGetUriListSnippet(document: vscode.TextDocument, urlLis
|
|||
}
|
||||
}
|
||||
|
||||
return createUriListSnippet(document, uris, title, placeHolderValue);
|
||||
return createUriListSnippet(document, uris, title, placeHolderValue, smartPaste);
|
||||
}
|
||||
|
||||
interface UriListSnippetOptions {
|
||||
|
@ -122,6 +146,7 @@ export function createUriListSnippet(
|
|||
uris: readonly vscode.Uri[],
|
||||
title = '',
|
||||
placeholderValue = 0,
|
||||
smartPaste = false,
|
||||
options?: UriListSnippetOptions,
|
||||
): { snippet: vscode.SnippetString; label: string } | undefined {
|
||||
if (!uris.length) {
|
||||
|
@ -164,13 +189,21 @@ export function createUriListSnippet(
|
|||
snippet.appendText(`](${escapeMarkdownLinkPath(mdPath)})`);
|
||||
} else {
|
||||
insertedLinkCount++;
|
||||
snippet.appendText('[');
|
||||
snippet.appendPlaceholder(escapeBrackets(title) || 'Title', placeholderValue);
|
||||
if (externalUriSchemes.includes(uri.scheme)) {
|
||||
const uriString = uri.toString(true);
|
||||
snippet.appendText(`](${uriString})`);
|
||||
if (smartPaste) {
|
||||
if (externalUriSchemes.includes(uri.scheme)) {
|
||||
snippet.appendText(uri.toString(true));
|
||||
} else {
|
||||
snippet.appendText(escapeMarkdownLinkPath(mdPath));
|
||||
}
|
||||
} else {
|
||||
snippet.appendText(`](${escapeMarkdownLinkPath(mdPath)})`);
|
||||
snippet.appendText('[');
|
||||
snippet.appendPlaceholder(escapeBrackets(title) || 'Title', placeholderValue);
|
||||
if (externalUriSchemes.includes(uri.scheme)) {
|
||||
const uriString = uri.toString(true);
|
||||
snippet.appendText(`](${uriString})`);
|
||||
} else {
|
||||
snippet.appendText(`](${escapeMarkdownLinkPath(mdPath)})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue