Post

VS Code Markdown PDF Extension: Tips and Gotchas

Practical tips for using the Markdown PDF extension in VS Code, including common pitfalls with Mermaid diagrams.

VS Code Markdown PDF Extension: Tips and Gotchas

Introduction

I spent 2 hours debugging a Mermaid diagram that worked perfectly in VS Code’s preview but crashed during PDF export. The error message was just “Syntax error in text” with no line number. After multiple trial-and-error sessions, I compiled this list of gotchas that I wish I knew earlier.

Most of this is an empirical observation from my VS Code Markdown-PDF (Chromium/Puppeteer) export pipeline, not documented Mermaid behavior: the renderer parses <...> as HTML, so a label like <meta> is read as an HTML tag and breaks the export. The only flowchart pitfalls Mermaid’s docs warn about directly are the lowercase end keyword and edges starting with o/x.


The Three Common Traps

Before diving into details, here are the most common causes of PDF export failures:

TrapProblemSolution
Parser-Breaking TokensAND, OR can break edge labelsUse _AND_, _OR_
Angle Brackets<row> looks like HTMLEscape as &lt;row&gt;, quote, or drop the brackets (quick hack: add non-English, e.g. <해당row>)
Real HTML Tags<meta>, <div> consistently failed in my export pipelineEscape as &lt;meta&gt;, quote, or rename (quick hack: <메타>, <구역>)

Trap #1: Tokens That Can Break the Parser in Edge Labels

Some uppercase tokens like AND and OR can confuse the Mermaid parser when they appear in edge labels, leading to “Syntax error in text”. To be precise: Mermaid only officially reserves the lowercase keyword end. The behavior below is best treated as a practical, defensive workaround rather than a documented list of reserved operators.

flowchart LR
    subgraph "Error"
        A1[A] -->|"AND"| B1[B]
    end
    subgraph "Works"
        A2[A] -->|"_AND_"| B2[B]
    end

Tokens to Watch For

TokenStatusAlternative
ANDError_AND_
ORError_OR_
NOTUsually OK_NOT_ (safer)
INUsually OK_IN_ (safer)

The most portable fix is to rephrase the whole edge label so the operator words never appear at all (e.g. q: cond1 + cond2 or q: all conditions).


Trap #2: Angle Brackets = HTML?

The PDF exporter uses Puppeteer (headless Chrome). Content in angle brackets can be interpreted as HTML tags.

Which Brackets Fail?

ContentResultWhy
<row>ErrorLooks like HTML tag
<unchanged>ErrorLooks like HTML tag
<1개>WorksNumber makes it invalid HTML
<해당row>WorksKorean makes it invalid HTML

Fix: Escape, Quote, or Remove the Brackets

The robust fix is to stop the brackets from looking like HTML: escape them as HTML entities (&lt;/&gt;), wrap the text in quotes, or just drop the angle brackets entirely.

1
2
3
4
5
Before (Error):
A -.->|"200(rows=<row>)"| T

After (Works, escaped):
A -.->|"200(rows=&lt;row&gt;)"| T

As a secondary quick hack, adding a non-English character also makes the content invalid as HTML so the parser leaves it alone:

1
A -.->|"200(rows=<해당row>)"| T

Trap #3: Real HTML Tag Names

If your placeholder happens to be a real HTML tag name, it consistently failed in my VS Code Markdown PDF (Puppeteer) export pipeline. The reliable fix is the same as Trap #2: escape the brackets as &lt;/&gt;, quote the text, or drop the brackets and rename the placeholder. Adding a non-English token (the Korean form below) is a secondary quick hack.

TagProblemAlternative
<meta>Real HTML tag&lt;meta&gt;, META (quick hack: <메타>)
<div>Real HTML tag&lt;div&gt;, DIV (quick hack: <구역>)
<span>Real HTML tag&lt;span&gt;, SPAN (quick hack: <범위>)
<br>Real HTML tagRemove or use /

Quick Fix Checklist

Before exporting to PDF, search for these patterns:

flowchart TD
    Q1{Export Failed?}
    Q1 -->|Yes| C1["Search: AND, OR"]
    C1 --> F1["Replace with _AND_, _OR_"]
    
    F1 --> C2["Search: &lt;English-only&gt;"]
    C2 --> F2["Escape/quote/remove (quick hack: add Korean &lt;한글&gt;)"]
    
    F2 --> C3["Search: &lt;meta&gt;, &lt;div&gt;, &lt;span&gt;"]
    C3 --> F3["Escape/rename (quick hack: &lt;메타&gt;, &lt;구역&gt;)"]
    
    F3 --> Q2{Still Failing?}
    Q2 -->|Yes| A1["Export incrementally to find the problematic section"]
    Q2 -->|No| A2["Success!"]

Configuration Tips

Fix Korean Text Rendering

If Korean appears as boxes:

1
2
3
4
5
{
  "markdown-pdf.styles": [
    "https://fonts.googleapis.com/css2?family=Noto+Sans+KR&display=swap"
  ]
}

Page Layout Settings

1
2
3
4
5
6
7
{
  "markdown-pdf.format": "A4",
  "markdown-pdf.margin.top": "20mm",
  "markdown-pdf.margin.bottom": "20mm",
  "markdown-pdf.margin.left": "15mm",
  "markdown-pdf.margin.right": "15mm"
}

Workflow: Avoiding Export Pain

flowchart LR
    W[Write section] --> P[Preview in VS Code]
    P --> E[Export to PDF]
    E --> Q{Success?}
    Q -->|Yes| W
    Q -->|No| D[Debug with checklist]
    D --> W

Key: Export after every few sections, not at the end. Finding the problematic line in a 200-line document is painful.


Summary

ProblemQuick Fix
AND/OR errors_AND_/_OR_
<english> failsEscape &lt;english&gt;, quote, or remove (quick hack: <한글>)
<meta> failsEscape &lt;meta&gt; or rename META (quick hack: <메타>)
Korean is brokenAdd Noto Sans KR font
Export is slowSplit into smaller files

The extension is powerful once you know the workarounds. Most issues come from Mermaid diagrams - fix those first!

This post is licensed under CC BY 4.0 by the author.