Files
vscode/extensions/markdown/src/tableOfContentsProvider.ts
Matt Bierner f7697a7f37 Support In-Document links inside of the markdown editor (#19411)
* Support In Document links inside of the markdown editor

Fixes #17288

* Cleaning up code to reduce duplication
2017-01-27 14:36:28 -08:00

78 lines
2.0 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as vscode from 'vscode';
import { MarkdownEngine, IToken } from './markdownEngine';
export interface TocEntry {
slug: string;
text: string;
line: number;
location: vscode.Location;
}
export class TableOfContentProvider {
private toc: TocEntry[];
public constructor(
private engine: MarkdownEngine,
private document: vscode.TextDocument) { }
public getToc(): TocEntry[] {
if (!this.toc) {
try {
this.toc = this.buildToc(this.document);
} catch (e) {
this.toc = [];
}
}
return this.toc;
}
public lookup(fragment: string): number {
const slug = TableOfContentProvider.slugify(fragment);
for (const entry of this.getToc()) {
if (entry.slug === slug) {
return entry.line;
}
}
return NaN;
}
private buildToc(document: vscode.TextDocument): any {
const toc: TocEntry[] = [];
const tokens: IToken[] = this.engine.parse(this.document.getText());
for (const heading of tokens.filter(token => token.type === 'heading_open')) {
const lineNumber = heading.map[0];
const line = document.lineAt(lineNumber);
const href = TableOfContentProvider.slugify(line.text);
if (href) {
toc.push({
slug: href,
text: TableOfContentProvider.getHeaderText(line.text),
line: lineNumber,
location: new vscode.Location(document.uri, line.range)
});
}
}
return toc;
}
private static getHeaderText(header: string): string {
return header.replace(/^\s*(#)+\s*(.*?)\s*\1*$/, '$2').trim();
}
public static slugify(header: string): string {
return encodeURI(TableOfContentProvider.getHeaderText(header)
.toLowerCase()
.replace(/\s/g, '-'));
}
}