From ce0f1adc253be183e3c9694a104eff67ed9d88a8 Mon Sep 17 00:00:00 2001 From: Julius Krumbiegel Date: Sat, 20 Dec 2025 00:13:42 +0100 Subject: [PATCH 1/3] allow ::: without preceding empty line to be parsed as closing div --- packages/core/src/markdownit/divs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/markdownit/divs.ts b/packages/core/src/markdownit/divs.ts index 92482856..3eab79c8 100644 --- a/packages/core/src/markdownit/divs.ts +++ b/packages/core/src/markdownit/divs.ts @@ -139,7 +139,7 @@ export const divPlugin = (md: MarkdownIt) => { return false; } }, - { alt: [] } + { alt: ["paragraph"] } ) md.renderer.rules[kTokDivOpen] = renderStartDiv From c7dce81dc481fad097206998616c1e30958b8e1d Mon Sep 17 00:00:00 2001 From: Julia Silge Date: Fri, 2 Jan 2026 15:05:24 -0700 Subject: [PATCH 2/3] Add some tests for code cell detection --- apps/vscode/src/test/codeBlocks.test.ts | 66 ++++++++ .../src/test/examples/div-code-blocks.qmd | 158 ++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 apps/vscode/src/test/codeBlocks.test.ts create mode 100644 apps/vscode/src/test/examples/div-code-blocks.qmd diff --git a/apps/vscode/src/test/codeBlocks.test.ts b/apps/vscode/src/test/codeBlocks.test.ts new file mode 100644 index 00000000..98b1a378 --- /dev/null +++ b/apps/vscode/src/test/codeBlocks.test.ts @@ -0,0 +1,66 @@ +import * as vscode from "vscode"; +import * as assert from "assert"; +import { WORKSPACE_PATH, examplesOutUri, openAndShowTextDocument } from "./test-utils"; +import { isExecutableLanguageBlock, languageNameFromBlock } from "quarto-core"; +import { MarkdownEngine } from "../markdown/engine"; + +suite("Code block detection", function () { + const engine = new MarkdownEngine(); + + suiteSetup(async function () { + await vscode.workspace.fs.delete(examplesOutUri(), { recursive: true }); + await vscode.workspace.fs.copy(vscode.Uri.file(WORKSPACE_PATH), examplesOutUri()); + }); + + // Test for issue #521 / PR #875: + // Code blocks inside divs should be detected even when the closing ::: + // doesn't have a preceding blank line. This real-world example has many + // .notes divs which caused later code blocks to not be detected. + test("Detects code blocks in document with many divs (issue #521)", async function () { + const { doc } = await openAndShowTextDocument("div-code-blocks.qmd"); + + const tokens = engine.parse(doc); + const executableBlocks = tokens.filter(isExecutableLanguageBlock); + + // Count R code blocks and math blocks separately + const rBlocks = executableBlocks.filter(b => languageNameFromBlock(b) === "r"); + const mathBlocks = executableBlocks.filter(b => languageNameFromBlock(b) === "tex"); + + // Should find all 3 R code blocks + assert.strictEqual( + rBlocks.length, + 3, + `Expected 3 R code blocks, found ${rBlocks.length}` + ); + + // Should find all 3 math blocks (displayed as tex) + assert.strictEqual( + mathBlocks.length, + 3, + `Expected 3 math blocks, found ${mathBlocks.length}` + ); + + // Total should be 6 executable blocks (3 R + 3 math) + assert.strictEqual( + executableBlocks.length, + 6, + `Expected 6 executable blocks total, found ${executableBlocks.length}` + ); + }); + + test("Detects code block in simple document", async function () { + const { doc } = await openAndShowTextDocument("hello.qmd"); + + const tokens = engine.parse(doc); + const executableBlocks = tokens.filter(isExecutableLanguageBlock); + + assert.strictEqual( + executableBlocks.length, + 1, + `Expected 1 executable block in hello.qmd, found ${executableBlocks.length}` + ); + + const language = languageNameFromBlock(executableBlocks[0]); + assert.strictEqual(language, "python", `Expected python, got ${language}`); + }); +}); diff --git a/apps/vscode/src/test/examples/div-code-blocks.qmd b/apps/vscode/src/test/examples/div-code-blocks.qmd new file mode 100644 index 00000000..67322164 --- /dev/null +++ b/apps/vscode/src/test/examples/div-code-blocks.qmd @@ -0,0 +1,158 @@ +--- +title: "Div Code Blocks" +format: html +--- + +## Code blocks in divs without blank lines + +This tests the fix for issue #521 where closing `:::` without a preceding +blank line would cause code blocks to not be detected. + +## A slide with code + +```{r} +library(tidyverse) +head(mtcars) +``` + +::: {.notes} +- test notes +::: + +## A slide with math + +$$ +\mathbf{y} = \mathbf{X}^\top\beta + \varepsilon +$$ + +::: {.notes} +- test notes +::: + +## A slide with code + +::: {.notes} +- test notes +::: + +## A slide with math + +::: {.notes} +- test notes +::: + +## A slide with code + +::: {.notes} +- test notes +::: + +## A slide with math + +::: {.notes} +- test notes +::: + +## A slide with code + +::: {.notes} +- test notes +::: + +## A slide with math + +::: {.notes} +- test notes +::: + +## A slide with code + +::: {.notes} +- test notes +::: + +## A slide with math + +::: {.notes} +- test notes +::: + +## A slide with code + +::: {.notes} +- test notes +::: + +## A slide with math + +::: {.notes} +- test notes +::: + +## A slide with code + +::: {.notes} +- test notes +::: + +## A slide with math + +::: {.notes} +- test notes +::: + +## A slide with code + +::: {.notes} +- test notes +::: + +## A slide with math + +::: {.notes} +- test notes +::: + +## A slide with code + +```{r} +head(mtcars) +``` + +::: {.notes} +- test notes +::: + +## A slide with math + +$$ +\mathbf{y} = \mathbf{X}^\top\beta + \varepsilon +$$ + +::: {.notes} +- test notes +::: + +## A slide with code + +Did not previously display properly: + +```{r} +head(mtcars) +``` + +::: {.notes} +- test notes +::: + +## A slide with math + +Did not previously display properly: + +$$ +\mathbf{y} = \mathbf{X}^\top\beta + \varepsilon +$$ + +::: {.notes} +- test notes +::: From 4ce1decbe7c58dd3b8f79a37fae4b2381ae77420 Mon Sep 17 00:00:00 2001 From: Julia Silge Date: Fri, 2 Jan 2026 15:05:34 -0700 Subject: [PATCH 3/3] Update CHANGELOG --- apps/vscode/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/vscode/CHANGELOG.md b/apps/vscode/CHANGELOG.md index 929c21a6..0bf87e38 100644 --- a/apps/vscode/CHANGELOG.md +++ b/apps/vscode/CHANGELOG.md @@ -2,6 +2,8 @@ ## 1.128.0 (Unreleased) +- Fixed a bug where code blocks inside complex div structures (e.g., many `::: {.notes}` divs without preceding blank lines) were not detected as executable cells (). + ## 1.127.0 (Release on 2025-12-17) - By default, headers from markdown files _in R projects_ (projects with a `DESCRIPTION` file such as R package) are no longer exported as workspace symbols. They remain exported as usual in other projects. This behaviour can be controlled manually with the new `quarto.symbols.exportToWorkspace` setting.