diff --git a/extensions/markdown-language-features/src/features/foldingProvider.ts b/extensions/markdown-language-features/src/features/foldingProvider.ts index 3874cc32f87..8f9d4969924 100644 --- a/extensions/markdown-language-features/src/features/foldingProvider.ts +++ b/extensions/markdown-language-features/src/features/foldingProvider.ts @@ -49,8 +49,8 @@ export default class MarkdownFoldingProvider implements vscode.FoldingRangeProvi _: vscode.FoldingContext, _token: vscode.CancellationToken ): Promise { - const [regions, sections] = await Promise.all([this.getRegions(document), this.getHeaderFoldingRanges(document)]); - return [...regions, ...sections].slice(0, rangeLimit); + const [regions, sections, lists] = await Promise.all([this.getRegions(document), this.getHeaderFoldingRanges(document), this.getListFoldingRanges(document)]); + return [...regions, ...sections, ...lists].slice(0, rangeLimit); } private async getHeaderFoldingRanges(document: vscode.TextDocument) { @@ -64,4 +64,18 @@ export default class MarkdownFoldingProvider implements vscode.FoldingRangeProvi return new vscode.FoldingRange(entry.line, endLine); }); } + + private async getListFoldingRanges(document: vscode.TextDocument): Promise { + + const isMultiLineListOpen = (token: Token) => + token.type === 'list_item_open' && token.map[1] > token.map[0]; + + const tokens = await this.engine.parse(document.uri, document.getText()); + const multiLineListItems = tokens.filter(isMultiLineListOpen); + return multiLineListItems.map(listItem => { + const start = listItem.map[0]; + const end = listItem.map[1] - 1; + return new vscode.FoldingRange(start, end); + }); + } } diff --git a/extensions/markdown-language-features/src/test/foldingProvider.test.ts b/extensions/markdown-language-features/src/test/foldingProvider.test.ts index 6489694db46..fad172dba24 100644 --- a/extensions/markdown-language-features/src/test/foldingProvider.test.ts +++ b/extensions/markdown-language-features/src/test/foldingProvider.test.ts @@ -103,6 +103,25 @@ a`); assert.strictEqual(second.end, 9); }); + test('Should fold from list to end of document', async () => { + const folds = await getFoldsForDocument(`a +- b +c +d`); + assert.strictEqual(folds.length, 1); + const firstFold = folds[0]; + assert.strictEqual(firstFold.start, 1); + assert.strictEqual(firstFold.end, 3); + }); + + test('Should fold if list has multiple lines of content', async () => { + const folds = await getFoldsForDocument(`a +- This list item\n spans multiple\n lines.`); + assert.strictEqual(folds.length, 1); + const firstFold = folds[0]; + assert.strictEqual(firstFold.start, 1); + assert.strictEqual(firstFold.end, 3); + }); });