Converting markdown to pdf with pandoc and typst
目录
Do you use markdown to write documents, but don’t want to use the cumbersome latex to convert to pdf? Then you can try pandoc and typst. This is a document template program that can convert markdown to beautiful pdf files. It also supports emphasis (italic bold), unordered lists, ordered lists, task lists, emoticons, links, pictures, footnotes, definition lists, mathematical formulas, code highlight fenced code blocks, tables, table width and column width, quote|blocktext, alerts, horizontal lines, titles and other formats. Want to see the document effect? Please take a look User Guide dark or User Guide light , which is also generated by this document template program and supports multiple code highlight color themes.
Why this template? #
About ten years ago, I liked to use markdown to write documents, just because Microsoft Office or WPS was too cumbersome. Later, he gradually found that it was a bit of an overkill to use Office Word or WPS for small-scale documents such as daily technical documents and group work plans. The commonly used formats are nothing more than titles, lists, tables, and text paragraphs. There is no need to use an old computer to run a huge document editor program. Youwu has a certain programming foundation and knows that separating text content from format can be more conducive to focusing on writing.
However, after writing content in markdown, when distributing it, I have always encountered such difficulties. Using pandoc to convert to pdf requires installing a huge latex engine. Using pandoc to convert markdown files to docx, then opening them in WPS or Microsoft Office and exporting them to pdf is cumbersome and does not meet the requirements of the simplicity of document writing workflow.
Until 2024, I found that typst, which has been open source for some time, is very much my habit. It converts the markdown file of the document content into pdf. I only need to install typst of dozens of MB, and it only takes seconds to produce very high-quality pdf documents or png images. I am very grateful for the contribution of the tyspt team.
Youwu simplified the original workflow of markdown to docx to pdf
based on
pandoc
to markdown to pdf or png
with the support of pandoc and
typst
. Of course, it took more than two months to learn the programming syntax of typst and compile the document template program.
The original intention of the design of the document template is to meet the document writing requirements of my daily work. It is very self-righteous. The main types of these documents are:
- Technical solution description
- Work plan
- Summary
- Log
Book publishing and academic papers are not considered for the time being.
Where to get this document template program, see [How to get this template]
Styles supported in the template #
The styles formats supported in the document are:
- Emphasis (italic or bold)
- Unordered list
- Ordered list
- Task list
- Emoji
- Links
- Picture
- Footnote
- Definition list
- Math Equations
- Code highlight fenced code block
- Table
- Table width and column width
- Quote quote|blocktext
- alerts
- Horizontal rule
- Title
Color settings in the template #
The document has two versions: dark and light. The document page is divided into two sizes: A4 and 300/650 aspect ratio for mobile reading.
Code highlight color themes are:
-
ayu
:
- ayu-mirage
- ayu-dark
- ayu-light
-
Catppuccin
- Catppuccin Frappe
- Catppuccin Latte
- Catppuccin Macchiato
- Catppuccin Mocha
This template program already contains all the combinations of the above situations.
Demonstrations #
You can directly download userguide.dark.ayu-dark.pdf to see the look and feel.
Emphasis #
The markdown content is as follows:
Emphasis, also known as italics, uses an *asterisk* or _underline_.
Emphasis, also known as bold, uses an **asterisk** or __underline__.
Use a combination of **asterisk and _underline_** for emphasis.
Strikethrough uses two tildes. ~~Strike this out.~~
**This is bold text**
__This is bold text__
*This is italic text*
_This is italic text_
~~Strikethrough~~
Renders to:
Unordered list #
The markdown content is as follows:
* Unordered lists can be made with an asterisk (`*`)
- or a minus sign (`-`)
+ or a plus sign (`+`)
+ Create a list by starting a line with `+`, `-`, or `*`
+ Create a sublist by indenting 2 spaces:
- A change in the marker character forces the start of a new list:
* Ac tristique libero volutpat at
+ Facilisis in pretium nisl aliquet
- Nulla volutpat aliquam velit
+ Very simple!
+ Unordered lists can also be
+ mixed with numbered lists
1. Indent and create a numbered list item
2. Another numbered item
+ Another unordered list item
Renders to:
Ordered list #
The markdown content is as follows:
1. First ordered list item
2. Another item
* Unordered list
1. The actual number doesn't matter, as long as it's a number
1. The numbers will reorder
4. Another item.
You can also properly indent paragraphs in list items.
5. Extra blank lines
In addition to properly indenting paragraphs, adding an extra blank line before a paragraph also forms a new indented paragraph with an indented first line.
In addition to properly indenting paragraphs, adding an extra blank line before a paragraph also forms a new indented paragraph with an indented first line.
7. One more item
1. Make changes
1. Fix bugs
2. Improve formatting
- Make headings bigger
2. Push my commit to GitHub
3. Open a pull request
* Describe my changes
* Mention all members of my team
* Ask for feedback
Renders to:
Task list #
The markdown content is as follows:
- [x] Finish my changes
- [ ] Push my commits to GitHub
- [ ] Open a pull request
- [x] Support \@mentions, #refs, [links](), **formatting**, and <del>tags</del>
- [x] Require list syntax (supports any unordered or ordered list)
- [ ] This is a complete project
- [ ] This is an incomplete project
- ✅ This line is not a task list item, but it is also a list item
Rendered as:
emoji #
markdown The content is as follows:
*emoji marks*: 😄 😡 😓 👇
*emoji symbols*: 😀😃😄😁🐶🐱🐭🐹
🍏🍐🍉🍇🍓
⚽️🏐🏈🏀
🚗🚕🚙🚌
⌚️📱📲💻⌨️
🩷❤️🧡💛🉐㊙️㊗️🈴🉑☢️☣️
🏳️🏴🏴☠️🏁
⚠️🌟🔥👍✅
Renders to:
Links #
The content of markdown is as follows:
[I am an inline-style link](https://www.google.com)
[I am an inline-style link with a title](https://www.google.com "Google's Homepage")
[I am a reference-style link][Any case-insensitive reference text]
[I am a relative reference to a repository file](../blob/master/LICENSE)
[You can use a number for a reference-style link definition][1]
Or leave it blank and use [the link text itself].
URLs and URLs in angle brackets are automatically converted to links. http://www.example.com or <http://www.example.com>, and sometimes example.com (but not on Github).
Some text indicating that the reference link can follow later.
[Any case-insensitive reference text]: https://www.mozilla.org
[1]: http://slashdot.org
[The link text itself]: http://www.reddit.com
Renders to:
Picture #
The content of markdown is as follows:
This is the logo:
Inline style:
![Alternative text](./images/icon48.png "Logo Title Text 1")
Quote style:
![Alternative text][Logo]
[Logo]: ./images/icon48.png "Logo Title Text 2"
No caption below the image, and the image is right next to the text:
![Minion](./images/minion.png){width=20%}
![Stormtroopocat](./images/stormtroopocat.png "The Stormtroopocat"){width=20%}
You can also add a caption below the image, which needs to be a separate paragraph, that is, a blank line before and after:
![Image title, some explanation][id]
Define the image location in the quote later in the document:
[id]: ./images/dojocat.jpg "The Dojocat"
You can also specify the image size:
![Minion](./images/minion.png){width=5%} ![Minion](./images/minion.png){width=10%}
![Minion](./images/minion.png){width=20%}![Minion](./images/minion.png){width=30%}
Renders to:
Footnote #
markdown The content is as follows:
Footnote 1 link [^1].
Footnote 2 link [^2].
~Inline footnote ^[text of inline footnote] definition.
Repeated footnote reference [^2].
[^1]: Footnotes **can have tags** and multiple paragraphs.
[^2]: Footnote text.
Renders to:
Definition list #
The content of markdown is as follows:
Term
: The term name is on a separate line, and the second line starts with a colon (`: `), followed by a description of the term definition
Another term
: It starts with a colon (`: `), followed by a description of the term definition. *Definition lists* are often used in documents to unify the definitions of professional terms, business terms, and nouns.
Term entry line break
: It is related to the line break interpretation of markdown. If it is `hard_linkbreak`, a line needs to be left blank between entries.
This is not a definition term
: The definition term is not separated from the previous entry by a blank line and cannot become a new entry.
Term definition paragraph
: The term content is indented to the right as a whole paragraph.
Renders to:
Mathematical Equations #
The content of markdown is as follows:
Display on a single line
: $$
e=mc^2
$$
Inline
: This is a bunny, followed by a formula, $e=mc^2$. There can be text after it.
Renders to:
Code highlighting #
markdown The content is as follows:
```
Inline `code` has `backticks` around it.
```
Inline `code` has `backticks` around it.
Code blocks use a pair of triple backticks ```
css sample:
````
```css
@font-face {
font-family: Chunkfive; src: url('Chunkfive.otf');
}
body, .usertext {
color: #F0F0F0; background: #600;
font-family: Chunkfive, sans;
}
@import url(print.css);
@media print {
a[href^=http]::after {
content: attr(href)
}
}
```
````
css highlighting effect:
```css
@font-face {
font-family: Chunkfive; src: url('Chunkfive.otf');
}
body, .usertext {
color: #F0F0F0; background: #600;
font-family: Chunkfive, sans;
}
@import url(print.css);
@media print {
a[href^=http]::after {
content: attr(href)
}
}
```
----
javascript sample:
````
```javascript
function $initHighlight(block, cls) {
try {
if (cls.search(/\bno\-highlight\b/) != -1)
return process(block, true, 0x0F) +
` class="${cls}"`;
} catch (e) {
/* handle exception */
}
for (var i = 0 / 2; i < classes.length; i++) {
if (checkCondition(classes[i]) === undefined)
console.log('undefined');
}
}
export $initHighlight;
```
````
javascript highlighting effect:
```javascript
function $initHighlight(block, cls) {
try {
if (cls.search(/\bno\-highlight\b/) != -1)
return process(block, true, 0x0F) +
` class="${cls}"`;
} catch (e) {
/* handle exception */
}
for (var i = 0 / 2; i < classes.length; i++) {
if (checkCondition(classes[i]) === undefined)
console.log('undefined');
}
}
export $initHighlight;
```
Renders to:
Table #
The markdown content is as follows:
*Colons* can be used to align columns.
| Table | is very | Cool |
| ------------- |:-------------:| -----:|
| Column 3 is | Right-aligned | $1600 |
| Column 2 is | Centered | $12 |
| Zebra Stripes | Neat | $1 |
There must be at least 3 dashes (`-`) between each header cell.
The outer pipes (`|`) are optional and you don't need them to make the raw Markdown line up nicely. You can also use inline Markdown.
Table example, outer pipe characters (|) can be omitted:
Markdown | Less | Pretty
--- | --- | ---
*Still* | `Renders` | **Very well**
1 | 2 | 3
| First heading | Second heading |
| ------------- | ------------- |
| Content cell | Content cell |
| Content cell | Content cell |
Table example, cell content can be marked up:
| Command | Description |
| --- | --- |
| git status | List all new or modified files |
| git diff | Show differences in files that have not yet been staged |
| Command | Description |
| --- | --- |
| `git status` | List all *new or modified* files |
| `git diff` | Show differences in files that have not yet been staged |
Table example, columns can be freely aligned:
| Left alignment | Center alignment | Right alignment |
| :--- | :---: | ---: |
| git status | git status | git status |
| git diff | git diff | git diff |
Table example, special symbols in cells:
| Name | Character |
| --- | --- |
| Backtick | ` |
| Pipe | \| |
Renders to:
Table width and column width #
The pandoc markdown parser supports table formats with two grids that can control the table width and column width, multiline tables
and grid tables
. The default line width of 72 scii characters can fill the entire page width.
Take grid_stables
as an example:
: 2 columns 72 characters
+-----------------------------------+----------------------------------+
| Fruit Price | Advantages |
+===================================+:=================================+
| Oranges $2.10 | - cures scurvy |
| | - tasty |
+-----------------------------------+----------------------------------+
: 3 columns 72 characters
+---------------+-------------------+----------------------------------+
| Fruit | Price | Advantages |
+===============+===================+:=================================+
| Oranges | $2.10 | - cures scurvy |
| | | - tasty |
+---------------+-------------------+----------------------------------+
: 2 columns 37 characters
+---------------+-------------------+
| Fruit | Price |
+===============+===================+
| Oranges | $2.10 |
| | |
+---------------+-------------------+
Renders to:
Take multiline_tables
as an example:
: 4 columns 72 characters
------------------------
Centered Default Right Left
Header Aligned Aligned Aligned
---------- ------- --------------- -------------------------------------
First row 12.0 Example of a row that
spans multiple lines.
------------------------
: 3 columns 34 characters
------------------------
Centered Default Right
Header Aligned Aligned
---------- ------- ---------------
First row 12.0
------------------------
: 2 columns 72 characters
------------------------
Centered Default Right Left
Header Aligned Aligned Aligned
----------------------------- ------------------------------------
First row 12.0 Example of a row that
spans multiple lines.
------------------------
Renders to:
Block Quotes #
The markdown content is as follows:
> Blockquotes are really handy in emails to simulate reply text.
This line is part of the same quote.
Quote separator.
> This is a really long line that will still quote correctly when it wraps. Oh, let's keep writing it to make sure it's long enough to actually wrap for each person. Oh, and you can *put* **Markdown** into a blockquote.
> Blockquotes can also be nested...
>> ...by using additional greater-than signs right next to each other...
> > > ...or with spaces between the arrows.
Renders to:
gfm alerts #
alerts is a special html css style in GitHub-Flavored markdown. This template has been processed for compatibility. In addition to the note, tip, important, caution, and warning specified by gfm itself, it also supports idea, error, success, goal, and notification. Both uppercase and lowercase are acceptable.
The markdown content is as follows:
> [!NOTE]
> This is a note
> [!TIP]
> This is a tip
> [!IMPORTANT]
> This is important
> [!CAUTION]
> Be careful with the problem described here
> [!WARNING]
> Warning
>
>[!Idea]
> This is an idea
>
>
> [!Error]
> This is an error
>
> [!Success]
> When successful
> [!Goal]
> This is the goal
>
> [!Notification]
> There is a notification here
>
Renders to:
horizontal rule #
The markdown content is as follows:
Three symbols or more
Three hyphens `---`
---
Three asterisks `***`
***
Three underscores `___`
___
Renders to:
title #
The markdown content is as follows:
Alt-H2
------
# (only for demonstration) h1 title
## h2 title
### h3 title
#### h4 title
##### h5 title
###### h6 title
Or, for H1 and H2, use the underline style:
(only for demonstration) Alt-H1
======
Alt-H2
------
Renders to:
Usage #
Install this template as a typst local package, that is, copy or link it to the user’s local directory {data_dir}/typst/packages/local
, so that when using pandoc to convert markdown to pdf, specify the --template
parameter as a template in the template folder themekit/{version number}/pandoc/
.
{data_dir}
is related to the operating system
For detailed operations, see the [User Guide] of the template program
How to get this template #
If the above demonstration meets your daily use requirements, or if you need to develop and maintain such a program yourself but don’t want to start from scratch, you can refer to this template.
This pandoc typst template program for converting markdown to pdf, has no plans to be open source yet. You can get the authorized version from the following link.
- For Users outside of Mainland China
- on ko-fi: pandoc typst template for converting markdown to pdf
- on unifans.io: Convert markdown to pdf using pandoc and typst
- For Users in Mainland China
chinese version of this article: 《使用 pandoc 和 typst 将 markdown 转换为 pdf》