Change:
[X] Notebooks (.ipynb files) [ ] Interactive Window and/or Cell Scripts (.py files with #%% markers) I expected that folding cells per a markdown header level would collapse all of the markdown and code cells under that header, per the VS Code Outline view of the notebook. In practice though, if there is a markdown cell with a python code block, then the comments in that python code block are considered the next top-level markdown section which interrupts the code folding. a new file and set the interpreter markdown cell with content: markdown cell: code cell: markdown cell: python print('hello world') the cell that cells 2 and 3 are collapsed and hidden, but cell 4 is not Add additional 's to the embedded python comment so that its not at the same level of the makrdown section it is under; e.g., python print('hello world') 70.0 v2022.7. Python 3.8.13 v2022.12.0 conda 4.13.0 Local
still seeing this issue- lmk if my setup is wrong. thanks! <img width="1322" alt="Screenshot 2023-01-25 at 1 11 16 PM" src="https://user-"<img width="1314" alt="Screenshot 2023-01-25 at 1 11 11 PM" src="https://user-"
Can you try finishing editing the cells to put them into render mode: ! I don't think we update the folding until the cell is no longer being edited
was verifying another issue and this works now!

Discussion:
import { IdleValue } from 'vs/base/common/async'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; <del> import { marked } from 'vs/base/common/marked/marked'; </del> import { renderMarkdownAsPlaintext } from 'vs/base/browser/markdownRenderer'; import { INotebookExecutionStateService } from 'vs/workbench/contrib/notebook/common/notebookExecutionStateService'; import { executingStateIcon } from 'vs/workbench/contrib/notebook/browser/notebookIcons'; import { URI } from 'vs/base/common/uri'; <ins> import { getMarkdownHeadersInCell } from 'vs/workbench/contrib/notebook/browser/viewModel/foldingModel'; </ins> export interface IOutlineMarkerInfo { readonly count: number;

if (isMarkdown) { const fullContent = cell.getText().substring(0, 10_000); <del> for (const token of marked.lexer(fullContent, { gfm: true })) { if (token.type === 'heading') { hasHeader = true; entries.push(new OutlineEntry(entries.length, token.depth, cell, renderMarkdownAsPlaintext({ value: token.text }).trim(), false, false)); } </del> <ins> for (const { depth, text } of getMarkdownHeadersInCell(fullContent)) { hasHeader = true; entries.push(new OutlineEntry(entries.length, depth, cell, text, false, false)); </ins> } if (!hasHeader) { // no markdown syntax headers, try to find html tags const match = fullContent.match(/<h([1-6]).*>(.*)</h1>/i);

*  Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ <ins> import { renderMarkdownAsPlaintext } from 'vs/base/browser/markdownRenderer'; </ins> import { Emitter, Event } from 'vs/base/common/event'; import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; <ins> import { marked } from 'vs/base/common/marked/marked'; </ins> import { TrackedRangeStickiness } from 'vs/editor/common/model'; import { FoldingLimitReporter } from 'vs/editor/contrib/folding/browser/folding'; import { FoldingRegion, FoldingRegions } from 'vs/editor/contrib/folding/browser/foldingRanges';

for (let i = 0; i < cells.length; i++) { const cell = cells[i]; <del> if (cell.cellKind === CellKind.Code) { </del> <ins> if (cell.cellKind !== CellKind.Markup || cell.language !== 'markdown') { </ins> continue; } <del> const content = cell.getText(); const matches = content.match(/^[ t]*(#+) /gm); let min = 7; if (matches && matches.length) { for (let j = 0; j < matches.length; j++) { min = Math.min(min, matches[j].length); } } if (min < 7) { </del> <ins> const minDepth = Math.min(7, ...Array.from(getMarkdownHeadersInCell(cell.getText()), header => header.depth)); if (minDepth < 7) { </ins> // header 1 to 6 <del> stack.push({ index: i, level: min, endIndex: 0 }); </del> <ins> stack.push({ index: i, level: minDepth, endIndex: 0 }); </ins> } } <del> // calcualte folding ranges </del> <ins> // calculate folding ranges </ins> const rawFoldingRanges: IFoldingRangeData[] = stack.map((entry, startIndex) => { let end: number | undefined = undefined; for (let i = startIndex + 1; i < stack.length; ++i) {

const range = foldingModel.regions.findRange(index + 1); foldingModel.setCollapsed(range, collapsed); } <ins> export function* getMarkdownHeadersInCell(cellContent: string): Iterable<{ readonly depth: number; readonly text: string }> { for (const token of marked.lexer(cellContent, { gfm: true })) { if (token.type === 'heading') { yield { depth: token.depth, text: renderMarkdownAsPlaintext({ value: token.text }).trim() }; } } } </ins>