Summary
Markdown for Agents (MfA) does not preserve code blocks. <pre> elements in the source HTML are converted to plain paragraphs in the Markdown output — no fences, no indentation, no language hint. Their inner content is then processed as ordinary inline Markdown.
This is a content-fidelity bug rather than a formatting nit, because Markdown assigns meaning to characters that are inert inside a code block. A # at the start of a line becomes a heading; * and _ become emphasis. So a Python or shell comment inside a sample is silently promoted to a document heading, and a consumer has no way to tell where code starts or stops.
Reproduces on every Read the Docs-hosted project I've checked, across two different documentation generators (Sphinx and MkDocs Material), so it doesn't look theme-specific.
Reproduction 1 — Sphinx (docs.ray.io)
URL="https://docs.ray.io/en/master/ray-core/fault-tolerance.html"
# Source HTML: 5 <pre> blocks
curl -s "$URL" | grep -o '<pre' | wc -l
# 5
# Markdown output: 0 code fences
curl -s -H "Accept: text/markdown" "$URL" | grep -c '^```'
# 0
The page has five Python samples. All five arrive as bare paragraphs at indent 0. The consequence:
curl -s -H "Accept: text/markdown" "$URL" | grep -n '^# '
24:# Fault tolerance[#](#fault-tolerance "Link to this heading") <- the real H1
54:# Manually retry the actor task.
70:# Non-fault tolerant version:
78:# Object x outlives its owner task A.
90:# Fault tolerant version:
97:# The owner of x is the driver
98:# so x is accessible and can be auto recovered
99:# during the entire lifetime of the driver.
110:# If the node with ip 127.0.0.3 fails while task b is running,
111:# Ray cannot retry the task on other nodes.
116:# Prefer running on the particular node specified by node id
117:# but can also run on other nodes if the target node fails.
Eleven Python comments are now H1 headings, structurally indistinguishable from the page's actual title. An excerpt of the output, showing code and prose at the same level:
First, if the fault tolerance mechanisms provided by Ray don't work for you, you can
always catch [exceptions](...) caused by failures and recover manually.
@ray.remote
class Actor:
def read_only(self):
...
actor = Actor.remote()
# Manually retry the actor task.
while True:
try:
print(ray.get(actor.read_only.remote()))
Nothing marks the boundary between the sentence and the class definition.
Reproduction 2 — MkDocs Material (vizro.readthedocs.io)
URL="https://vizro.readthedocs.io/en/stable/pages/user-guides/dashboard/"
curl -s "$URL" | grep -o '<pre' | wc -l # 7
curl -s -H "Accept: text/markdown" "$URL" | grep -c '^```' # 0
Here the same missing-fence problem also exposes the theme's per-line anchors, because they're no longer inside a code context:
[](#%5F%5Fcodelineno-0-1)import vizro.plotly.express as px
[](#%5F%5Fcodelineno-0-2)from vizro import Vizro
[](#%5F%5Fcodelineno-0-3)import vizro.models as vm
[](#%5F%5Fcodelineno-0-5)df = px.data.iris()
Every line of the sample is prefixed with an empty Markdown link, so the code can't be copied or executed without post-processing.
Expected
<pre> (and <pre><code>) should emit a fenced code block, with the language taken from the usual class hints where available (class="language-python", class="highlight-python", Pygments' class="highlight" wrappers):
```python
@ray.remote
class Actor:
def read_only(self):
...
```
Inside the fence, content should be emitted verbatim — no inline-Markdown processing, no link extraction, no escaping.
Impact
Related
Filing here rather than only through Read the Docs' support channel, since #14488 was resolved quickly once it was reported publicly.
Summary
Markdown for Agents (MfA) does not preserve code blocks.
<pre>elements in the source HTML are converted to plain paragraphs in the Markdown output — no fences, no indentation, no language hint. Their inner content is then processed as ordinary inline Markdown.This is a content-fidelity bug rather than a formatting nit, because Markdown assigns meaning to characters that are inert inside a code block. A
#at the start of a line becomes a heading;*and_become emphasis. So a Python or shell comment inside a sample is silently promoted to a document heading, and a consumer has no way to tell where code starts or stops.Reproduces on every Read the Docs-hosted project I've checked, across two different documentation generators (Sphinx and MkDocs Material), so it doesn't look theme-specific.
Reproduction 1 — Sphinx (docs.ray.io)
The page has five Python samples. All five arrive as bare paragraphs at indent 0. The consequence:
Eleven Python comments are now H1 headings, structurally indistinguishable from the page's actual title. An excerpt of the output, showing code and prose at the same level:
Nothing marks the boundary between the sentence and the class definition.
Reproduction 2 — MkDocs Material (vizro.readthedocs.io)
Here the same missing-fence problem also exposes the theme's per-line anchors, because they're no longer inside a code context:
Every line of the sample is prefixed with an empty Markdown link, so the code can't be copied or executed without post-processing.
Expected
<pre>(and<pre><code>) should emit a fenced code block, with the language taken from the usual class hints where available (class="language-python",class="highlight-python", Pygments'class="highlight"wrappers):Inside the fence, content should be emitted verbatim — no inline-Markdown processing, no link extraction, no escaping.
Impact
/crawlAPI (Browser Rendering /crawl API: Markdown converter incorrectly resolves root-relative image URLs #13406), so a fix would likely benefit both surfaces.Related
/crawl: root-relative image URLs resolved incorrectly.hostnameoption requires URL cloudflare-docs#31303 —hostnameoption requires a URL.Filing here rather than only through Read the Docs' support channel, since #14488 was resolved quickly once it was reported publicly.