mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-23 01:58:53 +01:00
Markdown region folding (#55399)
* Add foldin g of regions to markdown * Add test for region folding * Tweak region identification regex
This commit is contained in:
committed by
Matt Bierner
parent
868140430d
commit
6a1515671f
@@ -7,6 +7,7 @@ import * as vscode from 'vscode';
|
||||
|
||||
import { MarkdownEngine } from '../markdownEngine';
|
||||
import { TableOfContentsProvider } from '../tableOfContentsProvider';
|
||||
import { Token } from 'markdown-it';
|
||||
|
||||
const rangeLimit = 5000;
|
||||
|
||||
@@ -16,15 +17,44 @@ export default class MarkdownFoldingProvider implements vscode.FoldingRangeProvi
|
||||
private readonly engine: MarkdownEngine
|
||||
) { }
|
||||
|
||||
private async getRegions(document: vscode.TextDocument): Promise<vscode.FoldingRange[]> {
|
||||
|
||||
const isStartRegion = (t: string) => /^\s*<!--\s*#?region\b.*-->/.test(t);
|
||||
const isEndRegion = (t: string) => /^\s*<!--\s*#?endregion\b.*-->/.test(t);
|
||||
|
||||
const isRegionMarker = (token: Token) => token.type === 'html_block' &&
|
||||
(isStartRegion(token.content) || isEndRegion(token.content));
|
||||
|
||||
|
||||
const tokens = await this.engine.parse(document.uri, document.getText());
|
||||
const regionMarkers = tokens.filter(isRegionMarker)
|
||||
.map(token => ({ line: token.map[0], isStart: isStartRegion(token.content) }));
|
||||
|
||||
const nestingStack: { line: number, isStart: boolean }[] = [];
|
||||
return regionMarkers
|
||||
.map(marker => {
|
||||
if (marker.isStart) {
|
||||
nestingStack.push(marker);
|
||||
} else if (nestingStack.length && nestingStack[nestingStack.length - 1].isStart) {
|
||||
return new vscode.FoldingRange(nestingStack.pop()!.line, marker.line, vscode.FoldingRangeKind.Region);
|
||||
} else {
|
||||
// noop: invalid nesting (i.e. [end, start] or [start, end, end])
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter((region: vscode.FoldingRange | null): region is vscode.FoldingRange => !!region);
|
||||
}
|
||||
|
||||
public async provideFoldingRanges(
|
||||
document: vscode.TextDocument,
|
||||
_: vscode.FoldingContext,
|
||||
_token: vscode.CancellationToken
|
||||
): Promise<vscode.FoldingRange[]> {
|
||||
const tocProvider = new TableOfContentsProvider(this.engine, document);
|
||||
let toc = await tocProvider.getToc();
|
||||
if (toc.length > rangeLimit) {
|
||||
toc = toc.slice(0, rangeLimit);
|
||||
let [regions, toc] = await Promise.all([this.getRegions(document), tocProvider.getToc()]);
|
||||
|
||||
if (toc.length > rangeLimit - regions.length) {
|
||||
toc = toc.slice(0, rangeLimit - regions.length);
|
||||
}
|
||||
|
||||
const foldingRanges = toc.map((entry, startIndex) => {
|
||||
@@ -44,7 +74,6 @@ export default class MarkdownFoldingProvider implements vscode.FoldingRangeProvi
|
||||
typeof end === 'number' ? end : document.lineCount - 1);
|
||||
});
|
||||
|
||||
|
||||
return foldingRanges;
|
||||
return [...regions, ...foldingRanges];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user