Skip to content

Commit f04005c

Browse files
committed
Initial commit
Split original project into separate repos.
0 parents  commit f04005c

13 files changed

Lines changed: 762 additions & 0 deletions

File tree

.editorconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[*.{css,js,json,less,md,py,rst,sass,scss,svg.j2,xml,yaml,yml}]
2+
charset = utf-8
3+
end_of_line = lf
4+
indent_size = 4
5+
indent_style = space
6+
insert_final_newline = true
7+
trim_trailing_whitespace = true
8+
9+
[*.{json,yml,yaml,rst,md}]
10+
indent_size = 2

.github/workflows/pre-commit.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: pre-commit
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- "main*"
7+
push:
8+
branches:
9+
- "main"
10+
11+
jobs:
12+
pre-commit:
13+
runs-on: ubuntu-22.04
14+
steps:
15+
- uses: actions/checkout@v4
16+
- uses: actions/setup-python@v5
17+
with:
18+
python-version: "3.11"
19+
- name: Get python version
20+
run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV
21+
- uses: actions/cache@v4
22+
with:
23+
path: ~/.cache/pre-commit
24+
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
25+
- name: Install pre-commit
26+
run: pip install pre-commit
27+
- name: Run pre-commit
28+
run: pre-commit run --all-files --show-diff-on-failure --color=always
29+
- name: Check that all files generated by pre-commit are in git
30+
run: |
31+
newfiles="$(git ls-files --others --exclude-from=.gitignore)"
32+
if [ "$newfiles" != "" ] ; then
33+
echo "Please check-in the following files:"
34+
echo "$newfiles"
35+
exit 1
36+
fi

.gitignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Python generated files
2+
__pycache__/
3+
*.py[cod]
4+
wheels/
5+
*.egg-info
6+
7+
# Cache
8+
/.pytest_cache
9+
/.ruff_cache
10+
11+
# venv
12+
/.venv
13+
14+
# PyCharm
15+
.idea/
16+
17+
# Backup files
18+
**.~
19+
*.swp

.pre-commit-config.yaml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
default_language_version:
2+
python: python3
3+
node: "22.9.0"
4+
repos:
5+
- repo: local
6+
hooks:
7+
- id: prettier
8+
name: prettier (with plugin-xml)
9+
entry: prettier
10+
args:
11+
- --write
12+
- --list-different
13+
- --ignore-unknown
14+
types: [text]
15+
files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$
16+
language: node
17+
additional_dependencies:
18+
- "prettier@3.3.3"
19+
- "@prettier/plugin-xml@3.4.1"
20+
- repo: https://github.com/pre-commit/pre-commit-hooks
21+
rev: v4.6.0
22+
hooks:
23+
- id: trailing-whitespace
24+
- id: end-of-file-fixer
25+
- id: debug-statements
26+
- id: fix-encoding-pragma
27+
args: ["--remove"]
28+
- id: check-case-conflict
29+
- id: check-docstring-first
30+
- id: check-executables-have-shebangs
31+
- id: check-merge-conflict
32+
- id: check-symlinks
33+
- id: check-xml
34+
- id: mixed-line-ending
35+
args: ["--fix=lf"]
36+
- repo: https://github.com/astral-sh/ruff-pre-commit
37+
rev: v0.6.8
38+
hooks:
39+
- id: ruff
40+
args: [--fix, --exit-non-zero-on-fix]
41+
- id: ruff-format
42+
- repo: https://github.com/PyCQA/pylint
43+
rev: v3.3.4
44+
hooks:
45+
- id: pylint
46+
args:
47+
- --rcfile=.pylintrc

.pylintrc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[MASTER]
2+
score=n
3+
generated-members=PyPDF2.*
4+
ignored-modules=jinja2,pypdf,yaml
5+
6+
[REPORTS]
7+
msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg}
8+
output-format=colorized
9+
reports=no
10+
11+
[MESSAGES CONTROL]
12+
disable=W0511 # Disable TODO/FIXME warnings

