ObsidianFlavoredMarkdown Plugin Incompatible with GitHubFlavoredMarkdown - Breaks Image Syntax with @ Characters in Filenames
When using both ObsidianFlavoredMarkdown and GitHubFlavoredMarkdown plugins together (default Quartz configuration), Obsidian image embeds with @ characters in filenames (e.g., @2x for retina images) fail to render. Instead of displaying as <img> tags, they render as broken Obsidian aliases with email-like links.
- Quartz Version: 4.5.2
- Platform: macOS (Darwin 24.6.0)
- Node Version: 22+ (tested with npm 10+)
The GitHubFlavoredMarkdown plugin uses remark-gfm, which includes autolink literal detection via micromark-extension-gfm-autolink-literal. This extension automatically converts email-like patterns (text with @ symbol) to mailto: links.
Processing Order Issue: When both plugins are enabled (in default configuration order):
ObsidianFlavoredMarkdownattempts to parse![[CleanShot 2025-10-19 at 17.35.29@2x.png]]GitHubFlavoredMarkdownruns and the autolink literal parser sees17.35.29@2xand converts it to<a href="./mailto:17.35.29@2x...">- This breaks the wikilink before the Obsidian plugin can fully process it
- Result:
![[CleanShot 2025-10-19 at <a href="./mailto:17.35.29@2x.png">17.35.29@2x.png</a>]]- broken image reference
Any Obsidian image embed where the filename contains the @ symbol:
- Screenshots:
Screenshot@2x.png,image@3x.png(Retina/High-DPI images) - Email-like patterns:
file@v1.0.png,photo@archive.png - Other uses:
data@timestamp.png,backup@2024.png
Markdown Input:
![[CleanShot 2025-10-19 at 17.35.29@2x.png]]Expected Output:
<p><img src="./attachments/CleanShot-2025-10-19-at-17.35.29@2x.png" width="auto" height="auto" alt/></p>Actual Output (with both plugins enabled):
<p>![[CleanShot 2025-10-19 at <a href="./mailto:17.35.29@2x.png" class="internal alias" data-slug="mailto:17.35.29@2x.png">17.35.29@2x.png</a>]]</p>File: quartz/plugins/transformers/ofm.ts and quartz/plugins/transformers/gfm.ts
The wikilink regex in ObsidianFlavoredMarkdown correctly matches:
/!?\[\[([^\[\]\|\#\\]+)?(#+[^\[\]\|\#\\]+)?(\\?\|[^\[\]\#]*)?\]\]/gHowever, GitHubFlavoredMarkdown uses remark-gfm which processes the markdown AST and doesn't respect unparsed wikilinks as atomic units. The autolink literal extension processes inline content before wikilinks are fully resolved.
- Markdown is converted to AST
remark-gfmprocesses the AST and converts email-like patterns in text nodesObsidianFlavoredMarkdownprocesses wikilinks, but the text has already been corrupted
This is a plugin ordering/interaction issue, not a regex issue.
When GitHubFlavoredMarkdown is disabled:
- The autolink literal parser doesn't run
@symbols in filenames are preservedObsidianFlavoredMarkdowncorrectly parses the full wikilink- Images render properly as
<img>tags
- Severity: Medium
- Affected Users: Anyone using Obsidian image embeds with
@in filenames (very common for Retina/High-DPI screenshots) - Workarounds:
- Disable
GitHubFlavoredMarkdownplugin (loses GFM features like autolinks, tables, strikethrough) - Rename images to remove
@(not practical for auto-generated screenshot names) - Use standard markdown image syntax instead of Obsidian wikilinks (breaks Obsidian portability)
- Disable
Modify the GitHubFlavoredMarkdown plugin to disable the autolink literal extension while keeping other GFM features:
// In quartz/plugins/transformers/gfm.ts
export const GitHubFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>> = (userOpts) => {
const opts = { ...defaultOptions, ...userOpts }
return {
name: "GitHubFlavoredMarkdown",
markdownPlugins() {
return opts.enableSmartyPants
? [
[remarkGfm, {
singleTilde: false,
// Disable autolink literal to prevent @ symbol conflicts
autolink: false
}],
smartypants
]
: [[remarkGfm, { singleTilde: false, autolink: false }]]
},
// ... rest of plugin
}
}Tradeoff: Users lose automatic URL and email autolink detection, but this is likely less critical than image embeds.
Change the default plugin order to process ObsidianFlavoredMarkdown before GitHubFlavoredMarkdown:
// In quartz.config.ts
transformers: [
Plugin.FrontMatter(),
Plugin.CreatedModifiedDate({...}),
Plugin.SyntaxHighlighting({...}),
Plugin.ObsidianFlavoredMarkdown({ enableInHtmlEmbed: false }), // Process first
Plugin.GitHubFlavoredMarkdown(), // Then GFM
// ...
]Limitation: This may not fully work because both plugins modify the markdown AST, and the ordering at the remark plugin level matters more than plugin definition order.
Document that users should escape @ symbols in Obsidian wikilinks:
![[CleanShot 2025-10-19 at 17.35.29\@2x.png]]Limitation: Not practical; users don't control auto-generated screenshot filenames in Obsidian.
Add a configuration option to disable autolink literals:
export interface Options {
enableSmartyPants: boolean
linkHeadings: boolean
enableAutolinkLiterals: boolean // New option, default true
}Benefit: Gives users flexibility without breaking existing behavior.
Implement Option 1 or Option 4 to disable autolink literal parsing by default or add a configuration option.
The autolink literal feature (auto-detecting URLs and emails) is a nice-to-have enhancement, while breaking Obsidian image embeds is a critical regression for users publishing Obsidian vaults.
- Create a Quartz site with default configuration (including both plugins)
- Copy an Obsidian vault with images into the content folder
- Include an image embed with
@in the filename:![[Screenshot@2x.png]]
- Run
npx quartz build - Check the generated HTML - image will render as broken alias, not as
<img>tag
quartz/plugins/transformers/ofm.ts- ObsidianFlavoredMarkdown pluginquartz/plugins/transformers/gfm.ts- GitHubFlavoredMarkdown pluginquartz/config.ts- Default plugin configurationnode_modules/remark-gfm/- Dependency with autolink literal extension
Obsidian's auto-generated screenshot filenames commonly include @2x, @3x suffixes for Retina display support. The default Quartz template and documentation encourage using symlinks or copying Obsidian vaults directly into Quartz, making this a common real-world scenario.
This issue can be tested by:
- Running Quartz with both plugins enabled (default)
- Adding an image with
@in filename - Verifying the output is broken (not an
<img>tag)
Then testing the fix:
- Disabling autolink literals in remark-gfm
- Running the same test
- Verifying the output is correct
This is a plugin interaction bug that should be addressed to ensure Obsidian vault publishing works reliably with the default configuration. The fix is straightforward and has minimal impact on other features.
Report submitted by: Aníbal Rojas Date: October 20, 2025 Reproduction environment: macOS, Quartz 4.5.2, Obsidian vault publishing workflow