Commit f0ea49da authored by Jakob Moser's avatar Jakob Moser
Browse files

Merge branch 'certifications' into 'master'

Create commitment certifications using coliverter

Closes #1

See merge request !1
parents eec55ff5 b86f28d3
Loading
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -2,12 +2,13 @@

Convert files into other formats, using the organization identity of Fachschaft Computerlinguistik.

This app uses the universal document converter **[Pandoc](https://pandoc.org/)** and the PDF converter **[WeasyPrint](https://weasyprint.org/)**. Both are excellent pieces of software and to almost all heavy lifting in this app. If you ever need to do some document conversion yourself, you will likely not need the Coliverter, and instead just use the dependencies directly.
This app uses the universal document converter **[Pandoc](https://pandoc.org/)** and the PDF converter **[WeasyPrint](https://weasyprint.org/)**. Both are excellent pieces of software and do almost all heavy lifting in this app. If you ever need to do some document conversion yourself, you will likely not need the Coliverter, and instead just use the dependencies directly.

## Why Coliverter?

- **If your Markdown files contain Emoji or other special Unicode**: Pandoc's Markdown-to-PDF converter uses LaTeX for elegant results, but sadly this also makes it quite bad at processing emoji.
- **If you want to use the Fachschaft Computerlinguistik styles**: Those are integrated in the Coliverter, so that every file converted with it also looks like it was produced by the Fachschaft.
- **If you want to generate commitment certifications (“Engagementbescheinigungen”)**: Coliverter has templates, can sign them cryptographically etc.

### Showcase

@@ -44,11 +45,27 @@ If you use `uv`, this should work out of the box (replace the paths as desired):
coliverter examples/basic_document.md examples/out/basic_document.pdf
```

If you want to generate a commitment certification, you first need to create a JSON file containing all the required data. See the `examples/` folder for details. After that, it works just as expected:

```bash
coliverter examples/certification_aktiver_fachschaftler.json Robby_McRobotface_Certification.pdf
```

## Extend

You can add new types of commitment certifications by completing the following steps:

1. Add a new template in the [`coliverter.resources.templates.commitment_certification`](./src/coliverter/resources/templates/commitment_certification) package.
2. Reference the template in [`coliverter.certifications.ColiCertification`](./src/coliverter/certifications/ColiCertification.py).

For more details, you can roughly follow the [documentation of Schwalbe PDF generator](https://gitlab.com/schwalbe-hd/pdf-generator/-/blob/master/docs/add_certification_type.md?ref_type=heads) (you will need to adapt paths, but other than that, the documentation should be mostly applicable to the Coliverter as well).

## Further reading

1. https://packaging.python.org/en/latest/tutorials/packaging-projects/
2. https://packaging.python.org/en/latest/guides/creating-command-line-tools/
3. https://typer.tiangolo.com/ (and the very recommendable https://typer.tiangolo.com/tutorial/first-steps/)
4. https://gitlab.com/schwalbe-hd/pdf-generator

## Older software

+22 −0
Original line number Diff line number Diff line
{
    "$schema": "https://schwalbe.stura.uni-heidelberg.de/schemas/v4/Certification",
    "office": {
        "name": "Fachschaft Computerlinguistik",
        "subject": {
            "name": "Computerlinguistik"
        },
        "kind": {
            "name": "Fachschaft"
        }
    },
    "person": {
        "name": "Robby McRobotface",
        "birthdate": "2002-08-20"
    },
    "issueDate": "2025-09-04",
    "officePeriod": {
        "start": "2023-10-01",
        "end": "2026-03-31"
    },
    "url": null
}
+22 −0
Original line number Diff line number Diff line
{
    "$schema": "https://schwalbe.stura.uni-heidelberg.de/schemas/v4/Certification",
    "office": {
        "name": "Awareness-Beauftragte der Fachschaft Computerlinguistik",
        "subject": {
            "name": "Computerlinguistik"
        },
        "kind": {
            "name": "Awareness"
        }
    },
    "person": {
        "name": "Luca Mustermensch",
        "birthdate": null
    },
    "issueDate": "2025-12-07",
    "officePeriod": {
        "start": "2025-10-15",
        "end": "2026-10-15"
    },
    "url": null
}
+5 −1
Original line number Diff line number Diff line
[project]
name = "coliverter"
version = "0.5.1"
version = "0.6.0"
authors = [
  { name="Jakob Moser", email="moser@cl.uni-heidelberg.de" },
]
@@ -9,6 +9,7 @@ readme = "README.md"
requires-python = ">=3.12"
dependencies = [
    "pandoc>=2.4",
    "pdf-generator",
    "typer>=0.16.0",
    "weasyprint>=66.0",
]
@@ -29,3 +30,6 @@ dev = [
    "coverage>=7.12.0",
    "pytest>=9.0.2",
]

[tool.uv.sources]
pdf-generator = { git = "https://gitlab.com/schwalbe-hd/pdf-generator.git" }
+34 −0
Original line number Diff line number Diff line
from dataclasses import dataclass

from babel import Locale
from pdf_generator.commitment_certification.Certification import Certification
from pdf_generator.jinja.templates import fill_template

from coliverter.resources.templates.get_template import get_template


@dataclass(frozen=True)
class ColiCertification(Certification):
    def html(self, locale: Locale) -> str:
        # This override here is a bit unlucky, technically, we only need to replace the get_template method.
        # This should be modeled in a smarter way, but it isn't.
        template_name = self.__class__.get_template_name(
            self.office_name, self.office_kind_name
        )
        assert template_name is not None, "The constructor should have caught this"

        return fill_template(
            get_template(template_name, locale), locale, certification=self
        )

    @classmethod
    def get_template_name(cls, office_name: str, office_kind_name: str) -> str | None:
        match office_kind_name:
            case "Awareness":
                return "commitment_certification/awareness"
            case "Fachschaft":
                return "commitment_certification/fachschaft"
            case "Beauftragte für Internationale Studierende":
                return "commitment_certification/internationales"

        return super().get_template_name(office_name, office_kind_name)
Loading