summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.envrc9
-rw-r--r--.gitignore8
-rw-r--r--.licensure.yml186
-rw-r--r--README.md7
-rw-r--r--beitragsordnung.tex42
-rwxr-xr-xbuild.sh14
-rw-r--r--content/static/title.tex11
-rw-r--r--flake.lock207
-rw-r--r--flake.nix126
-rw-r--r--headers/preamble.tex291
-rw-r--r--headers/preamble_local.tex50
-rw-r--r--lpm.toml16
-rw-r--r--references/reference.bib0
-rwxr-xr-xscripts/extract_text_from_all.sh8
-rw-r--r--treefmt.nix70
-rwxr-xr-xupdate.sh3
-rwxr-xr-xwatch.sh8
17 files changed, 1056 insertions, 0 deletions
diff --git a/.envrc b/.envrc
new file mode 100644
index 0000000..3bc1085
--- /dev/null
+++ b/.envrc
@@ -0,0 +1,9 @@
+use flake || use nix
+watch_file flake.nix
+
+PATH_add ./scripts
+
+if on_git_branch; then
+  echo && git status --short --branch &&
+  echo && git fetch --verbose
+fi
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..539b891
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+# build
+/result
+/build
+
+/resources.local
+
+# dev env
+.direnv
diff --git a/.licensure.yml b/.licensure.yml
new file mode 100644
index 0000000..cf3e67a
--- /dev/null
+++ b/.licensure.yml
@@ -0,0 +1,186 @@
+---
+# Regexes which if matched by a file path will always be excluded from
+# getting a license header
+excludes:
+  - .*lock
+  - \.git/.*
+  - LICENSE.spdx
+  - LICENSE
+  - COPYING
+  - COPYING.LESSER
+  - .*\.(rst|txt|pdf)
+# Definition of the licenses used on this project and to what files
+# they should apply.
+#
+# No default license configuration is provided. This section must be
+# configured by the user.
+licenses:
+  - files: \.tex
+    ident: CC-BY-SA-4.0
+    authors:
+      - name: "Silas Schöffel"
+        email: "sils@sils.li"
+
+    template: |
+      Vergügügütungsordnung 2024 - [year] (C) by [name of author]
+      SPDX-License-Identifier: CC-BY-SA-4.0
+
+      Vergügügütungsordnung is licensed under a
+      Creative Commons Attribution-ShareAlike 4.0 International License.
+
+      You should have received a copy of the license along with this
+      work.  If not, see <https://creativecommons.org/licenses/by-sa/4.0/>.
+
+    unwrap_text: false
+
+  # Either a regex or the string "any" to determine to what files this
+  # license should apply. It is common for projects to have files
+  # under multiple licenses or with multiple copyright holders. This
+  # provides the ability to automatically license files correctly
+  # based on their file paths.
+  #
+  # If "any" is provided all files will match this license.
+  - files: any
+    #
+    #   The license identifier, a list of common identifiers can be
+    #   found at: https://spdx.org/licenses/ but existence of the ident
+    #   in this list it is not enforced unless auto_template is set to
+    #   true.
+    ident: GPL-3.0-or-later
+    #
+    #   A list of authors who hold copyright over these files
+    authors:
+      # Provide either your full name or company name for copyright purposes
+      - name: "Silas Schöffel"
+        # Optionally provide email for copyright purposes
+        email: "sils@sils.li"
+
+    #   The template that will be rendered to generate the header before
+    #   comment characters are applied. Available variables are:
+    #    - [year]: substituted with the current year.
+    #    - [name of author]: Substituted with name of the author and email
+    #      if provided. If email is provided the output appears as Full
+    #      Name <email@example.com>. If multiple authors are provided the
+    #      list is concatenated together with commas.
+    template: |
+        Copyright (C) 2024 - [year]:
+        [name of author]
+        SPDX-License-Identifier: GPL-3.0-or-later
+
+        This file is part of Vergügügütungsordnung.
+
+        Vergügügütungsordnung is free software: you can redistribute it and/or modify
+        it under the terms of the Lesser GNU General Public License as
+        published by the Free Software Foundation, either version 3 of
+        the License, or (at your option) any later version.
+
+        This program is distributed in the hope that it will be useful,
+        but WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+        GNU General Public License for more details.
+
+        You should have received a copy of the GNU General Public License
+        and the Lesser GNU General Public License along with this program.
+        If not, see <https://www.gnu.org/licenses/>.
+
+
+    #   If auto_template is true then template is ignored and the SPDX
+    #   API will be queried with the ident value to automatically
+    #   determine the license header template. auto_template works best
+    #   with licenses that have a standardLicenseHeader field defined in
+    #   their license info JSON, if it is not then we will use the full
+    #   licenseText to generate the header which works fine for short
+    #   licenses like MIT but can be quite lengthy for other licenses
+    #   like BSD-4-Clause. The above default template is valid for most
+    #   licenses and is recommended for MIT, and BSD licenses. Common
+    #   licenses that work well with the auto_template feature are GPL
+    #   variants, and the Apache 2.0 license.
+    #
+    #   Important Note: this means the ident must be a valid SPDX identifier
+    # auto_template: true
+
+    #   If true try to detect the text wrapping of the template, and unwrap it
+    unwrap_text: false
+
+# Define type of comment characters to apply based on file extensions.
+comments:
+  # The extensions (or singular extension) field defines which file
+  # extensions to apply the commenter to.
+  - extensions:
+      - js
+      - go
+    # The commenter field defines the kind of commenter to
+    # generate. There are two types of commenters: line and block.
+    #
+    # This demonstrates a line commenter configuration. A line
+    # commenter type will apply the comment_char to the beginning of
+    # each line in the license header. It will then apply a number of
+    # empty newlines to the end of the header equal to trailing_lines.
+    #
+    # If trailing_lines is omitted it is assumed to be 0.
+    commenter:
+      type: line
+      comment_char: "//"
+      trailing_lines: 1
+
+  - extensions:
+      - rs
+      - tri
+      - css
+      - cpp
+      - c
+      - h
+    # This demonstrates a block commenter configuration. A block
+    # commenter type will add start_block_char as the first character
+    # in the license header and add end_block_char as the last character
+    # in the license header. If per_line_char is provided each line of
+    # the header between the block start and end characters will be
+    # line commented with the per_line_char
+    #
+    # trailing_lines works the same for both block and line commenter
+    # types
+    commenter:
+      type: block
+      start_block_char: "/*\n"
+      end_block_char: "*/\n"
+      per_line_char: "*"
+      trailing_lines: 1
+
+  - extension:
+      - html
+      - md
+    commenter:
+      type: block
+      start_block_char: "<!--\n"
+      end_block_char: "-->\n"
+      trailing_lines: 1
+
+  - extensions:
+      - el
+      - lisp
+    commenter:
+      type: line
+      comment_char: ";;;"
+      trailing_lines: 1
+
+  - extensions:
+      - tex
+      - bib
+    commenter:
+      type: line
+      comment_char: "%"
+      trailing_lines: 1
+
+  # The extension string "any" is special and so will match any file
+  # extensions. Commenter configurations are always checked in the
+  # order they are defined, so if any is used it should be the last
+  # commenter configuration or else it will override all others.
+  #
+  # In this configuration if we can't match the file extension we fall
+  # back to the popular '#' line comment used in most scripting
+  # languages.
+  - extension: any
+    commenter:
+      type: line
+      comment_char: '#'
+      trailing_lines: 1
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f429efe
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+# Beitragsordnung
+
+> Die Beitragsordnung
+
+## Licence
+
+All Rights Reserved.
diff --git a/beitragsordnung.tex b/beitragsordnung.tex
new file mode 100644
index 0000000..24cdb17
--- /dev/null
+++ b/beitragsordnung.tex
@@ -0,0 +1,42 @@
+% LTeX: language=en-GB
+%\documentclass[a4paper, 12pt, nosolutions]{report}
+% \documentclass[a4paper, 12pt, onecolumn]{report}
+\documentclass{article}
+
+\input{headers/preamble.tex}
+\input{headers/preamble_local.tex}
+
+\title{Beitragsordnung}
+\author{\Verein}
+
+\date{\DTMToday}
+
+% For the copyright section
+\years{2024}
+\authors{\Verein}
+
+\makeatletter
+\hypersetup{
+  pdftitle={\@title},
+  pdfsubject={},
+  pdfauthor={\@authors},
+  pdfkeywords={TODO},
+  colorlinks,
+  linkcolor={black},
+  citecolor={black},
+  urlcolor={blue!80!black}
+}
+\makeatother
+
+
+
+\begin{document}
+    \input{content/static/title}
+
+    % NEXT_CHAPTER
+
+    \clearpage{}
+		\todototoc
+		\listoftodos
+    \printbibliography\relax
+\end{document}
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..fcf2bff
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env sh
+
+# if no parameter is given, use 'dst' as destination directory
+if [ -z "$1" ]; then
+    dst=build
+else
+    dst="$1"
+fi
+
+# find all directories which are not the destination dir or inside it
+find . -type d -not -name "$dst" -not -path "./$dst/*" -printf '%P\n' | while IFS= read -r dir; do
+    mkdir --parents "$dst/$dir"
+done
+latexmk -outdir="$dst" -file-line-error -pdflatex -recorder "./beitragsordnung.tex"
diff --git a/content/static/title.tex b/content/static/title.tex
new file mode 100644
index 0000000..9cfd67e
--- /dev/null
+++ b/content/static/title.tex
@@ -0,0 +1,11 @@
+% LTeX: language=de-DE
+
+\maketitle
+\thispagestyle{empty}
+
+\clearpage
+\tableofcontents
+\thispagestyle{empty}
+\clearpage
+
+\setcounter{page}{1}
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..88b3634
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,207 @@
+{
+  "nodes": {
+    "crane": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1721842668,
+        "narHash": "sha256-k3oiD2z2AAwBFLa4+xfU+7G5fisRXfkvrMTCJrjZzXo=",
+        "owner": "ipetkov",
+        "repo": "crane",
+        "rev": "529c1a0b1f29f0d78fa3086b8f6a134c71ef3aaf",
+        "type": "github"
+      },
+      "original": {
+        "owner": "ipetkov",
+        "repo": "crane",
+        "type": "github"
+      }
+    },
+    "flake-compat": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1696426674,
+        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+        "type": "github"
+      },
+      "original": {
+        "owner": "edolstra",
+        "repo": "flake-compat",
+        "type": "github"
+      }
+    },
+    "flake-utils": {
+      "inputs": {
+        "systems": [
+          "systems"
+        ]
+      },
+      "locked": {
+        "lastModified": 1710146030,
+        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "flake_version_update": {
+      "inputs": {
+        "flake-utils": [
+          "flake-utils"
+        ],
+        "nixpkgs": [
+          "nixpkgs"
+        ],
+        "systems": [
+          "systems"
+        ]
+      },
+      "locked": {
+        "lastModified": 1685288691,
+        "narHash": "sha256-oP6h34oJ8rm6KlUpyZrX+ww3hnoWny2ecrEXxkU7F3c=",
+        "ref": "refs/heads/prime",
+        "rev": "e9a97e01eca780bd16e1dbdbd8856b59558f4959",
+        "revCount": 5,
+        "type": "git",
+        "url": "https://codeberg.org/soispha/flake_version_update.git"
+      },
+      "original": {
+        "type": "git",
+        "url": "https://codeberg.org/soispha/flake_version_update.git"
+      }
+    },
+    "lpm": {
+      "inputs": {
+        "crane": [
+          "crane"
+        ],
+        "flake-compat": [
+          "flake-compat"
+        ],
+        "flake-utils": [
+          "flake-utils"
+        ],
+        "nixpkgs": [
+          "nixpkgs"
+        ],
+        "rust-overlay": [
+          "rust-overlay"
+        ],
+        "systems": [
+          "systems"
+        ]
+      },
+      "locked": {
+        "lastModified": 1718253944,
+        "narHash": "sha256-22AP7h3Utx7xfJ7uyPWH2f6B6xFysCYgPQhNonTeEQ4=",
+        "ref": "refs/heads/prime",
+        "rev": "7ea10db20a83eedffd69a8c8824e14992ada3e10",
+        "revCount": 20,
+        "type": "git",
+        "url": "https://codeberg.org/bpeetz/lpm.git"
+      },
+      "original": {
+        "type": "git",
+        "url": "https://codeberg.org/bpeetz/lpm.git"
+      }
+    },
+    "nixpkgs": {
+      "locked": {
+        "lastModified": 1721782431,
+        "narHash": "sha256-UNDpwjYxNXQet/g3mgRLsQ9zxrbm9j2JEvP4ijF3AWs=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "4f02464258baaf54992debfd010a7a3662a25536",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixpkgs-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "root": {
+      "inputs": {
+        "crane": "crane",
+        "flake-compat": "flake-compat",
+        "flake-utils": "flake-utils",
+        "flake_version_update": "flake_version_update",
+        "lpm": "lpm",
+        "nixpkgs": "nixpkgs",
+        "rust-overlay": "rust-overlay",
+        "systems": "systems",
+        "treefmt-nix": "treefmt-nix"
+      }
+    },
+    "rust-overlay": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1721873995,
+        "narHash": "sha256-HyFmp6rktJQMxG+BZEjcQoCFKMek855Cc/dQk2YDac0=",
+        "owner": "oxalica",
+        "repo": "rust-overlay",
+        "rev": "33a7853f54f1797b029739297c4593bd96077c20",
+        "type": "github"
+      },
+      "original": {
+        "owner": "oxalica",
+        "repo": "rust-overlay",
+        "type": "github"
+      }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1680978846,
+        "narHash": "sha256-Gtqg8b/v49BFDpDetjclCYXm8mAnTrUzR0JnE2nv5aw=",
+        "owner": "nix-systems",
+        "repo": "x86_64-linux",
+        "rev": "2ecfcac5e15790ba6ce360ceccddb15ad16d08a8",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "x86_64-linux",
+        "type": "github"
+      }
+    },
+    "treefmt-nix": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1721769617,
+        "narHash": "sha256-6Pqa0bi5nV74IZcENKYRToRNM5obo1EQ+3ihtunJ014=",
+        "owner": "numtide",
+        "repo": "treefmt-nix",
+        "rev": "8db8970be1fb8be9c845af7ebec53b699fe7e009",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "treefmt-nix",
+        "type": "github"
+      }
+    }
+  },
+  "root": "root",
+  "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..208acde
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,126 @@
+{
+  description = "Die beitragsordnung";
+
+  inputs = {
+    nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+
+    treefmt-nix = {
+      url = "github:numtide/treefmt-nix";
+      inputs = {
+        nixpkgs.follows = "nixpkgs";
+      };
+    };
+    flake_version_update = {
+      url = "git+https://codeberg.org/soispha/flake_version_update.git";
+      inputs = {
+        systems.follows = "systems";
+        nixpkgs.follows = "nixpkgs";
+        flake-utils.follows = "flake-utils";
+      };
+    };
+    lpm = {
+      url = "git+https://codeberg.org/bpeetz/lpm.git";
+      inputs = {
+        nixpkgs.follows = "nixpkgs";
+        flake-compat.follows = "flake-compat";
+        flake-utils.follows = "flake-utils";
+        rust-overlay.follows = "rust-overlay";
+        crane.follows = "crane";
+        systems.follows = "systems";
+      };
+    };
+
+    # inputs for following
+    systems = {
+      url = "github:nix-systems/x86_64-linux"; # only evaluate for this system
+    };
+    flake-compat = {
+      url = "github:edolstra/flake-compat";
+      flake = false;
+    };
+    flake-utils = {
+      url = "github:numtide/flake-utils";
+      inputs = {
+        systems.follows = "systems";
+      };
+    };
+    crane = {
+      url = "github:ipetkov/crane";
+      inputs = {
+        nixpkgs.follows = "nixpkgs";
+      };
+    };
+    rust-overlay = {
+      url = "github:oxalica/rust-overlay";
+      inputs = {
+        nixpkgs.follows = "nixpkgs";
+        flake-utils.follows = "flake-utils";
+      };
+    };
+  };
+
+  outputs = {
+    self,
+    nixpkgs,
+    flake-utils,
+    treefmt-nix,
+    lpm,
+    flake_version_update,
+    ...
+  }:
+    flake-utils.lib.eachDefaultSystem (system: let
+      pkgs = nixpkgs.legacyPackages.${system};
+
+      # This version is set automatically on `cog bump --auto`;
+      version = "v0.1.0"; # GUIDING VERSION STRING
+
+      # TODO reduce to the needed ones
+      texlive = pkgs.texlive.combined.scheme-full;
+
+      treefmtEval = import ./treefmt.nix {inherit treefmt-nix pkgs;};
+
+      build = pkgs.stdenv.mkDerivation {
+        pname = "beitragsordnung";
+        inherit version;
+        src = ./.;
+
+        buildInputs = [
+          texlive
+        ];
+
+        # Run local
+        preferLocalBuild = true;
+        allowSubstitutes = false;
+
+        buildPhase = ''
+          # TODO: I have no idea, why calling it with `./build.sh` does not work <2024-03-20>
+          bash ./build.sh
+        '';
+
+        installPhase = ''
+          install -D ./build/beitragsordnung.pdf "$out/beitragsordnung.pdf";
+        '';
+      };
+    in {
+      packages.default = build;
+
+      checks = {
+        inherit build;
+        formatting = treefmtEval.config.build.check self;
+      };
+
+      formatter = treefmtEval.config.build.wrapper;
+
+      devShells.default = pkgs.mkShell {
+        packages = with pkgs; [
+          cocogitto
+          licensure
+          flake_version_update.packages."${system}".default
+          lpm.packages."${system}".default
+          texlive
+
+          zathura
+        ];
+      };
+    });
+}
diff --git a/headers/preamble.tex b/headers/preamble.tex
new file mode 100644
index 0000000..77c0461
--- /dev/null
+++ b/headers/preamble.tex
@@ -0,0 +1,291 @@
+% This preamble assumes pdflatex
+% derived from:
+% https://github.com/gillescastel/lecture-notes/blob/929672a96abc27eaeb6fa58b1d277b3582d28532/group-theory/preamble.tex
+% encodings
+\usepackage[utf8]{inputenc} % use utf8 encoding
+\usepackage[T1]{fontenc} % for 8bit font support
+\usepackage{lmodern} % latin modern fonts, should be better than ae, aecompl
+% \usepackage{ae,aecompl} % full T1 font support
+% \usepackage{textcomp} % support for yen and so on, not needed since latex2e(2020)
+
+% references
+\usepackage[ngerman]{babel} % For English language support, with reformed orthography!
+% \usepackage[brithish]{babel} % For English language support, with reformed orthography!
+\usepackage{csquotes} % required by biblatex
+% \usepackage{biber} % required by biblatex
+
+% \usepackage{biblatex-dw}
+\usepackage[backend=biber,
+        style=footnote-dw,
+        %
+        pageref=true,
+        annotation=true,
+        library=true,
+        %
+        % style=numeric,
+        autocite=superscript,
+        % FIXME: Keep this here? <2024-03-20>
+        doi=true,
+        isbn=true,
+        loccittracker=true,
+        opcittracker=true
+    ]{biblatex} % For bibtex references
+\addbibresource{resources/reference.bib}
+% \renewcommand{\autocite}[1]{\footcite{#1}\supercite{#1}}
+% \bibliography{res/reference} % Set the location of the references
+
+% dates, time
+\usepackage[de-DE, showdow]{datetime2} % make handling dates easier
+
+% index
+% \usepackage{index} % Helps to create an index TODO compare with other such packages
+% \makeindex
+
+% math
+\usepackage{amsmath}  % extensive math commands
+\usepackage{amsfonts} % more fonts for math (fracture, boldfaced and so on)
+\usepackage{mathtools} % extension to amsmath, with more sensible defaults (eq numbers only when referenced)
+\usepackage{amssymb} % more symbols, mostly redundant because already loaded by something else
+\usepackage{mathrsfs} % support for the RSFS fonts (through \mathscr command)
+\usepackage{cancel} % allows to cancel a part in math mode, for example to shorten a term
+\usepackage{bm} % bold mode in math, but better than \boldsymbol command from ams. \bm
+\usepackage[locale = DE]{siunitx} % For easy unit representation
+\sisetup{per-mode = fraction}
+\usepackage[version=4]{mhchem} % for \ce command
+
+
+
+% graphics and floats
+\usepackage{float} % makes dealing with floats easier
+\usepackage{graphicx} % allows for easy inclusion of graphics
+\usepackage[shortlabels]{enumitem} % makes enumerate, itemize and description better
+\usepackage{wrapfig} % Wraps text around figures with the \wrapfigure environment
+\usepackage[dvipsnames]{xcolor} % colors and color mixing \color{red!30!green!40!blue}
+\usepackage{pgfplots} % plots, 2D and 3D
+\pgfplotsset{compat=1.18} % use version 1.13
+\usepackage{tikz} % Nice drawn graphics, for library see: https://tex.stackexchange.com/a/42664
+% \usetikzlibrary{intersections, angles, quotes, calc, positioning}
+% \usetikzlibrary{arrows.meta} %TODO maybe deprecated?
+% \usepackage{tikz-cd} % better commutative diagrams
+% \usepackage{subcaption} % like caption package, but for subfigures
+% \usepackage{booktabs} % better tables
+
+
+% visuals
+\usepackage{fancyhdr}  % Text layout and margins, headers so on
+\usepackage{microtype} % makes text better to read
+\usepackage{multicol} % allows for multi-columns everywhere, with the "multicols" environment
+\usepackage{emptypage} % no page numbers and headings on empty pages
+% \usepackage[a4paper, left=2cm, right=2cm, top=2cm, bottom=2cm]{geometry} % For nice margins
+% \usepackage{xspace} % Adds a space when it thinks it is necessary
+\usepackage{blindtext} % blindtext
+
+% tikz style config
+\tikzset{help_lines/.style={step=.5cm,gray!50,very thin}}
+
+% notes
+% \usepackage{todonotes}
+
+% links
+% \usepackage[hidelinks]{hyperref} % Links in the pdf
+\usepackage[nospace]{varioref}
+\usepackage[pdflang=de-DE]{hyperref}
+% \hypersetup{
+%         colorlinks,
+%         linkcolor={black},
+%         citecolor={black},
+%         urlcolor={blue!80!black}
+%     }
+
+
+% \usepackage{stmaryrd} % for \lightning
+% \newcommand\contra{\scalebox{1.1}{$\lightning$}}
+
+% number sets
+\newcommand\N{\ensuremath{\mathbb{N}}}
+\newcommand\R{\ensuremath{\mathbb{R}}}
+\newcommand\Z{\ensuremath{\mathbb{Z}}}
+\newcommand\Q{\ensuremath{\mathbb{Q}}}
+\newcommand\C{\ensuremath{\mathbb{C}}}
+\renewcommand\O{\ensuremath{\emptyset}} % replaces the Ø
+
+% readable limits
+\let\svlim\lim{}
+\renewcommand\lim{\svlim\limits}
+
+% aliases
+\let\implies\Rightarrow{}
+\let\impliedby\Leftarrow{}
+\let\iff\Leftrightarrow{}
+
+\renewcommand\epsilon{\varepsilon} % I like the textual epsilon more
+% \renewcommand\phi{\varphi}
+
+% horizontal rule
+\newcommand\hr{
+        \par\noindent\rule[0.5ex]{\linewidth}{0.5pt}
+    }
+
+% copyright:
+\makeatletter
+\DeclareRobustCommand\authors[1]{\gdef\@authors{#1}}
+\DeclareRobustCommand\years[1]{\gdef\@years{#1}}
+\makeatother
+
+% theorems
+% packages:
+\usepackage[framemethod=TikZ]{mdframed}
+\mdfsetup{skipabove=1em,skipbelow=0em, innertopmargin=5pt, innerbottommargin=6pt}
+\usepackage{amsthm}  % math commands for theorems
+\usepackage{thmtools} % improved theorems
+\usepackage{environ} % for hiding of the solution env
+
+% styles:
+% \renewcommand\qedsymbol{\ensuremath{\text{\textit{O.}}~\epsilon.~\delta.}}
+\renewcommand\qedsymbol{\dots}
+\theoremstyle{definition}
+\declaretheoremstyle[
+        headfont=\bfseries\sffamily\color{NavyBlue!80},
+        bodyfont=\normalfont,
+        headpunct={:\\},
+        qed=\qedsymbol,
+        mdframed={
+                linewidth=2pt,
+                rightline=false, topline=false, bottomline=false,
+                linecolor=NavyBlue, backgroundcolor=NavyBlue!5,
+            },
+    ]{thmexample}
+\declaretheoremstyle[
+        headfont=\bfseries\sffamily\color{RawSienna!80},
+        bodyfont=\normalfont,
+        headpunct={:\\},
+        qed=\qedsymbol,
+        mdframed={
+                linewidth=2pt,
+                rightline=false, topline=false, bottomline=false,
+                linecolor=RawSienna, backgroundcolor=RawSienna!5,
+            },
+    ]{thmexercise}
+\declaretheoremstyle[
+        headfont=\bfseries\sffamily\color{Violet!80},
+        bodyfont=\normalfont,
+        headpunct={:\\},
+        notebraces={f\"ur }{},
+        qed=\qedsymbol,
+        mdframed={
+                linewidth=2pt,
+                rightline=false, topline=false, bottomline=false,
+                linecolor=Violet, backgroundcolor=Violet!5,
+            },
+    ]{thmsolution}
+\declaretheoremstyle[
+        headfont=\bfseries\sffamily\color{ForestGreen!80},
+        bodyfont=\normalfont,
+        headpunct={:\\},
+        qed=\qedsymbol,
+        mdframed={
+                linewidth=2pt,
+                rightline=false, topline=false, bottomline=false,
+                linecolor=ForestGreen, backgroundcolor=ForestGreen!5,
+            },
+    ]{thmdef}
+\declaretheoremstyle[
+        headfont=\bfseries\sffamily\color{RawSienna!70!black},
+        bodyfont=\normalfont,
+        headpunct={:\\},
+        qed=\qedsymbol,
+        mdframed={
+                linewidth=2pt,
+                leftline=false, rightline=true, topline=false, bottomline=false,
+                linecolor=RawSienna, backgroundcolor=Red!5,
+            }
+    ]{thmtheorem}
+
+\declaretheorem[numbered=yes, style=thmdef, name=Definition]{definition}
+\declaretheorem[numbered=no, style=thmexample,name=Beispiel]{eg}
+\declaretheorem[numbered=no, style=thmexercise, name=Aufgabe]{ex}
+\declaretheorem[numbered=yes, style=thmtheorem, name=Satz]{theorem}
+% \declaretheorem[style=thmredbox, name=Proposition]{prop}
+% \declaretheorem[style=thmredbox, name=Lemma]{lemma}
+% \declaretheorem[style=thmredbox, numbered=no, name=Corollary]{corollary}
+
+% Solutions
+\makeatletter
+\@ifclasswith{report}{nosolutions}
+    {%
+        \NewEnviron{solution}[1][]{Eine L\"osung mit dem Name ("L\"osung für #1") wurde versteckt.\ \\ \par}
+        \newcommand\hdsolution[1]{L\"osung versteckt}
+    }{%
+        \declaretheorem[numbered=no, style=thmsolution, name=L\"osung]{replacementSolution}
+
+        \NewEnviron{solution}[1][]{
+            \vspace{-1em}
+            \begin{replacementSolution}[#1]
+            \
+            \BODY
+            \end{replacementSolution}
+        }
+        \newcommand\hdsolution[1]{#1}
+    }
+\makeatother
+
+\DTMnewdatestyle{margindate}{
+        \renewcommand*\DTMdisplaydate[4]{
+                \MakeLowercase{\DTMshortweekdayname{##4}}\space
+                \number##3\relax\space
+                \MakeLowercase{\DTMshortmonthname{##2}}\space
+                \DTMtwodigits{\DTMtwodigits{##1}}
+            }
+        \renewcommand*\DTMDisplaydate[4]{
+                \DTMshortweekdayname{##4}\space
+                ##3\space
+                \DTMshortmonthname{##2}\space
+                \DTMtwodigits{\DTMtwodigits{##1}}
+            }
+    }
+
+\newcommand*\margindate[1]{
+        \DTMsetdatestyle{margindate}
+        \marginpar{
+                \small\textsf{\mbox{\DTMDate{#1}}}
+            }\relax
+    }
+
+\def\@lesson{}%
+\newcommand{\lesson}[3]{
+        \if\relax\detokenize{#3}\relax
+            \def\@lesson{Unterricht: #1}%
+        \else
+            % \def\@lesson{Unterricht #1: #3}%
+            \def\@lesson{#1: #3}%
+        \fi
+        \subsection*{\@lesson}
+        \margindate{#2}
+    }
+
+% \pagestyle{fancy}
+% \fancyhf{}
+% \fancyhead[LE, RO]{}
+% \fancyhead[RO, LE]{\@lesson}
+% \fancyhead[RE, LO]{}
+% \fancyfoot[LE, RO]{\thepage}
+% \fancyfoot[C]{\leftmark}
+
+
+% Parameters
+% \renewcommand{\sfdefault}{ptm}
+% \pagenumbering{arabic}
+% \setcounter{page}{2}
+% \renewcommand{\thesection}{\Roman{section}}
+% \renewcommand{\thesubsection}{\thesection.\Roman{subsection}}
+%
+
+%% Footers and Headers
+%\pagestyle{fancy}
+%\fancyhf{}
+%\renewcommand{\headrulewidth}{2pt}
+%\renewcommand{\footrulewidth}{1pt}
+%\renewcommand{\baselinestretch}{1.5}
+%\fancyhead[L]{{\textbf{\titleset}}}
+%\fancyhead[R]{\textbf{\course}}
+%\fancyfoot[L]{\thepage}
diff --git a/headers/preamble_local.tex b/headers/preamble_local.tex
new file mode 100644
index 0000000..cfbc404
--- /dev/null
+++ b/headers/preamble_local.tex
@@ -0,0 +1,50 @@
+\usepackage{titlesec}
+\usepackage{titletoc}
+\usepackage[german]{todonotes}
+
+\titleformat
+{\section}
+{\normalfont\Large\bfseries}
+{\S \thesection}
+{1em}
+{}
+
+\titlecontents{section}
+[0em]
+{}
+{\contentslabel[\S\hspace{0.2em}\thecontentslabel]{2.3em}}
+{\hspace{-2.3em}}
+{\titlerule*[1pc]{.}\contentspage}
+
+\usepackage{nag}
+
+\NewDocumentCommand{\Verein}{}{<Vereinsname>}
+
+\NewDocumentCommand{\sils}{O{} m}{
+	\todo[color=green!35, #1]{Silas: #2}
+}
+\NewDocumentCommand{\bpeetz}{O{} m}{
+	\todo[color=blue!35, #1]{Benedikt: #2}
+}
+
+\newcounter{para}
+
+\NewDocumentCommand{\paracount}{}{
+	\stepcounter{para}
+	\paragraph{(\arabic{para})}
+}
+
+\NewDocumentCommand{\sectionc}{sm}{
+	\IfBooleanTF#1
+	{
+		\section*{#2}
+		\setcounter{para}{0}
+	}
+	{
+		\section{#2}
+		\setcounter{para}{0}
+	}
+}
+
+\usepackage{enumitem} % For the enumerations with letters
+
diff --git a/lpm.toml b/lpm.toml
new file mode 100644
index 0000000..858fcf1
--- /dev/null
+++ b/lpm.toml
@@ -0,0 +1,16 @@
+main_file = "beitragsordnung.tex"
+
+[templates]
+section = '''
+%! TEX root = ../../../beitragsordnung.tex
+% LTeX: language=de-DE
+
+\paracount{} % "REPLACMENT_SECTION_TITLE" DATE
+Dies ist ein paragraph
+'''
+chapter = '''
+%! TEX root = ../../beitragsordnung.tex
+% LTeX: language=de-DE
+
+\sectionc{REPLACEMENT_CHAPTER}
+'''
diff --git a/references/reference.bib b/references/reference.bib
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/references/reference.bib
diff --git a/scripts/extract_text_from_all.sh b/scripts/extract_text_from_all.sh
new file mode 100755
index 0000000..ad0af07
--- /dev/null
+++ b/scripts/extract_text_from_all.sh
@@ -0,0 +1,8 @@
+#! /usr/bin/env sh
+
+grep 'INPUT ./' ./build/beitragsordnung.fls | uniq | sed 's/INPUT //' | while read -r file; do
+    if ! [ "$(basename "$file")" = preamble.tex ] && ! [ "$(basename "$file")" = gymnasium.png ]; then
+        printf "\n%% Filename: %s\n" "$file"
+        grep -v '^\s*%' "$file"
+    fi
+done
diff --git a/treefmt.nix b/treefmt.nix
new file mode 100644
index 0000000..794e8fc
--- /dev/null
+++ b/treefmt.nix
@@ -0,0 +1,70 @@
+{
+  treefmt-nix,
+  pkgs,
+}:
+treefmt-nix.lib.evalModule pkgs (
+  {pkgs, ...}: {
+    # Used to find the project root
+    projectRootFile = "flake.nix";
+
+    programs = {
+      alejandra.enable = true;
+      rustfmt.enable = true;
+      clang-format.enable = true;
+      mdformat.enable = true;
+      shfmt = {
+        enable = true;
+        indent_size = 4;
+      };
+      shellcheck.enable = true;
+      prettier = {
+        enable = true;
+        settings = {
+          arrowParens = "always";
+          bracketSameLine = false;
+          bracketSpacing = true;
+          editorconfig = true;
+          embeddedLanguageFormatting = "auto";
+          endOfLine = "lf";
+          # experimentalTernaries = false;
+          htmlWhitespaceSensitivity = "css";
+          insertPragma = false;
+          jsxSingleQuote = true;
+          printWidth = 80;
+          proseWrap = "always";
+          quoteProps = "consistent";
+          requirePragma = false;
+          semi = true;
+          singleAttributePerLine = true;
+          singleQuote = false;
+          trailingComma = "all";
+          useTabs = false;
+          vueIndentScriptAndStyle = false;
+
+          tabWidth = 2;
+        };
+      };
+      stylua.enable = true;
+      ruff = {
+        enable = true;
+        format = true;
+      };
+      taplo.enable = true;
+    };
+
+    settings = {
+      global.excludes = [
+        "CHANGELOG.md"
+        "NEWS.md"
+      ];
+      formatter = {
+        clang-format = {
+          options = ["--style" "GNU"];
+        };
+        shfmt = {
+          includes = ["*.bash"];
+        };
+      };
+    };
+  }
+)
diff --git a/update.sh b/update.sh
new file mode 100755
index 0000000..49216b8
--- /dev/null
+++ b/update.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env sh
+
+nix flake update
diff --git a/watch.sh b/watch.sh
new file mode 100755
index 0000000..ba5c1b9
--- /dev/null
+++ b/watch.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+sleeptime=${1-10}
+
+while true; do
+    ./build.sh
+    sleep "$sleeptime"
+done