From fe360ffe894d0c72592590932762f7c69453b321 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 10 Jan 2024 11:57:08 -0800 Subject: [PATCH 1/2] Use markdown engine to enable/disable smart paste Fixes #188863 Fixes #188958 Fixes #188868 This is more reliable than using the regular expressions. However the regular expressions are still needed for inline elements --- .../markdown-language-features/package.json | 1 + .../src/extension.shared.ts | 10 +- .../copyFiles/pasteUrlProvider.ts | 82 +++++++++----- .../src/markdownEngine.ts | 6 + .../src/test/markdownLink.test.ts | 107 +++++++++++++----- .../markdown-language-features/yarn.lock | 19 ++++ 6 files changed, 163 insertions(+), 62 deletions(-) diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 160ddbb3a7b54..839219f5a9478 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -756,6 +756,7 @@ "@types/picomatch": "^2.3.0", "@types/vscode-notebook-renderer": "^1.60.0", "@types/vscode-webview": "^1.57.0", + "@vscode/markdown-it-katex": "^1.0.1", "lodash.throttle": "^4.1.1", "vscode-languageserver-types": "^3.17.2", "vscode-markdown-languageservice": "^0.3.0-alpha.3" diff --git a/extensions/markdown-language-features/src/extension.shared.ts b/extensions/markdown-language-features/src/extension.shared.ts index aceb8f8b5ae19..d6499591039ef 100644 --- a/extensions/markdown-language-features/src/extension.shared.ts +++ b/extensions/markdown-language-features/src/extension.shared.ts @@ -7,13 +7,13 @@ import * as vscode from 'vscode'; import { MdLanguageClient } from './client/client'; import { CommandManager } from './commandManager'; import { registerMarkdownCommands } from './commands/index'; -import { registerLinkPasteSupport } from './languageFeatures/copyFiles/pasteUrlProvider'; +import { registerPasteUrlSupport } from './languageFeatures/copyFiles/pasteUrlProvider'; import { registerResourceDropOrPasteSupport } from './languageFeatures/copyFiles/dropOrPasteResource'; import { registerDiagnosticSupport } from './languageFeatures/diagnostics'; import { registerFindFileReferenceSupport } from './languageFeatures/fileReferences'; import { registerUpdateLinksOnRename } from './languageFeatures/linkUpdater'; import { ILogger } from './logging'; -import { MarkdownItEngine } from './markdownEngine'; +import { IMdParser, MarkdownItEngine } from './markdownEngine'; import { MarkdownContributionProvider } from './markdownExtensions'; import { MdDocumentRenderer } from './preview/documentRenderer'; import { MarkdownPreviewManager } from './preview/previewManager'; @@ -40,7 +40,7 @@ export function activateShared( const previewManager = new MarkdownPreviewManager(contentProvider, logger, contributions, opener); context.subscriptions.push(previewManager); - context.subscriptions.push(registerMarkdownLanguageFeatures(client, commandManager)); + context.subscriptions.push(registerMarkdownLanguageFeatures(client, commandManager, engine)); context.subscriptions.push(registerMarkdownCommands(commandManager, previewManager, telemetryReporter, cspArbiter, engine)); context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(() => { @@ -51,6 +51,7 @@ export function activateShared( function registerMarkdownLanguageFeatures( client: MdLanguageClient, commandManager: CommandManager, + parser: IMdParser, ): vscode.Disposable { const selector: vscode.DocumentSelector = { language: 'markdown', scheme: '*' }; return vscode.Disposable.from( @@ -58,8 +59,7 @@ function registerMarkdownLanguageFeatures( registerDiagnosticSupport(selector, commandManager), registerFindFileReferenceSupport(commandManager, client), registerResourceDropOrPasteSupport(selector), - registerLinkPasteSupport(selector), + registerPasteUrlSupport(selector, parser), registerUpdateLinksOnRename(client), ); } - diff --git a/extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts b/extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts index a4998e787f84f..c051683ce962d 100644 --- a/extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts +++ b/extensions/markdown-language-features/src/languageFeatures/copyFiles/pasteUrlProvider.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; +import { IMdParser } from '../../markdownEngine'; import { ITextDocument } from '../../types/textDocument'; import { Mime } from '../../util/mimes'; import { createInsertUriListEdit, externalUriSchemes } from './shared'; @@ -31,6 +32,10 @@ class PasteUrlEditProvider implements vscode.DocumentPasteEditProvider { public static readonly pasteMimeTypes = [Mime.textPlain]; + constructor( + private readonly _parser: IMdParser, + ) { } + async provideDocumentPasteEdits( document: vscode.TextDocument, ranges: readonly vscode.Range[], @@ -63,7 +68,7 @@ class PasteUrlEditProvider implements vscode.DocumentPasteEditProvider { workspaceEdit.set(document.uri, edit.edits); pasteEdit.additionalEdit = workspaceEdit; - if (!shouldInsertMarkdownLinkByDefault(document, pasteUrlSetting, ranges)) { + if (!shouldInsertMarkdownLinkByDefault(this._parser, document, pasteUrlSetting, ranges, token)) { pasteEdit.yieldTo = [{ mimeType: Mime.textPlain }]; } @@ -71,45 +76,59 @@ class PasteUrlEditProvider implements vscode.DocumentPasteEditProvider { } } -export function registerLinkPasteSupport(selector: vscode.DocumentSelector,) { - return vscode.languages.registerDocumentPasteEditProvider(selector, new PasteUrlEditProvider(), { +export function registerPasteUrlSupport(selector: vscode.DocumentSelector, parser: IMdParser) { + return vscode.languages.registerDocumentPasteEditProvider(selector, new PasteUrlEditProvider(parser), { id: PasteUrlEditProvider.id, pasteMimeTypes: PasteUrlEditProvider.pasteMimeTypes, }); } -const smartPasteRegexes = [ +const smartPasteLineRegexes = [ { regex: /(\[[^\[\]]*](?:\([^\(\)]*\)|\[[^\[\]]*]))/g }, // In a Markdown link - { regex: /^```[\s\S]*?```$/gm }, // In a backtick fenced code block - { regex: /^~~~[\s\S]*?~~~$/gm }, // In a tildefenced code block - { regex: /^\$\$[\s\S]*?\$\$$/gm }, // In a fenced math block + { regex: /\$\$[\s\S]*?\$\$/gm }, // In a fenced math block { regex: /`[^`]*`/g }, // In inline code { regex: /\$[^$]*\$/g }, // In inline math + { regex: /^[ ]{0,3}\[\w+\]:\s.*$/g }, // Block link definition (needed as tokens are not generated for these) ]; -export function shouldInsertMarkdownLinkByDefault(document: ITextDocument, pasteUrlSetting: PasteUrlAsMarkdownLink, ranges: readonly vscode.Range[]): boolean { +export async function shouldInsertMarkdownLinkByDefault( + parser: IMdParser, + document: ITextDocument, + pasteUrlSetting: PasteUrlAsMarkdownLink, + ranges: readonly vscode.Range[], + token: vscode.CancellationToken, +): Promise { switch (pasteUrlSetting) { case PasteUrlAsMarkdownLink.Always: { return true; } case PasteUrlAsMarkdownLink.Smart: { - return ranges.every(range => shouldSmartPasteForSelection(document, range)); + return checkSmart(); } case PasteUrlAsMarkdownLink.SmartWithSelection: { - return ( - // At least one range must not be empty - ranges.some(range => document.getText(range).trim().length > 0) - // And all ranges must be smart - && ranges.every(range => shouldSmartPasteForSelection(document, range)) - ); + // At least one range must not be empty + if (!ranges.some(range => document.getText(range).trim().length > 0)) { + return false; + } + // And all ranges must be smart + return checkSmart(); } default: { return false; } } + + async function checkSmart(): Promise { + return (await Promise.all(ranges.map(range => shouldSmartPasteForSelection(parser, document, range, token)))).every(x => x); + } } -function shouldSmartPasteForSelection(document: ITextDocument, selectedRange: vscode.Range): boolean { +async function shouldSmartPasteForSelection( + parser: IMdParser, + document: ITextDocument, + selectedRange: vscode.Range, + token: vscode.CancellationToken, +): Promise { // Disable for multi-line selections if (selectedRange.start.line !== selectedRange.end.line) { return false; @@ -125,18 +144,25 @@ function shouldSmartPasteForSelection(document: ITextDocument, selectedRange: vs return false; } - // TODO: use proper parsing instead of regexes - for (const regex of smartPasteRegexes) { - const matches = [...document.getText().matchAll(regex.regex)]; - for (const match of matches) { - if (match.index !== undefined) { - const matchRange = new vscode.Range( - document.positionAt(match.index), - document.positionAt(match.index + match[0].length) - ); - if (matchRange.intersection(selectedRange)) { - return false; - } + // Check if selection is inside a special block level element using markdown engine + const tokens = await parser.tokenize(document); + if (token.isCancellationRequested) { + return false; + } + for (const token of tokens) { + if (token.map && token.map[0] <= selectedRange.start.line && token.map[1] > selectedRange.start.line) { + if (!['paragraph_open', 'inline', 'heading_open', 'ordered_list_open', 'bullet_list_open', 'list_item_open', 'blockquote_open'].includes(token.type)) { + return false; + } + } + } + + // Run additional regex checks on the current line to check if we are inside an inline element + const line = document.getText(new vscode.Range(selectedRange.start.line, 0, selectedRange.start.line, Number.MAX_SAFE_INTEGER)); + for (const regex of smartPasteLineRegexes) { + for (const match of line.matchAll(regex.regex)) { + if (match.index !== undefined && selectedRange.start.character >= match.index && selectedRange.start.character <= match.index + match[0].length) { + return false; } } } diff --git a/extensions/markdown-language-features/src/markdownEngine.ts b/extensions/markdown-language-features/src/markdownEngine.ts index 2a2e5896dbdb3..8d67bf6f9c06a 100644 --- a/extensions/markdown-language-features/src/markdownEngine.ts +++ b/extensions/markdown-language-features/src/markdownEngine.ts @@ -118,6 +118,12 @@ export class MarkdownItEngine implements IMdParser { }); } + + public async getEngine(resource: vscode.Uri | undefined): Promise { + const config = this._getConfig(resource); + return this._getEngine(config); + } + private async _getEngine(config: MarkdownItConfig): Promise { if (!this._md) { this._md = (async () => { diff --git a/extensions/markdown-language-features/src/test/markdownLink.test.ts b/extensions/markdown-language-features/src/test/markdownLink.test.ts index 62cfa9e9c8aa0..7b5849e47e25d 100644 --- a/extensions/markdown-language-features/src/test/markdownLink.test.ts +++ b/extensions/markdown-language-features/src/test/markdownLink.test.ts @@ -8,6 +8,8 @@ import * as vscode from 'vscode'; import { InMemoryDocument } from '../client/inMemoryDocument'; import { PasteUrlAsMarkdownLink, findValidUriInText, shouldInsertMarkdownLinkByDefault } from '../languageFeatures/copyFiles/pasteUrlProvider'; import { createInsertUriListEdit } from '../languageFeatures/copyFiles/shared'; +import { createNewMarkdownEngine } from './engine'; +import { noopToken } from '../util/cancellation'; function makeTestDoc(contents: string) { return new InMemoryDocument(vscode.Uri.file('test.md'), contents); @@ -136,88 +138,135 @@ suite('createEditAddingLinksForUriList', () => { suite('shouldInsertMarkdownLinkByDefault', () => { - test('Smart should enabled for selected plain text', () => { + test('Smart should be enabled for selected plain text', async () => { assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc('hello world'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 12)]), + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('hello world'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 12)], noopToken), true); }); - test('Smart should enabled for empty selection', () => { + test('Smart should be enabled in headers', async () => { assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc('xyz'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 0, 0, 0)]), + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('# title'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 2, 0, 2)], noopToken), true); }); - test('SmartWithSelection should disable for empty selection', () => { + test('Smart should be enabled in lists', async () => { assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc('xyz'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 0)]), + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('1. text'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 3, 0, 3)], noopToken), + true); + }); + + test('Smart should be enabled in blockquotes', async () => { + assert.strictEqual( + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('> text'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 3, 0, 3)], noopToken), + true); + }); + + test('Smart should be disabled in indented code blocks', async () => { + assert.strictEqual( + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc(' code'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 4, 0, 4)], noopToken), false); }); - test('Smart should disable for selected link', () => { + test('Smart should be disabled in fenced code blocks', async () => { assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc('https://www.microsoft.com'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 25)]), + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('```\r\n\r\n```'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 5, 0, 5)], noopToken), + false); + + assert.strictEqual( + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('~~~\r\n\r\n~~~'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 5, 0, 5)], noopToken), false); }); - test('Smart should disable for selected link with trailing whitespace', () => { + test('Smart should be disabled in math blocks', async () => { + const katex = (await import('@vscode/markdown-it-katex')).default; + const engine = createNewMarkdownEngine(); + (await engine.getEngine(undefined)).use(katex); assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc(' https://www.microsoft.com '), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 30)]), + await shouldInsertMarkdownLinkByDefault(engine, makeTestDoc('$$\r\n\r\n$$'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 5, 0, 5)], noopToken), false); }); - test('Should evaluate pasteAsMarkdownLink as true for a link pasted in square brackets', () => { + test('Smart should be disabled in link definitions', async () => { assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc('[abc]'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 1, 0, 4)]), - true); + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('[ref]: http://example.com'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 4, 0, 6)], noopToken), + false); + + assert.strictEqual( + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('[ref]: '), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 7, 0, 7)], noopToken), + false); }); - test('Should evaluate pasteAsMarkdownLink as false for selected whitespace and new lines', () => { + test('Smart should be disabled in html blocks', async () => { assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc(' \r\n\r\n'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 7)]), + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('

