From 90d7737045210f146791e5876b148d18a18ce6f3 Mon Sep 17 00:00:00 2001 From: Matt Bierner Date: Mon, 30 Jan 2017 15:18:18 -0800 Subject: [PATCH] Support Fragments for intra document markdown editor links Adds support for editor links with fragements for markdown. This jumps to the correct header location if one can be found --- .../markdown/src/documentLinkProvider.ts | 39 ++++++++----------- extensions/markdown/src/extension.ts | 24 +++++++++++- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/extensions/markdown/src/documentLinkProvider.ts b/extensions/markdown/src/documentLinkProvider.ts index 6ea12abd95680..afb11517fb56e 100644 --- a/extensions/markdown/src/documentLinkProvider.ts +++ b/extensions/markdown/src/documentLinkProvider.ts @@ -9,7 +9,6 @@ import * as vscode from 'vscode'; import * as path from 'path'; import { MarkdownEngine } from './markdownEngine'; -import { TableOfContentProvider } from './tableOfContentsProvider'; export default class MarkdownDocumentLinkProvider implements vscode.DocumentLinkProvider { @@ -22,8 +21,6 @@ export default class MarkdownDocumentLinkProvider implements vscode.DocumentLink const base = path.dirname(document.uri.fsPath); const text = document.getText(); - const toc = new TableOfContentProvider(this.engine, document); - this._linkPattern.lastIndex = 0; let match: RegExpMatchArray | null; while ((match = this._linkPattern.exec(text))) { @@ -35,7 +32,7 @@ export default class MarkdownDocumentLinkProvider implements vscode.DocumentLink try { results.push(new vscode.DocumentLink( new vscode.Range(linkStart, linkEnd), - this.normalizeLink(link, base, toc))); + this.normalizeLink(document, link, base))); } catch (e) { // noop } @@ -44,26 +41,22 @@ export default class MarkdownDocumentLinkProvider implements vscode.DocumentLink return results; } - private normalizeLink(link: string, base: string, toc: TableOfContentProvider): vscode.Uri { - let uri = vscode.Uri.parse(link); - if (!uri.scheme) { - if (uri.fragment && !uri.path) { - // local link - const line = toc.lookup(uri.fragment); - if (!isNaN(line)) { - return vscode.Uri.parse(`command:revealLine?${encodeURIComponent(JSON.stringify({ lineNumber: line, at: 'top' }))}`); - } - } + private normalizeLink(document: vscode.TextDocument, link: string, base: string): vscode.Uri { + const uri = vscode.Uri.parse(link); + if (uri.scheme) { + return uri; + } - // assume it must be a file - let file; - if (uri.path[0] === '/') { - file = path.join(vscode.workspace.rootPath, uri.path); - } else { - file = path.join(base, uri.path); - } - uri = vscode.Uri.file(file); + // assume it must be a file + let resourcePath; + if (!uri.path) { + resourcePath = document.uri.path; + } else if (uri.path[0] === '/') { + resourcePath = path.join(vscode.workspace.rootPath, uri.path); + } else { + resourcePath = path.join(base, uri.path); } - return uri; + + return vscode.Uri.parse(`command:_markdown.openDocumentLink?${encodeURIComponent(JSON.stringify({ fragment: uri.fragment, path: resourcePath }))}`); } } diff --git a/extensions/markdown/src/extension.ts b/extensions/markdown/src/extension.ts index 26093d4144847..ae70659572372 100644 --- a/extensions/markdown/src/extension.ts +++ b/extensions/markdown/src/extension.ts @@ -12,7 +12,7 @@ import { MarkdownEngine } from './markdownEngine'; import DocumentLinkProvider from './documentLinkProvider'; import MDDocumentSymbolProvider from './documentSymbolProvider'; import { MDDocumentContentProvider, getMarkdownUri, isMarkdownFile } from './previewContentProvider'; - +import { TableOfContentProvider } from './tableOfContentsProvider'; interface IPackageInfo { name: string; @@ -70,6 +70,28 @@ export function activate(context: vscode.ExtensionContext) { }); })); + context.subscriptions.push(vscode.commands.registerCommand('_markdown.openDocumentLink', (args) => { + const tryRevealLine = (editor: vscode.TextEditor) => { + if (editor && args.fragment) { + const toc = new TableOfContentProvider(engine, editor.document); + const line = toc.lookup(args.fragment); + if (!isNaN(line)) { + return editor.revealRange( + new vscode.Range(line, 0, line, 0), + vscode.TextEditorRevealType.AtTop); + } + } + }; + if (vscode.window.activeTextEditor && vscode.window.activeTextEditor.document.uri.path === args.path) { + return tryRevealLine(vscode.window.activeTextEditor); + } else { + const resource = vscode.Uri.file(args.path); + vscode.workspace.openTextDocument(resource) + .then(vscode.window.showTextDocument) + .then(tryRevealLine, _ => vscode.commands.executeCommand('vscode.open', resource)); + } + })); + context.subscriptions.push(vscode.workspace.onDidSaveTextDocument(document => { if (isMarkdownFile(document)) { const uri = getMarkdownUri(document.uri);