diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 0d74e1ac674..4a6c326c19e 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -24,6 +24,7 @@ "onCommand:markdown.showLockedPreviewToSide", "onCommand:markdown.showSource", "onCommand:markdown.showPreviewSecuritySelector", + "onCommand:markdown.render", "onWebviewPanel:markdown.preview" ], "contributes": { @@ -328,4 +329,4 @@ "webpack": "^4.1.0", "webpack-cli": "^2.0.10" } -} \ No newline at end of file +} diff --git a/extensions/markdown-language-features/src/commands/index.ts b/extensions/markdown-language-features/src/commands/index.ts index e8c9651ee0c..68aff7ffcf5 100644 --- a/extensions/markdown-language-features/src/commands/index.ts +++ b/extensions/markdown-language-features/src/commands/index.ts @@ -10,3 +10,4 @@ export { RefreshPreviewCommand } from './refreshPreview'; export { ShowPreviewSecuritySelectorCommand } from './showPreviewSecuritySelector'; export { MoveCursorToPositionCommand } from './moveCursorToPosition'; export { ToggleLockCommand } from './toggleLock'; +export { RenderDocument } from './renderDocument'; diff --git a/extensions/markdown-language-features/src/commands/renderDocument.ts b/extensions/markdown-language-features/src/commands/renderDocument.ts new file mode 100644 index 00000000000..3d7a0bc29a0 --- /dev/null +++ b/extensions/markdown-language-features/src/commands/renderDocument.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; + +import { Command } from '../commandManager'; +import { MarkdownEngine } from '../markdownEngine'; +import { SkinnyTextDocument } from '../tableOfContentsProvider'; + +export class RenderDocument implements Command { + public readonly id = 'markdown.render'; + + public constructor( + private readonly engine: MarkdownEngine + ) { } + + public async execute(document?: SkinnyTextDocument | string): Promise { + if (!document) { + if (!vscode.window.activeTextEditor) { + return; + } + + document = vscode.window.activeTextEditor.document; + } + + return this.engine.render(document); + } +} diff --git a/extensions/markdown-language-features/src/extension.ts b/extensions/markdown-language-features/src/extension.ts index 3fe2c9d4cd3..44e8873b16d 100644 --- a/extensions/markdown-language-features/src/extension.ts +++ b/extensions/markdown-language-features/src/extension.ts @@ -83,6 +83,7 @@ function registerMarkdownCommands( commandManager.register(new commands.ShowPreviewSecuritySelectorCommand(previewSecuritySelector, previewManager)); commandManager.register(new commands.OpenDocumentLinkCommand(engine)); commandManager.register(new commands.ToggleLockCommand(previewManager)); + commandManager.register(new commands.RenderDocument(engine)); return commandManager; } diff --git a/extensions/markdown-language-features/src/markdownEngine.ts b/extensions/markdown-language-features/src/markdownEngine.ts index 613d207712b..9b51dc06b86 100644 --- a/extensions/markdown-language-features/src/markdownEngine.ts +++ b/extensions/markdown-language-features/src/markdownEngine.ts @@ -118,7 +118,7 @@ export class MarkdownEngine { return md; } - private tokenize( + private tokenizeDocument( document: SkinnyTextDocument, config: MarkdownItConfig, engine: MarkdownIt @@ -131,16 +131,23 @@ export class MarkdownEngine { this.currentDocument = document.uri; this._slugCount = new Map(); - const text = document.getText(); - const tokens = engine.parse(text.replace(UNICODE_NEWLINE_REGEX, ''), {}); + const tokens = this.tokenizeString(document.getText(), engine); this._tokenCache.update(document, config, tokens); return tokens; } - public async render(document: SkinnyTextDocument): Promise { - const config = this.getConfig(document.uri); + private tokenizeString(text: string, engine: MarkdownIt) { + return engine.parse(text.replace(UNICODE_NEWLINE_REGEX, ''), {}); + } + + public async render(document: SkinnyTextDocument | string): Promise { + const config = this.getConfig(typeof document === 'string' ? undefined : document.uri); const engine = await this.getEngine(config); - return engine.renderer.render(this.tokenize(document, config, engine), { + const tokens = typeof document === 'string' + ? this.tokenizeString(document, engine) + : this.tokenizeDocument(document, config, engine); + + return engine.renderer.render(tokens, { ...(engine as any).options, ...config }, {}); @@ -149,14 +156,14 @@ export class MarkdownEngine { public async parse(document: SkinnyTextDocument): Promise { const config = this.getConfig(document.uri); const engine = await this.getEngine(config); - return this.tokenize(document, config, engine); + return this.tokenizeDocument(document, config, engine); } public cleanCache(): void { this._tokenCache.clean(); } - private getConfig(resource: vscode.Uri): MarkdownItConfig { + private getConfig(resource?: vscode.Uri): MarkdownItConfig { const config = vscode.workspace.getConfiguration('markdown', resource); return { breaks: config.get('preview.breaks', false), diff --git a/extensions/markdown-language-features/src/test/engine.test.ts b/extensions/markdown-language-features/src/test/engine.test.ts new file mode 100644 index 00000000000..3cd4f86693e --- /dev/null +++ b/extensions/markdown-language-features/src/test/engine.test.ts @@ -0,0 +1,32 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import * as vscode from 'vscode'; +import 'mocha'; + +import { InMemoryDocument } from './inMemoryDocument'; +import { createNewMarkdownEngine } from './engine'; + +const testFileName = vscode.Uri.file('test.md'); + +suite('markdown.engine', () => { + suite('rendering', () => { + const input = '# hello\n\nworld!'; + const output = '

hello

\n' + + '

world!

\n'; + + test('Renders a document', async () => { + const doc = new InMemoryDocument(testFileName, input); + const engine = createNewMarkdownEngine(); + assert.strictEqual(await engine.render(doc), output); + }); + + test('Renders a string', async () => { + const engine = createNewMarkdownEngine(); + assert.strictEqual(await engine.render(input), output); + }); + }); +});