Render HTML (with CSS) to a PDF file. Trigger when the user wants to export a styled report, invoice, label, or any HTML/Jinja-rendered page to PDF. Uses WeasyPrint, which supports a meaningful subset of CSS Paged Media (page size, margins, headers/footers, page-break-before/after). Optional dependency — install via `pip install opensquilla[document-extras]` or `uv add weasyprint` because WeasyPrint pulls in native libraries (Pango, Cairo, fontconfig) that need OS-level packages.
62
75%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Fix and improve this skill with Tessl
tessl review fix ./src/opensquilla/skills/bundled/html-to-pdf/SKILL.mdRender HTML + CSS to PDF using WeasyPrint. Best for static report exports
where the source already exists in HTML form (templates, dashboards,
invoices). For programmatic PDF assembly from data structures, use the
pdf-toolkit skill's reportlab path instead.
First, use the available tool list for this session to choose the delivery path.
If write_file, edit_file, apply_patch, or execute_code is available:
.pdf, .html, or requested file in the active workspace using the
workflow below.publish_artifact for the final file before your final reply when that
tool is available.If none of those file-authoring tools are available:
In all cases, do not paste full file source as the deliverable. Source code is appropriate only when the user explicitly asks for code.
pdf-toolkit (reportlab) directly instead.pdf-toolkit (pypdf path).docx skill.python {baseDir}/scripts/render.py --html report.html --out report.pdf
python {baseDir}/scripts/render.py --html invoice.html --out invoice.pdf --page-size A4The script accepts a local file path, a file:// URL, or an http(s)://
URL. CSS is loaded relative to the HTML location for local paths; for
URLs, the same fetch rules apply (network resources are loaded with
WeasyPrint's default fetcher).
WeasyPrint implements the parts of CSS that matter for paged output:
@page rule with size, margin, @top-center, @bottom-right boxespage-break-before, page-break-after, break-inside: avoidcounter(page), counter(pages)prince- properties: WeasyPrint supports many but not all PrinceXML
extensionsExample header/footer setup:
@page {
size: Letter;
margin: 1in;
@top-center { content: "Q3 Review — Confidential"; }
@bottom-right { content: "Page " counter(page) " of " counter(pages); }
}WeasyPrint is pure Python but depends on native libraries. The OpenSquilla
install spec only triggers pip install weasyprint; the OS packages must
be installed separately.
brew install pango cairo gdk-pixbuf libffisudo apt-get install -y libpango-1.0-0 libpangoft2-1.0-0 \
libharfbuzz0b libfontconfig1The simplest path is the GTK runtime via winget:
winget install --id GTK.GTK3Or use MSYS2's mingw-w64-x86_64-pango package and ensure its bin/
directory is on PATH. WeasyPrint ≥61 ships an alternate "lite" path that
bundles its own native libs on Windows; check WeasyPrint's installation
docs for the current state.
If the render.py script raises OSError: cannot load library, the
native libs are not on the search path — the user must install them per
the platform instructions above.
@font-face with absolute paths or data URIs.94ac35e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.