Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 (<https://github.com/quarto-dev/quarto/pull/875>).

## 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.
Expand Down
66 changes: 66 additions & 0 deletions apps/vscode/src/test/codeBlocks.test.ts
Original file line number Diff line number Diff line change
@@ -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}`);
});
});
158 changes: 158 additions & 0 deletions apps/vscode/src/test/examples/div-code-blocks.qmd
Original file line number Diff line number Diff line change
@@ -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
:::
2 changes: 1 addition & 1 deletion packages/core/src/markdownit/divs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export const divPlugin = (md: MarkdownIt) => {
return false;
}
},
{ alt: [] }
{ alt: ["paragraph"] }
)

md.renderer.rules[kTokDivOpen] = renderStartDiv
Expand Down