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
3 changes: 2 additions & 1 deletion news/changelog-1.9.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,4 +222,5 @@ All changes included in 1.9:
- ([#13998](https://github.com/quarto-dev/quarto-cli/issues/13998)): Fix YAML validation error with CR-only line terminators (old Mac format). Documents using `\r` line endings no longer fail with "Expected YAML front matter to contain at least 2 lines".
- ([#14012](https://github.com/quarto-dev/quarto-cli/issues/14012)): Add `fr-CA` language translation for Quebec French inclusive writing conventions, using parenthetical forms instead of middle dots for author labels. (author: @tdhock)
- ([#14032](https://github.com/quarto-dev/quarto-cli/issues/14032)): Add `editor_options` with `chunk_output_type` to YAML schema for autocompletion and validation in RStudio and Positron.
- ([#14156](https://github.com/quarto-dev/quarto-cli/issues/14156)): Avoid O(n^2) performance in handling large code blocks.
- ([#14156](https://github.com/quarto-dev/quarto-cli/issues/14156)): Avoid O(n^2) performance in handling large code blocks.
- ([#14177](https://github.com/quarto-dev/quarto-cli/issues/14177)): Escape fenced code correctly when backticks occur at the beginning of a line.
13 changes: 9 additions & 4 deletions src/resources/filters/quarto-pre/engine-escape.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@ function engine_escape()
-- Line-by-line replacement for the pattern (\n?[^`\n]+`+){({+([^<}]+)}+)}
-- which suffers from O(n^2) backtracking on long lines without backticks.
-- See https://github.com/quarto-dev/quarto-cli/issues/14156
-- Start-of-line fix for https://github.com/quarto-dev/quarto-cli/issues/14177
--
-- The original pattern cannot cross newlines (due to [^`\n]+), so processing
-- per-line is semantically equivalent and avoids catastrophic backtracking.
local line_pattern = "([^`\n]+`+)" .. patterns.engine_escape
-- Two patterns for inline engine escape replacement:
-- 1. Start-of-line: match 1-2 backticks only (inline code, not code fences)
-- 2. Mid-line: match any backticks preceded by non-backtick text
-- This avoids over-processing code fence patterns (```{{engine}}) produced by step 2.
local sol_pattern = "^(``?)" .. patterns.engine_escape
local mid_pattern = "([^`\n]+`+)" .. patterns.engine_escape
local function unescape_inline_engine_codes(text)
if not text:find("{{", 1, true) then
return text
Expand All @@ -29,7 +33,8 @@ function engine_escape()
pos = len + 1
end
if line:find("`", 1, true) and line:find("{{", 1, true) then
line = line:gsub(line_pattern, "%1%2")
line = line:gsub(sol_pattern, "%1%2")
line = line:gsub(mid_pattern, "%1%2")
end
result[#result + 1] = line
end
Expand Down
20 changes: 20 additions & 0 deletions tests/docs/smoke-all/2026/03/09/issue-14177.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: "Issue with fenced inline code at beginning of line"
_quarto:
tests:
html:
ensureFileRegexMatches:
- []
- ["\\{\\{"]
---

For teaching materials explaining how to use insert inline code, I would like to display source code demonstrating how to use inline code in the rendered version of a Quarto document. Here's an example below:

``` markdown
## Inline code demo

`{{r}} nrow(penguins)` penguins are included in the amazing `penguins` dataset.
On average these penguins weigh `{{r}} mean(penguins$body_mass, na.rm = TRUE)` grams, although the lightest weighs `{{r}} min(penguins$body_mass, na.rm = TRUE)` g and the heaviest `{{r}} max(penguins$body_mass, na.rm = TRUE)` g.
```

When the paragraph above is rendered, the inline code snippets are all correctly rendered as fenced code except the first one that retains its double curly brackets (see screenshot).
Loading