Astro Info
Astro v7.1.6
Vite v8.1.5
Node v24.18.1
System Windows (x64)
Package Manager npm
Output static
Adapter none
Integrations @astrojs/mdx (v7.0.5)
If this issue only occurs in one browser, which browser is a problem?
Happens in FireFox and Chrome, didn't test others
Describe the Bug
Describe the bug
When rendering an MDX content collection entry using render() from astro:content, enabling markdown.smartypants causes typographic punctuation to be corrupted into mojibake on Windows.
For example:
Don’t becomes Don’
“Hello” becomes “Helloâ€�
This only occurs when rendering an entry from a content collection using render(). A direct .mdx page renders correctly.
Environment
- Astro: 7.1.6
- @astrojs/mdx: 7.0.5
- @mdx-js/mdx: 3.1.1
- Node.js: 24.18.1 (LTS)
- npm
- Windows 11
What I tested
I spent quite some time isolating the issue.
✅ Source file encoding
The .mdx file is saved as UTF-8.
I verified this by:
- Saving the file explicitly as UTF-8.
- Confirming the encoding in Notepad++.
- Inspecting the file with
Format-Hex.
The UTF-8 bytes are correct:
- ASCII apostrophe (
') → 27
- Right single quotation mark (
’) → E2 80 99
The source file itself is not corrupted.
✅ Content collection
getCollection() returns the correct content.
For example:
console.log(lesson.body);
prints:
which proves the content is read correctly before rendering.
✅ Direct MDX pages
A page such as:
renders perfectly:
No corruption occurs.
❌ Rendering through astro:content
Rendering the same content using:
const { Content } = await render(lesson);
produces HTML containing:
Don’t
“I don’t like it�
Viewing the generated HTML source confirms the mojibake is already present before the browser renders the page.
✅ Disabling Smartypants fixes the problem
Changing:
markdown: {
smartypants: false,
}
immediately fixes the issue.
The same content then renders correctly:
Summary
The issue appears to occur only when all of the following are true:
- Rendering an MDX content collection entry using
render() from astro:content
markdown.smartypants is enabled
- Running on Windows
Direct .mdx pages do not exhibit this behavior, and the content returned by getCollection() is already correct before rendering.
This suggests the corruption occurs somewhere during the rendering pipeline rather than while reading the source file.
What's the expected result?
When rendering an MDX content collection entry using render() from astro:content, enabling markdown.smartypants should produce valid typographic punctuation without corrupting the output.
For example, the following Markdown:
Don't
Don’t
"I don't like it"
"I don’t like it"
should render as:
Don't
Don’t
“I don't like it”
“I don’t like it”
or, if Smartypants is expected to convert straight quotes:
Don’t
Don’t
“I don’t like it”
“I don’t like it”
In either case, the rendered HTML should contain valid Unicode punctuation (’, “, ”) and should never contain mojibake such as ’, “, or â€�.
Link to Minimal Reproducible Example
I will create that later - right now not in a position to do
Participation
Astro Info
If this issue only occurs in one browser, which browser is a problem?
Happens in FireFox and Chrome, didn't test others
Describe the Bug
Describe the bug
When rendering an MDX content collection entry using
render()fromastro:content, enablingmarkdown.smartypantscauses typographic punctuation to be corrupted into mojibake on Windows.For example:
Don’tbecomesDon’“Hello”becomes“Helloâ€�This only occurs when rendering an entry from a content collection using
render(). A direct.mdxpage renders correctly.Environment
What I tested
I spent quite some time isolating the issue.
✅ Source file encoding
The
.mdxfile is saved as UTF-8.I verified this by:
Format-Hex.The UTF-8 bytes are correct:
') →27’) →E2 80 99The source file itself is not corrupted.
✅ Content collection
getCollection()returns the correct content.For example:
prints:
which proves the content is read correctly before rendering.
✅ Direct MDX pages
A page such as:
renders perfectly:
No corruption occurs.
❌ Rendering through astro:content
Rendering the same content using:
produces HTML containing:
Viewing the generated HTML source confirms the mojibake is already present before the browser renders the page.
✅ Disabling Smartypants fixes the problem
Changing:
immediately fixes the issue.
The same content then renders correctly:
Summary
The issue appears to occur only when all of the following are true:
render()fromastro:contentmarkdown.smartypantsis enabledDirect
.mdxpages do not exhibit this behavior, and the content returned bygetCollection()is already correct before rendering.This suggests the corruption occurs somewhere during the rendering pipeline rather than while reading the source file.
What's the expected result?
When rendering an MDX content collection entry using
render()fromastro:content, enablingmarkdown.smartypantsshould produce valid typographic punctuation without corrupting the output.For example, the following Markdown:
should render as:
or, if Smartypants is expected to convert straight quotes:
In either case, the rendered HTML should contain valid Unicode punctuation (
’,“,”) and should never contain mojibake such as’,“, orâ€�.Link to Minimal Reproducible Example
I will create that later - right now not in a position to do
Participation