diff --git a/extensions/markdown/src/commands.ts b/extensions/markdown/src/commands.ts index 6a759d5708f..2cb9ae5668f 100644 --- a/extensions/markdown/src/commands.ts +++ b/extensions/markdown/src/commands.ts @@ -10,10 +10,12 @@ import * as vscode from 'vscode'; import * as path from 'path'; import { Command } from './commandManager'; -import { ExtensionContentSecurityPolicyArbiter } from './security'; +import { ExtensionContentSecurityPolicyArbiter, PreviewSecuritySelector } from './security'; import { getMarkdownUri, MDDocumentContentProvider, isMarkdownFile } from './previewContentProvider'; import TelemetryReporter from 'vscode-extension-telemetry'; import { Logger } from './logger'; +import { TableOfContentsProvider } from './tableOfContentsProvider'; +import { MarkdownEngine } from './markdownEngine'; function getViewColumn(sideBySide: boolean): vscode.ViewColumn | undefined { @@ -88,8 +90,8 @@ export class ShowPreviewCommand implements Command { public readonly id = 'markdown.showPreview'; public constructor( - private cspArbiter: ExtensionContentSecurityPolicyArbiter, - private telemetryReporter: TelemetryReporter | null + private readonly cspArbiter: ExtensionContentSecurityPolicyArbiter, + private readonly telemetryReporter: TelemetryReporter | null ) { } public execute(uri?: vscode.Uri) { @@ -101,8 +103,8 @@ export class ShowPreviewToSideCommand implements Command { public readonly id = 'markdown.showPreviewToSide'; public constructor( - private cspArbiter: ExtensionContentSecurityPolicyArbiter, - private telemetryReporter: TelemetryReporter | null + private readonly cspArbiter: ExtensionContentSecurityPolicyArbiter, + private readonly telemetryReporter: TelemetryReporter | null ) { } public execute(uri?: vscode.Uri) { @@ -134,7 +136,7 @@ export class RefreshPreviewCommand implements Command { public readonly id = 'markdown.refreshPreview'; public constructor( - private contentProvider: MDDocumentContentProvider + private readonly contentProvider: MDDocumentContentProvider ) { } public execute(resource: string | undefined) { @@ -154,6 +156,25 @@ export class RefreshPreviewCommand implements Command { } } +export class ShowPreviewSecuritySelectorCommand implements Command { + public readonly id = 'markdown.showPreviewSecuritySelector'; + + public constructor( + private readonly previewSecuritySelector: PreviewSecuritySelector + ) { } + + public execute(resource: string | undefined) { + if (resource) { + const source = vscode.Uri.parse(resource).query; + this.previewSecuritySelector.showSecutitySelectorForResource(vscode.Uri.parse(source)); + } else { + if (vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.languageId === 'markdown') { + this.previewSecuritySelector.showSecutitySelectorForResource(vscode.window.activeTextEditor.document.uri); + } + } + } +} + export class RevealLineCommand implements Command { public readonly id = '_markdown.revealLine'; @@ -179,6 +200,26 @@ export class RevealLineCommand implements Command { } } +export class DidClickCommand implements Command { + public readonly id = '_markdown.didClick'; + + public execute(uri: string, line: number) { + const sourceUri = vscode.Uri.parse(decodeURIComponent(uri)); + return vscode.workspace.openTextDocument(sourceUri) + .then(document => vscode.window.showTextDocument(document)) + .then(editor => + vscode.commands.executeCommand('revealLine', { lineNumber: Math.floor(line), at: 'center' }) + .then(() => editor)) + .then(editor => { + if (editor) { + editor.selection = new vscode.Selection( + new vscode.Position(Math.floor(line), 0), + new vscode.Position(Math.floor(line), 0)); + } + }); + } +} + export class MoveCursorToPositionCommand implements Command { public readonly id = '_markdown.moveCursorToPosition'; @@ -192,3 +233,59 @@ export class MoveCursorToPositionCommand implements Command { vscode.window.activeTextEditor.selection = selection; } } + +export class OnPreviewStyleLoadErrorCommand implements Command { + public readonly id = '_markdown.onPreviewStyleLoadError'; + + public execute(resources: string[]) { + vscode.window.showWarningMessage(localize('onPreviewStyleLoadError', "Could not load 'markdown.styles': {0}", resources.join(', '))); + } +} + +export interface OpenDocumentLinkArgs { + path: string; + fragment: string; +} + +export class OpenDocumentLinkCommand implements Command { + public readonly id = '_markdown.openDocumentLink'; + + public constructor( + private readonly engine: MarkdownEngine + ) { } + + public execute(args: OpenDocumentLinkArgs) { + const tryRevealLine = async (editor: vscode.TextEditor) => { + if (editor && args.fragment) { + const toc = new TableOfContentsProvider(this.engine, editor.document); + const line = await toc.lookup(args.fragment); + if (!isNaN(line)) { + return editor.revealRange( + new vscode.Range(line, 0, line, 0), + vscode.TextEditorRevealType.AtTop); + } + } + }; + + const tryOpen = async (path: string) => { + if (vscode.window.activeTextEditor && isMarkdownFile(vscode.window.activeTextEditor.document) && vscode.window.activeTextEditor.document.uri.fsPath === path) { + return tryRevealLine(vscode.window.activeTextEditor); + } else { + const resource = vscode.Uri.file(path); + return vscode.workspace.openTextDocument(resource) + .then(vscode.window.showTextDocument) + .then(tryRevealLine); + } + }; + + return tryOpen(args.path).catch(() => { + if (path.extname(args.path) === '') { + return tryOpen(args.path + '.md'); + } + const resource = vscode.Uri.file(args.path); + return Promise.resolve(void 0) + .then(() => vscode.commands.executeCommand('vscode.open', resource)) + .then(() => void 0); + }); + } +} diff --git a/extensions/markdown/src/extension.ts b/extensions/markdown/src/extension.ts index 88b08bfde56..708b1242073 100644 --- a/extensions/markdown/src/extension.ts +++ b/extensions/markdown/src/extension.ts @@ -5,8 +5,6 @@ 'use strict'; -import * as nls from 'vscode-nls'; -const localize = nls.config(process.env.VSCODE_NLS_CONFIG)(); import * as vscode from 'vscode'; import * as path from 'path'; import TelemetryReporter from 'vscode-extension-telemetry'; @@ -15,7 +13,6 @@ import LinkProvider from './documentLinkProvider'; import MDDocumentSymbolProvider from './documentSymbolProvider'; import { ExtensionContentSecurityPolicyArbiter, PreviewSecuritySelector } from './security'; import { MDDocumentContentProvider, getMarkdownUri, isMarkdownFile } from './previewContentProvider'; -import { TableOfContentsProvider } from './tableOfContentsProvider'; import { Logger } from './logger'; import { CommandManager } from './commandManager'; import * as commands from './commands'; @@ -26,11 +23,6 @@ interface IPackageInfo { aiKey: string; } -interface OpenDocumentLinkArgs { - path: string; - fragment: string; -} - const resolveExtensionResources = (extension: vscode.Extension, stylePath: string): vscode.Uri => { const resource = vscode.Uri.parse(stylePath); if (resource.scheme) { @@ -109,72 +101,10 @@ export function activate(context: vscode.ExtensionContext) { commandManager.register(new commands.RefreshPreviewCommand(contentProvider)); commandManager.register(new commands.RevealLineCommand(logger)); commandManager.register(new commands.MoveCursorToPositionCommand()); - - context.subscriptions.push(vscode.commands.registerCommand('_markdown.didClick', (uri: string, line) => { - const sourceUri = vscode.Uri.parse(decodeURIComponent(uri)); - return vscode.workspace.openTextDocument(sourceUri) - .then(document => vscode.window.showTextDocument(document)) - .then(editor => - vscode.commands.executeCommand('revealLine', { lineNumber: Math.floor(line), at: 'center' }) - .then(() => editor)) - .then(editor => { - if (editor) { - editor.selection = new vscode.Selection( - new vscode.Position(Math.floor(line), 0), - new vscode.Position(Math.floor(line), 0)); - } - }); - })); - - context.subscriptions.push(vscode.commands.registerCommand('_markdown.openDocumentLink', (args: OpenDocumentLinkArgs) => { - const tryRevealLine = async (editor: vscode.TextEditor) => { - if (editor && args.fragment) { - const toc = new TableOfContentsProvider(engine, editor.document); - const line = await toc.lookup(args.fragment); - if (!isNaN(line)) { - return editor.revealRange( - new vscode.Range(line, 0, line, 0), - vscode.TextEditorRevealType.AtTop); - } - } - }; - - const tryOpen = async (path: string) => { - if (vscode.window.activeTextEditor && isMarkdownFile(vscode.window.activeTextEditor.document) && vscode.window.activeTextEditor.document.uri.fsPath === path) { - return tryRevealLine(vscode.window.activeTextEditor); - } else { - const resource = vscode.Uri.file(path); - return vscode.workspace.openTextDocument(resource) - .then(vscode.window.showTextDocument) - .then(tryRevealLine); - } - }; - - return tryOpen(args.path).catch(() => { - if (path.extname(args.path) === '') { - return tryOpen(args.path + '.md'); - } - const resource = vscode.Uri.file(args.path); - return Promise.resolve(void 0) - .then(() => vscode.commands.executeCommand('vscode.open', resource)) - .then(() => void 0); - }); - })); - - context.subscriptions.push(vscode.commands.registerCommand('markdown.showPreviewSecuritySelector', (resource: string | undefined) => { - if (resource) { - const source = vscode.Uri.parse(resource).query; - previewSecuritySelector.showSecutitySelectorForResource(vscode.Uri.parse(source)); - } else { - if (vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.languageId === 'markdown') { - previewSecuritySelector.showSecutitySelectorForResource(vscode.window.activeTextEditor.document.uri); - } - } - })); - - context.subscriptions.push(vscode.commands.registerCommand('_markdown.onPreviewStyleLoadError', (resources: string[]) => { - vscode.window.showWarningMessage(localize('onPreviewStyleLoadError', "Could not load 'markdown.styles': {0}", resources.join(', '))); - })); + commandManager.register(new commands.ShowPreviewSecuritySelectorCommand(previewSecuritySelector)); + commandManager.register(new commands.OnPreviewStyleLoadErrorCommand()); + commandManager.register(new commands.DidClickCommand()); + commandManager.register(new commands.OpenDocumentLinkCommand(engine)); context.subscriptions.push(vscode.workspace.onDidSaveTextDocument(document => { if (isMarkdownFile(document)) {