Description
Quarto renders Python percent scripts and the docs name jupytext as the reference implementation of the format, with markdown cells written either as # comments or as a multi-line string (""").
Jupytext writes markdown cells as strings when cell_markers = '"""' is set, and since 1.13.0 it prefixes the string with r whenever the cell contains a backslash, so that LaTeX such as \frac is not read as a Python escape sequence (changelog entry for jupytext/jupytext#836; src/jupytext/cell_to_text.py, "Markdown cells that contain a backslash should be encoded as raw strings"; expected output in tests/functional/others/test_raw_strings.py). Its reader accepts """, r""", R""" and the ''' forms (src/jupytext/cell_reader.py).
Quarto's parser recognises only a bare """ line:
// src/core/jupyter/percent.ts, markdownFromJupyterPercentScript
const isTripleQuote = (line: string) => !!line.match(/^"{3,}\s*$/);
so a cell jupytext wrote falls into the comment branch, which only strips a leading #, and both delimiter lines are rendered as prose. The same applies to a cell a user writes as r""" by hand to keep Python from interpreting the backslashes (a plain """ cell containing \xi or \underline is a syntax error in Python, so the raw prefix is the only way to keep such a file importable or runnable).
Minimal example
doc.py:
# %% [markdown]
# ---
# title: "Raw-string markdown cell"
# ---
# %% [markdown]
r"""
# A heading
Display math: $\frac{a}{b}$
"""
quarto render doc.py (1.8.25; the parser is unchanged in 1.10.18, 1.11.3 and main) produces a document whose body, as plain text, reads
r”“” A heading
Display math: \(\frac{a}{b}\) ““”
The heading is lost (the # was stripped as a comment prefix) and both delimiters appear as text, smart-quoted by Pandoc. Replacing r""" by """ renders correctly, which confirms the cause.
Proposed change
Accept an optional r/R prefix on the opening delimiter, and the single-quote form, matching jupytext's reader:
const isTripleQuoteOpen = (line: string) => !!line.match(/^[rR]?("{3,}|'{3,})\s*$/);
const isTripleQuoteClose = (line: string) => !!line.match(/^("{3,}|'{3,})\s*$/);
No other part of the pipeline is affected: the cell content is taken as markdown source either way.
Quarto version
1.8.25 on Windows 11; the relevant code is identical at tags v1.10.18 and v1.11.3 and on main.
Description
Quarto renders Python percent scripts and the docs name jupytext as the reference implementation of the format, with markdown cells written either as
#comments or as a multi-line string (""").Jupytext writes markdown cells as strings when
cell_markers = '"""'is set, and since 1.13.0 it prefixes the string withrwhenever the cell contains a backslash, so that LaTeX such as\fracis not read as a Python escape sequence (changelog entry for jupytext/jupytext#836;src/jupytext/cell_to_text.py, "Markdown cells that contain a backslash should be encoded as raw strings"; expected output intests/functional/others/test_raw_strings.py). Its reader accepts""",r""",R"""and the'''forms (src/jupytext/cell_reader.py).Quarto's parser recognises only a bare
"""line:so a cell jupytext wrote falls into the comment branch, which only strips a leading
#, and both delimiter lines are rendered as prose. The same applies to a cell a user writes asr"""by hand to keep Python from interpreting the backslashes (a plain"""cell containing\xior\underlineis a syntax error in Python, so the raw prefix is the only way to keep such a file importable or runnable).Minimal example
doc.py:quarto render doc.py(1.8.25; the parser is unchanged in 1.10.18, 1.11.3 and main) produces a document whose body, as plain text, readsThe heading is lost (the
#was stripped as a comment prefix) and both delimiters appear as text, smart-quoted by Pandoc. Replacingr"""by"""renders correctly, which confirms the cause.Proposed change
Accept an optional
r/Rprefix on the opening delimiter, and the single-quote form, matching jupytext's reader:No other part of the pipeline is affected: the cell content is taken as markdown source either way.
Quarto version
1.8.25 on Windows 11; the relevant code is identical at tags v1.10.18 and v1.11.3 and on main.