Combine with Markdown¶
Several fpdf2
methods allow Markdown syntax elements:
FPDF.cell()
has an optionalmarkdown=True
parameter that makes it possible to use**bold**
,__italics__
,~~strikethrough~~
or--underlined--
Markdown markersFPDF.multi_cell()
&FPDF.table()
methods have a similar feature
But fpdf2
also allows for basic conversion from HTML to PDF (cf. HTML). This can be combined with a Markdown-rendering library in order to generate PDF documents from Markdown:
mistletoe¶
The mistletoe library follows the CommonMark specification:
pip install mistletoe
from mistletoe import markdown
html = markdown(
"""
# Top title (ATX)
Subtitle (setext)
-----------------
### An even lower heading (ATX)
**Text in bold**
_Text in italics_
~~Strikethrough~~
[This is a link](https://github.com/PyFPDF/fpdf2)
<https://py-pdf.github.io/fpdf2/>
This is an unordered list:
* an item
* another item
This is an ordered list:
1. first item
2. second item
3. third item with an unordered sublist:
* an item
* another item
Inline `code span`
A table:
| Foo | Bar | Baz |
| ---:|:---:|:--- |
| Foo | Bar | Baz |
Actual HTML:
<dl>
<dt>Term1</dt><dd>Definition1</dd>
<dt>Term2</dt><dd>Definition2</dd>
</dl>
Some horizontal thematic breaks:
***
---
___

"""
)
from fpdf import FPDF
pdf = FPDF()
pdf.add_page()
pdf.write_html(html)
pdf.output("pdf-from-markdown-with-mistletoe.pdf")
The library can be easily extended: Creating a custom token and renderer.
Rendering unicode characters¶
from mistletoe import markdown
html = markdown(
"""
# Unicode:
| Emoji | Description |
| --- | - |
| 😀 | GRINNING FACE |
| 😁 | GRINNING FACE WITH SMILING EYES |
| 😈 | SMILING FACE WITH HORNS |
# A checklist:
* ☐ item 1
* ☑ item 2
* ☐ item 3
"""
)
from fpdf import FPDF
pdf = FPDF()
pdf.add_font("DejaVuSans", fname="test/fonts/DejaVuSans.ttf")
pdf.add_font("DejaVuSans", fname="test/fonts/DejaVuSans-Bold.ttf", style="B")
pdf.set_font("DejaVuSans", size=24)
pdf.add_page()
pdf.write_html(html)
pdf.output("pdf-from-markdown-with-mistletoe-unicode.pdf")
Result:
markdown-it-py¶
The markdown-it-py library also follows the CommonMark specification:
pip install markdown-it-py
from markdown_it import MarkdownIt
md = (
MarkdownIt("commonmark", {"breaks": True, "html": True})
.enable("strikethrough")
.enable("table")
)
html = md.render(
"""
# Top title (ATX)
Subtitle (setext)
-----------------
### An even lower heading (ATX)
**Text in bold**
_Text in italics_
~~Strikethrough~~
[This is a link](https://github.com/PyFPDF/fpdf2)
<https://py-pdf.github.io/fpdf2/>
This is an unordered list:
* an item
* another item
This is an ordered list:
1. first item
2. second item
3. third item with an unordered sublist:
* an item
* another item
Inline `code span`
A table:
| Foo | Bar | Baz |
| ---:|:---:|:--- |
| Foo | Bar | Baz |
Actual HTML:
<dl>
<dt>Term1</dt><dd>Definition1</dd>
<dt>Term2</dt><dd>Definition2</dd>
</dl>
Some horizontal thematic breaks:
***
---
___

"""
)
from fpdf import FPDF
pdf = FPDF()
pdf.add_page()
pdf.write_html(html)
pdf.output("pdf-from-markdown-with-markdown-it.pdf")
Plugin extensions: the strikethrough
& table
plugins are embedded within the core package, and many other plugins are then available via the mdit-py-plugins package, including:
- Footnotes
- Definition lists
- Task lists
- Heading anchors
- LaTeX math
- Containers
- Word count
mistune¶
There is also the mistune library, that may be the fastest, but it does not follow the CommonMark spec:
pip install mistune
from mistune import html
html = html(
"""
# Top title (ATX)
Subtitle (setext)
-----------------
### An even lower heading (ATX)
**Text in bold**
_Text in italics_
~~Strikethrough~~
[This is a link](https://github.com/PyFPDF/fpdf2)
<https://py-pdf.github.io/fpdf2/>
This is an unordered list:
* an item
* another item
This is an ordered list:
1. first item
2. second item
3. third item with an unordered sublist:
* an item
* another item
Inline `code span`
A table:
| Foo | Bar | Baz |
| ---:|:---:|:--- |
| Foo | Bar | Baz |
Actual HTML:
<dl>
<dt>Term1</dt><dd>Definition1</dd>
<dt>Term2</dt><dd>Definition2</dd>
</dl>
Some horizontal thematic breaks:
***
---
___

"""
)
from fpdf import FPDF
pdf = FPDF()
pdf.add_page()
pdf.write_html(html)
pdf.output("pdf-from-markdown-with-mistune.pdf")
Python-Markdown¶
There is also the Python-Markdown library, which is the oldest Markdown rendering Python lib still active, but it does not follow the CommonMark spec:
pip install markdown
from markdown import markdown
html = markdown(
"""
# Top title (ATX)
Subtitle (setext)
-----------------
### An even lower heading (ATX)
**Text in bold**
_Text in italics_
[This is a link](https://github.com/PyFPDF/fpdf2)
<https://py-pdf.github.io/fpdf2/>
This is an unordered list:
* an item
* another item
This is an ordered list:
1. first item
2. second item
3. third item with an unordered sublist:
* an item
* another item
Inline `code span`
A table:
Foo | Bar | Baz
--- | --- | ---
Foo | Bar | Baz
Definition list:
Term
: Definition
Actual HTML:
<dl>
<dt>Term1</dt><dd>Definition1</dd>
<dt>Term2</dt><dd>Definition2</dd>
</dl>
Some horizontal thematic breaks:
***
---
___

""",
extensions=["def_list", "sane_lists", "tables"],
)
from fpdf import FPDF
pdf = FPDF()
pdf.add_page()
pdf.write_html(html)
pdf.output("pdf-from-markdown-with-markdown.pdf")