\na\n

'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(1, 0, 1, 0)], noopToken), false); }); - test('Should evaluate pasteAsMarkdownLink as false for pasting within a backtick code block', () => { + test('Smart should be disabled in Markdown links', async () => { assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc('```\r\n\r\n```'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 5, 0, 5)]), + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('[a](bcdef)'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 4, 0, 6)], noopToken), false); }); - test('Should evaluate pasteAsMarkdownLink as false for pasting within a tilde code block', () => { + test('Smart should be disabled in Markdown images', async () => { assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc('~~~\r\n\r\n~~~'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 5, 0, 5)]), + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('![a](bcdef)'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 5, 0, 10)], noopToken), false); }); - test('Should evaluate pasteAsMarkdownLink as false for pasting within a math block', () => { + test('Smart should be disabled in inline code', async () => { assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc('$$$\r\n\r\n$$$'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 5, 0, 5)]), + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('``'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 1, 0, 1)], noopToken), false); + + assert.strictEqual( + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('``'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 0, 0, 0)], noopToken), + false); + }); + + test('Smart should be disabled in inline math', async () => { + assert.strictEqual( + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('$$'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 1, 0, 1)], noopToken), + false); + }); + + test('Smart should be enabled for empty selection', async () => { + assert.strictEqual( + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('xyz'), PasteUrlAsMarkdownLink.Smart, [new vscode.Range(0, 0, 0, 0)], noopToken), + true); }); - test('Should evaluate pasteAsMarkdownLink as false for pasting within a Markdown link', () => { + test('SmartWithSelection should disable for empty selection', async () => { assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc('[a](bcdef)'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 4, 0, 6)]), + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('xyz'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 0)], noopToken), false); }); - test('Should evaluate pasteAsMarkdownLink as false for pasting within a Markdown image link', () => { + test('Smart should disable for selected link', async () => { assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc('![a](bcdef)'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 5, 0, 10)]), + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('https://www.microsoft.com'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 25)], noopToken), false); }); - test('Should evaluate pasteAsMarkdownLink as false for pasting within inline code', () => { + test('Smart should disable for selected link with trailing whitespace', async () => { assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc('``'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 1, 0, 1)]), + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc(' https://www.microsoft.com '), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 30)], noopToken), false); }); - test('Should evaluate pasteAsMarkdownLink as false for pasting within inline math', () => { + test('Should evaluate pasteAsMarkdownLink as true for a link pasted in square brackets', async () => { + assert.strictEqual( + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc('[abc]'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 1, 0, 4)], noopToken), + true); + }); + + test('Should evaluate pasteAsMarkdownLink as false for selected whitespace and new lines', async () => { assert.strictEqual( - shouldInsertMarkdownLinkByDefault(makeTestDoc('$$'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 1, 0, 1)]), + await shouldInsertMarkdownLinkByDefault(createNewMarkdownEngine(), makeTestDoc(' \r\n\r\n'), PasteUrlAsMarkdownLink.SmartWithSelection, [new vscode.Range(0, 0, 0, 7)], noopToken), false); }); + + }); }); diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index 5e3d1826af56e..c3022ef86f7e6 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -166,6 +166,13 @@ resolved "https://registry.yarnpkg.com/@vscode/l10n/-/l10n-0.0.10.tgz#9c513107c690c0dd16e3ec61e453743de15ebdb0" integrity sha512-E1OCmDcDWa0Ya7vtSjp/XfHFGqYJfh+YPC1RkATU71fTac+j1JjCcB3qwSzmlKAighx2WxhLlfhS0RwAN++PFQ== +"@vscode/markdown-it-katex@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@vscode/markdown-it-katex/-/markdown-it-katex-1.0.1.tgz#79c6e7312074e1f897cc22c42ce078d1e72003b0" + integrity sha512-O/HiT5Uc6rN6rSx8tDdgwO1tLSn/lrNeikTzYw1EBG6B2IGLKw4I4e/GBh9DRNSdE9PajCA0tsVBz86qyA7B3A== + dependencies: + katex "^0.16.4" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -184,6 +191,11 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -204,6 +216,13 @@ highlight.js@^11.8.0: resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.8.0.tgz#966518ea83257bae2e7c9a48596231856555bb65" integrity sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg== +katex@^0.16.4: + version "0.16.9" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.9.tgz#bc62d8f7abfea6e181250f85a56e4ef292dcb1fa" + integrity sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ== + dependencies: + commander "^8.3.0" + linkify-it@^3.0.1: version "3.0.3" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" From d73f4ee11e3444adb77f162a9893552dcb4d0814 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Wed, 10 Jan 2024 12:53:19 -0800 Subject: [PATCH 2/2] Add typings --- .../src/typings/markdown-it-katex.d.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 extensions/markdown-language-features/src/typings/markdown-it-katex.d.ts diff --git a/extensions/markdown-language-features/src/typings/markdown-it-katex.d.ts b/extensions/markdown-language-features/src/typings/markdown-it-katex.d.ts new file mode 100644 index 0000000000000..7e9ed78cf5e40 --- /dev/null +++ b/extensions/markdown-language-features/src/typings/markdown-it-katex.d.ts @@ -0,0 +1,6 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +declare module '@vscode/markdown-it-katex';