.ruff.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
target-version = "py310"
2+
fix = true
3+
4+
[lint]
5+
extend-select = [
6+
"B",
7+
"C90",
8+
"E501", # line too long (default 88)
9+
"I", # isort
10+
"UP", # pyupgrade
11+
]
12+
extend-safe-fixes = ["UP008"]
13+
14+
[lint.isort]
15+
section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"]
16+
17+
[lint.mccabe]
18+
max-complexity = 16

README.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# kpc-sponsorship
2+
3+
Creates a [Kiwi PyCon](https://kiwipycon.nz/) sponsorship prospectus and material specs
4+
documents for different sponsorship tiers in PDF format.
5+
6+
The main branch has a year tag for the version that is/was used for that particular
7+
year's conference, like
8+
"[2025](https://github.com/pythonnz/kpc-sponsorship/releases/tag/2025)".
9+
10+
## Requirements
11+
12+
- [Roboto fonts](https://fonts.google.com/specimen/Roboto) - the font we use
13+
- [Jinja2](https://jinja.palletsprojects.com/en/stable/) (>=3.1.3) - to render the SVG
14+
templates
15+
- [Inkscape](https://inkscape.org/) - to convert SVG to PDF
16+
- [pypdf](https://pypdf.readthedocs.io/en/stable/index.html) (>=4.3.1) - to assemble PDF
17+
pages to a document
18+
- [Ghostscript](https://www.ghostscript.com/) - for PDF compression
19+
20+
```
21+
sudo apt install fonts-roboto
22+
sudo apt install python3-jinja2
23+
sudo apt install inkscape
24+
sudo apt install python3-pypdf
25+
sudo apt install ghostscript
26+
```
27+
28+
The two Python dependencies can also be installed with pip:
29+
30+
```
31+
pip install -r requirements.txt
32+
```
33+
34+
The requirements file installs at least the versions that currently get installed by the
35+
above system packages on Ubuntu 24.10.
36+
37+
## Usage
38+
39+
Generate all documents with:
40+
41+
```
42+
python3 -m generate
43+
```
44+
45+
This will create a `build/` directory and a `dist/` directory (both ignored by git).<br>
46+
It will produce your PDF files in the `dist/` directory (and leave some artifacts in the
47+
`build/` directory, mainly for debugging).
48+
49+
## Structure and Workflow
50+
51+
A total of 6 documents are generated:
52+
53+
- Sponsorship Prospectus
54+
- Material Specs - Diamond
55+
- Material Specs - Platinum
56+
- Material Specs - Gold
57+
- Material Specs - Silver
58+
- Material Specs - Bronze
59+
60+
A **document** is made up of **pages**.<br> Pages take their layout from **templates**,
61+
and their specific content from your **configuration**. They may also include
62+
**images**.
63+
64+
- `templates/`<br> contains `.svg.j2` files describing the layout of a page. These are
65+
Jinja2 templates which are used to render pages in SVG format, which then gets
66+
transformed into PDF.<br> They contain placeholders for text and images.<br> You only
67+
need to work with these files if you want to make fundamental layout or branding
68+
changes.
69+
70+
- `pages/`<br> contains one `.yml` file for each page of a document. These files
71+
describe which template to use, which image files (if any) should be used in its
72+
template, and they also define content which generally doesn't need to be
73+
configurable.<br> You only need to work with these files if you want to change text
74+
that is usually fixed, or if you want to change which images are used.
75+
76+
- `images/`<br> contains the actual image files referenced in the `.yml` files for
77+
pages.
78+
79+
- `config/`<br> contains the configuration of all documents. It describes which pages
80+
make up a document and in which order, and what specific content to insert. Common
81+
configuration is in `common.yml`, document-specific configuration in their respective
82+
files.<br> You will at the very least need to to adjust the year for your next
83+
conference in `common.yml`.
84+
85+
- `generate/`<br> Contains the code for generating documents.<br> The main entry point
86+
for invoking the generator is in `__main__.py`. Common functionality is in
87+
`common.py`. Helper functions for rendering the SVGs with Jinja are in `render.py`.
88+
Each document gets its own separate module under `documents/`.<br> Documents are
89+
generated using the above framework. A top-level `build/` working directory and a
90+
`dist/` directory for the final results will be created. If they already exist they
91+
will be wiped clean.<br> In the `build/` directory, it will create individual `.svg`
92+
files for each page, convert them to `.pdf` files, and then combine them into a single
93+
`.pdf` file for each document and place them in the `dist/` directory. The prospectus
94+
PDF will also be compressed.
95+
96+
Note: You need to follow a consistent naming convention.
97+
`generate/documents/prospectus.py` will be given the combined configuration of
98+
`config/common.yml` and `config/prospectus.yml`. It will take its pages from
99+
`pages/prospectus/`. Do the same for any new documents you may add.
100+
101+
## Development
102+
103+
Your changes will be rejected by github if the linters throw warnings. You should
104+
install [pre-commmit](https://pre-commit.com) and run
105+
106+
```
107+
pre-commit install
108+
```
109+
110+
inside your repo. This will ensure you run the same checks as github every time you
111+
commit.
112+
113+
## Known Issues
114+
115+
See [Github Issues](https://github.com/pythonnz/kpc-sponsorship/issues) for known
116+
issues.

prettier.config.cjs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/** @type {import('prettier').Config} */
2+
3+
const config = {
4+
plugins: [require.resolve("@prettier/plugin-xml")],
5+
bracketSpacing: false,
6+
printWidth: 88,
7+
proseWrap: "always",
8+
semi: true,
9+
trailingComma: "es5",
10+
xmlWhitespaceSensitivity: "strict",
11+
};
12+
13+
module.exports = config;

pyproject.toml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
[project]
2+
name = "pdfbaker"
3+
version = "0.1.0"
4+
description = "SVG Jinja templates + YAML config = PDF documents"
5+
authors = [
6+
{ name = "Danny W. Adair", email = "danny.adair@unfold.nz" }
7+
]
8+
dependencies = [
9+
"pyyaml",
10+
"jinja2",
11+
"pypdf",
12+
]
13+
readme = "README.md"
14+
requires-python = ">= 3.11"
15+
16+
[project.optional-dependencies]
17+
cairosvg = ["cairosvg"]
18+
all = ["cairosvg"]
19+
20+
[project.scripts]
21+
pdfbaker = "pdfbaker.__main__:main"
22+
23+
[build-system]
24+
requires = ["hatchling==1.26.3"] # https://github.com/astral-sh/rye/issues/1446
25+
build-backend = "hatchling.build"
26+
27+
[tool.rye]
28+
managed = true
29+
dev-dependencies = []
30+
31+
[tool.hatch.metadata]
32+
allow-direct-references = true
33+
34+
[tool.hatch.build.targets.wheel]
35+
packages = ["src/pdfbaker"]

src/pdfbaker/__init__.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""Core functionality for document generation."""
2+
3+
from .common import (
4+
load_pages,
5+
compress_pdf,
6+
combine_pdfs,
7+
convert_svg_to_pdf,
8+
)
9+
10+
from .render import (
11+
process_template_data,
12+
create_env,
13+
highlight,
14+
process_style,
15+
process_text_with_jinja,
16+
process_list_item_texts,
17+
process_list_items,
18+
space_bullets,
19+
encode_image,
20+
encode_images,
21+
)
22+
23+
__all__ = [
24+
# Common functions
25+
"load_pages",
26+
"compress_pdf",
27+
"combine_pdfs",
28+
"convert_svg_to_pdf",
29+
# Render functions
30+
"process_template_data",
31+
"create_env",
32+
"highlight",
33+
"process_style",
34+
"process_text_with_jinja",
35+
"process_list_item_texts",
36+
"process_list_items",
37+
"space_bullets",
38+
"encode_image",
39+
"encode_images",
40+
]

0 commit comments

Comments
 (0)