-
-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy pathpdf.py
85 lines (76 loc) · 2.74 KB
/
pdf.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#
# Copyright © Michal Čihař <[email protected]>
#
# This file is part of Weblate <https://weblate.org/>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
from __future__ import annotations
from pathlib import Path
from django.conf import settings
from django.contrib.staticfiles import finders
from weasyprint import CSS, HTML
from weasyprint.text.fonts import FontConfiguration
SIGNATURE_URL = "signature:"
INVOICES_URL = "invoices:"
LEGAL_URL = "legal:"
STATIC_URL = "static:"
INVOICES_TEMPLATES_PATH = Path(__file__).parent / "invoices" / "templates"
LEGAL_TEMPLATES_PATH = Path(__file__).parent / "legal" / "templates"
def url_fetcher(url: str) -> dict[str, str | bytes]:
path_obj: Path
result: dict[str, str | bytes]
if url == SIGNATURE_URL:
if settings.AGREEMENTS_SIGNATURE_PATH is None:
raise ValueError("Signature not configured!")
path_obj = settings.AGREEMENTS_SIGNATURE_PATH
elif url.startswith(INVOICES_URL):
path_obj = INVOICES_TEMPLATES_PATH / url.removeprefix(INVOICES_URL)
elif url.startswith(LEGAL_URL):
path_obj = LEGAL_TEMPLATES_PATH / url.removeprefix(LEGAL_URL)
elif url.startswith(STATIC_URL):
fullname = url.removeprefix(STATIC_URL)
match = finders.find(fullname)
if match is None:
raise ValueError(f"Could not find {fullname}")
path_obj = Path(match)
else:
raise ValueError(f"Unsupported URL: {url}")
result = {
"filename": path_obj.name,
"string": path_obj.read_bytes(),
}
if path_obj.suffix == ".css":
result["mime_type"] = "text/css"
result["encoding"] = "utf-8"
return result
def render_pdf(*, html: str, output: Path) -> None:
font_config = FontConfiguration()
renderer = HTML(
string=html,
url_fetcher=url_fetcher,
)
fonts_css = finders.find("pdf/fonts.css")
if fonts_css is None:
raise ValueError("Could not load fonts CSS")
font_style = CSS(
filename=fonts_css,
font_config=font_config,
url_fetcher=url_fetcher,
)
renderer.write_pdf(
output,
stylesheets=[font_style],
font_config=font_config,
)