Guide
Schema and code
Check templates and data against a JSON Schema before each render, and write the first template from your classes.
On this page
The schema file
A template can have a JSON Schema next to it, with the same name:
rechnung.md
rechnung.schema.jsonWhen the file exists, every brevier pdf and brevier html checks two
things before it prints:
- Each
{{ }}tag in the template names a field that the schema has. - The data matches the schema: required fields, types, lists.
If one check fails, nothing is printed. Brevier lists every problem, with the template line for the first check.
When there is no schema file, Brevier skips both checks.
--schema chooses another schema: the path of a file, or false to skip
the checks.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"rechnung": {
"type": "object",
"properties": {
"nummer": { "type": "string", "title": "Rechnungsnummer" },
"summe": { "type": "number", "format": "decimal" }
},
"required": ["nummer", "summe"]
}
},
"required": ["rechnung"]
}A column's title in the schema is also the default header text of a
table block.
From your classes
You do not have to write the schema by hand. It comes from the classes you already pass to your old PDF library, in two steps. Your classes need no Brevier interface, base class or annotation.
1. Write the schema
In Java, a build step reads your compiled classes. brevier-codegen.jar is
built by the Java client.
java -cp build/classes:brevier-codegen.jar dev.brevier.codegen.SchemaGeneratorCommand \
--root rechnung=com.ww.Rechnung --root kunde=com.ww.Kunde > rechnung.schema.jsonEach --root is one top-level field of the data: name=class. Add []
after the class for a list: --root positionen=com.ww.Position[].
In Python, brevier.schema() reads dataclasses, pydantic v2 models, attrs
classes, TypedDicts, Django models and SQLAlchemy models:
import json
from pathlib import Path
import brevier
from billing.models import Kunde, Rechnung
schema = brevier.schema(Rechnung, kunde=Kunde)
Path("rechnung.schema.json").write_text(json.dumps(schema, indent=2), encoding="utf-8")A class passed without a name gets the class name with a small first
letter: Rechnung becomes rechnung.
In C#, BrevierSchema.Create() reads your classes:
using System.IO;
using System.Text.Json;
using Brevier;
var schema = BrevierSchema.Create(typeof(Rechnung), typeof(Kunde));
File.WriteAllText("rechnung.schema.json", schema.ToJsonString(new() { WriteIndented = true }));2. Write the template
brevier template --schema rechnung.schema.jsonThis writes three files next to the schema:
| File | Content |
|---|---|
rechnung.html |
A first template that uses every field. |
rechnung.css |
A stylesheet to start from. |
sample.json |
Sample data that matches the schema. |
--format md writes a Markdown template instead of HTML. brevier template
never overwrites a file. If one of the three files exists, it writes none
of them. Add --force to replace them all.
From one record
If you have a real record and no classes, scaffold writes all four files
from it: the schema, the template, the stylesheet and the sample data.
brevier scaffold --from rechnung.jsonFrom a template
If you have the template, from-template writes the schema it needs.
With --lang java17 it also writes Java classes for the data.
brevier from-template rechnung.htmlSee Command line for all options.
The TypeScript client does not read types yet. Use brevier scaffold --from rechnung.json or write the schema by hand.