Skip to content

Instantly share code, notes, and snippets.

@waylan
Created June 9, 2021 20:18
Show Gist options
  • Save waylan/db1fef8cb32fe660a617938af5f62ab2 to your computer and use it in GitHub Desktop.
Save waylan/db1fef8cb32fe660a617938af5f62ab2 to your computer and use it in GitHub Desktop.
A simple Markdown to PDF converter.
import markdown
from xhtml2pdf import pisa
from datetime import date
TEMPLATE = """
<html>
<head>
<style>
@page {{
size: letter portrait;
@frame header_left_frame {{
-pdf-frame-content: header_left_content;
left: 50pt; width: 170pt; top: 10pt; height: 40pt;
}}
@frame header_center_frame {{
-pdf-frame-content: header_center_content;
left: 221pt; width: 170pt; top: 10pt; height: 40pt;
}}
@frame header_right_frame {{
-pdf-frame-content: header_right_content;
left: 392pt; width: 170pt; top: 10pt; height: 40pt;
}}
@frame content_frame {{
left: 50pt; width: 512pt; top: 50pt; height: 692pt;
margin: 10pt, 0;
}}
@frame footer_left_frame {{
-pdf-frame-content: footer_left_content;
left: 50pt; width: 170pt; top: 742pt; height: 40pt;
}}
@frame footer_center_frame {{
-pdf-frame-content: footer_center_content;
left: 221pt; width: 170pt; top: 742pt; height: 40pt;
}}
@frame footer_right_frame {{
-pdf-frame-content: footer_right_content;
left: 392pt; width: 170pt; top: 742pt; height: 40pt;
}}
div {{border: 1px solid black;}}
#header_left_content, #footer_left_content {{
text-align: left;
}}
#header_center_content, #footer_center_content {{
text-align: center;
}}
#header_right_content, #footer_right_content {{
text-align: right;
}}
#header_left_content, #header_center_content, #header_right_content {{
display:table-cell;
vertical-align: bottom;
}}
}}
</style>
</head>
<body>
<div id="header_left_content">{top_left}</div>
<div id="header_center_content">{top_center}</div>
<div id="header_right_content">{top_right}</div>
<div id="footer_left_content">{bottom_left}</div>
<div id="footer_center_content">{bottom_center}</div>
<div id="footer_right_content">{bottom_right}</div>
{body}
</body>
</html>
"""
positions = ('left', 'center', 'right')
header_pos = [f'top_{pos}' for pos in positions]
footer_pos = [f'bottom_{pos}' for pos in positions]
def md2pdf(input, output, header=None, footer=None):
header = header or ('', '', '')
footer = footer or ('', '', '')
with open(input, 'r') as fd:
md_src = fd.read()
context = {'body': markdown.markdown(md_src)}
context.update(zip(header_pos, header))
context.update(zip(footer_pos, footer))
html = TEMPLATE.format(**context)
with open(output, 'w+b') as fd:
status = pisa.CreatePDF(html, dest=fd)
return status.err
if __name__ == '__main__':
pisa.showLogging()
today = date.today().strftime('%m/%d/%Y')
md2pdf('source.md', 'output.pdf', header=('left', 'center', 'right'), footer=('left', 'center', 'Updated '+ today))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment