Generate forensic report using docxtpl templates
Project description
laudo
Convert markdown files to docx or pdf using docxtpl templates and LibreOffice headless.
Installation
pip install laudo
Requires Python 3.13+ and LibreOffice installed system-wide for PDF output.
Usage
CLI
laudo <folder> <output>
<folder>— directory with your project files.<output>— output file (.docxor.pdf).
Python API
from laudo import convert
convert("my_project/", "output.docx")
convert("my_project/", "output.pdf")
Input Folder Structure
my_project/
├── template.docx # docxtpl template with Jinja2 placeholders
├── fotos/ # Images with captions (EXIF)
│ ├── logo.png
│ └── photo.jpg
├── context.txt # (optional) Variables one per line
├── intro.md # One or more .md files
└── chapter-1.md
template.docx
A standard Word document using docxtpl syntax. Use Jinja2 placeholders like {{ variable }} or {{p intro|markdown }}.
context.txt
Optional file with variables in key = value format, one per line:
author = John Doe
title = My Document
Lines starting with # and empty lines are ignored.
These variables are also available for substitution inside your .md files (see below).
Markdown files
Every .md file is read and its content is injected into the template context. The variable name is the filename without extension (whitespace replaced by underscores):
| File | Context key |
|---|---|
intro.md |
intro |
chapter 1.md |
chapter_1 |
You can use {{ varname }} inside .md files to reference values from context.txt:
context.txt:
name = John Doe
intro.md:
# Hello {{ name }}
The result will be # Hello John Doe, then stored in context key intro.
image_group(name, cols) shorthand
Inside .md files you can use the image_group(name, cols) shorthand to embed a sub-template with images from a specific photo group:
image_group(events, 3)
This is automatically expanded to:
{{p subdoc('image_group', pics=pics.group('events'), cols=3) }}
It renders the image_group.docx sub-template, passing the images from the events group and the number of columns. See Fotos for how image groups work.
Use the subdoc global function to embed .docx sub-templates located alongside the main template:
{{p subdoc("cover.docx") }}
You can also pass context variables to the sub-template:
{{p subdoc("cover.docx", title=title, author=author) }}
Use the markdown filter in your template:
{{p intro|markdown }}
Fotos
All image files inside fotos/ are listed recursively (including subdirectories). Two context variables are injected:
pics—list[dict]of all imagespics_map—dict[str, dict]keyed byrefnamefor quick lookup
Each image dict:
{
"refname": "logo",
"path": "fotos/logo.png",
"caption": "",
"thumb": ".laudo/thumbs/logo_thumb.jpg",
"reduced": ".laudo/thumbs/logo_reduced.jpg",
"label": "Foto",
"group": ""
}
refnameis the filename without extension.groupis empty for images directly infotos/, or the subfolder path (e.g."events","events/party") for images in subdirectories.- Results are sorted first by
group, then byrefname. - Captions are read from the SQLite database
pics.sqlitein.laudo/. - Thumbnails and reduced images are generated on demand and stored in
.laudo/thumbs/.
PDF Output
When the output path ends with .pdf, a docx is generated first and then converted to PDF via LibreOffice headless:
laudo my_project/ output.pdf
The intermediate docx file is automatically removed.
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file laudo-0.2.0.tar.gz.
File metadata
- Download URL: laudo-0.2.0.tar.gz
- Upload date:
- Size: 95.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6cd771e3f5c7b0256bde307cd38ffb65a59ba2fb09f3363df95f7bf0ffbce32
|
|
| MD5 |
e081eb83d8c5ea063af4355a358e088c
|
|
| BLAKE2b-256 |
44f2243bd21a8bb37483810a1d766edf34368d0310eb59b1b60ffa9e031b511a
|
File details
Details for the file laudo-0.2.0-py3-none-any.whl.
File metadata
- Download URL: laudo-0.2.0-py3-none-any.whl
- Upload date:
- Size: 100.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ad407cc6031755999bb260400fd03a03d8a61e254d86d5c2cc4a263d4f4eb508
|
|
| MD5 |
3c8a4bead08cb4d1ccffe15a3b523269
|
|
| BLAKE2b-256 |
f8502b57a130d9c33fa8baa04c898d813310ad3228328792ec17565fe3c5b3f6
|