diff --git a/packages/preview/supercharged-dhbw/3.4.1/CHANGELOG.md b/packages/preview/supercharged-dhbw/3.4.1/CHANGELOG.md
new file mode 100644
index 000000000..870916cdc
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/CHANGELOG.md
@@ -0,0 +1,142 @@
+# Supercharged-DHBW Changelog
+
+## [v3.4.1] - 2025-01-07
+
+- Fix error that page numbering style is not applied to the table of contents
+- Improve docs
+
+## [v3.4.0] - 2024-12-08
+
+- Fix inconsistency in the header spacing
+- Add option to provide the page numbering style
+- Update some descriptions in the documentation
+
+## [v3.3.2] - 2024-11-02
+
+- Fix typo in declaration of authorship
+
+## [v3.3.1] - 2024-10-03
+
+- Fix expect company attribute in author if `at-university` is true
+
+## [v3.3.0] - 2024-09-20
+
+- Display current chapter in the header instead of the title
+
+## [v3.2.0] - 2024-09-16
+
+- Remove double space in confidentiality statement
+- Add argument to provide keys that are ignored when highlighting links
+- Remove unnecessary argument `show-appendix`
+
+## [v3.1.1] - 2024-08-26
+
+- Update declaration of authorship text to match the new DHBW requirements
+
+## [v3.1.0] - 2024-08-20
+
+- Fix typo in readme and improve contents
+- Add attribute `titlepage-content` to create a custom titlepage
+- Add attribute `math-numbering` to change the numbering style of math equations
+- Fix typo in german confidentiality statement
+- Reorder outlines and abstract
+- Add glossary support
+- Improve code and language handling
+- Fix error when no acronyms are provided
+- Add more examples to the documentation
+
+## [v3.0.0] - 2024-08-08
+
+- Combine header settings in a dictionary (breaking change)
+- Move abstract in front of the outlines
+- Refactor language handling
+- Smaller improvements to the code readability
+- Provide more examples
+- Attribute to provide a custom declaration of authorship
+
+## [v2.2.0] - 2024-07-29
+
+- Change default heading numbering to `1.1`
+- Add attribute to provide a heading numbering
+- Add attribute `university-short` to allow other universities except DHBW
+- Add attribute to provide a custom header
+
+## [v2.1.0] - 2024-07-19
+
+- Add confidentiality marker attribute
+- Add header configuration options
+-> Show title in header
+-> Show left logo in header
+-> Show right logo in header
+-> Show header divider
+
+## [v2.0.2] - 2024-07-04
+
+- Display plural text in the declaration of authorship if the document has multiple authors
+
+## [v2.0.1] - 2024-07-04
+
+- Update and fix errors in docs
+- Remove english version of the declaration of authorship as a german one is mandatory even for english projects
+
+## [v2.0.0] - 2024-07-02
+
+- Rename argument `at-dhbw` to `at-university`
+- Add argument `city` to provide a city when no company is provided
+- Add the option to provide a supervisor for the company and university
+- Add `bib-style` argument
+- Add an argument to provide custom confidentiality statement content
+- Fix acronym linebreak bug
+
+## [v1.5.0] - 2024-06-24
+
+- Highlight links in blue
+- Link acronyms to definitions
+- Add option to define space between acronyms and there long versions
+- Improve user feedback with error messages
+- Remove optional arguments from main.typ template file
+- Improve docs
+- Improve spacing for many authors
+- Change naming of `studiengang` to `kurs`
+- Add `type-of-thesis` attribute
+- Add `type-of-degree` attribute
+- Make `acronyms` attribute optional
+- Add acronym usage docs
+- Add option to provide date range instead of one date
+- Add attribute to specify the date format
+
+## [v1.4.0] - 2024-06-10
+
+- Fix typo on titlepage
+- Improve header spacing
+- Use alphabetical numbering for references and appendix pages
+- Remove the numbering style option from the template
+- Add option to change the toc depth
+
+## [v1.3.1] - 2024-05-27
+
+- Don't display list of tables when empty
+- Don't display code snippets list when empty
+- Improve spacing for many authors (>4)
+- Improve paragraph spacing
+
+## [v1.3.0] - 2024-05-23
+
+- Fix `supervisor` on titlepage is missing when `at-dhbw` option is true
+- Fix confidentiality statement page is empty instead of hidden when at-dhbw option is true
+- Fix a bug the prevented the appendix content to update
+- Fix and refactor acronym usage
+- Fix missing translation and typo in declaration of authorship
+- Refactor usage of abstract and appendix
+
+## [v1.2.0] - 2024-05-16
+
+- Fix bug that `course-of-studies` is displayed twice even if similar
+- Fix bug where title text is not semibold
+- Add option to hide page headder
+- Add option to provide numbering style
+- Add option to change numbering alignment
+
+## [v1.0.0] - 2024-05-14
+
+- Initial release
diff --git a/packages/preview/supercharged-dhbw/3.4.1/LICENSE b/packages/preview/supercharged-dhbw/3.4.1/LICENSE
new file mode 100644
index 000000000..666b7f0ee
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 Danny Seidel
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/packages/preview/supercharged-dhbw/3.4.1/README.md b/packages/preview/supercharged-dhbw/3.4.1/README.md
new file mode 100644
index 000000000..414c4c51c
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/README.md
@@ -0,0 +1,248 @@
+# Supercharged DHBW
+
+Unofficial [Typst](https://typst.app/) template for DHBW students.
+
+You can see an example PDF of how the template looks [here](https://github.com/DannySeidel/typst-dhbw-template/blob/main/examples/example.pdf).
+
+To see an example of how you can use this template, check out the `main.typ` file.
+More examples can be found in the [examples directory](https://github.com/DannySeidel/typst-dhbw-template/blob/main/examples) of the GitHub repository.
+
+## Usage
+
+You can use this template in the Typst web app by clicking "Start from template" on the dashboard and searching for `supercharged-dhbw`.
+
+Alternatively, you can use the CLI to kick this project off using the command
+
+```shell
+typst init @preview/supercharged-dhbw
+```
+
+Typst will create a new directory with all the files needed to get you started.
+
+## Fonts
+
+This template uses the following fonts:
+
+- [Montserrat](https://fonts.google.com/specimen/Montserrat)
+- [Open Sans](https://fonts.google.com/specimen/Open+Sans)
+
+If you want to use typst locally, you can download the fonts from the links above and install them on your system.
+Otherwise, when using the web version add the fonts to your project.
+
+For further information on how to add fonts to your project, please refer to the [Typst documentation](https://typst.app/docs/reference/text/text/#parameters-font).
+
+## Used Packages
+
+This template uses the following packages:
+
+- [codelst](https://typst.app/universe/package/codelst): To create code snippets
+
+Insert code snippets using the following syntax:
+
+```typ
+#figure(caption: "Codeblock Example", sourcecode[```ts
+const ReactComponent = () => {
+ return (
+
+
Hello World
+
+ );
+};
+
+export default ReactComponent;
+```])
+```
+
+## Configuration
+
+This template exports the `supercharged-dhbw` function with the following named arguments:
+
+`title (str*)`: Title of the document
+
+`authors (dictionary*)`: List of authors with the following named arguments (max. 6 authors when in the company or 8 authors when at university):
+
+- name (str*): Name of the author
+- student-id (str*): Student ID of the author
+- course (str*): Course of the author
+- course-of-studies (str*): Course of studies of the author
+- company (dictionary): Company of the author (only needed when `at-university` is `false`) with the following named arguments:
+ - name (str*): Name of the company
+ - post-code (str): Post code of the company
+ - city (str*): City of the company
+ - country (str): Country of the company
+
+`abstract (content)`: Content of the abstract, it is recommended that you pass a variable containing the content or a function that returns the content
+
+`acronym-spacing (length)`: Spacing between the acronym and its long form (check the [Typst documentation](https://typst.app/docs/reference/layout/length/) for examples on how to provide parameters of type length), default is `5em`
+
+`acronyms (dictionary)`: Pass a dictionary containing the acronyms and their long forms (See the example in the `acronyms.typ` file)
+
+`appendix (content)`: Content of the appendix, it is recommended that you pass a variable containing the content or a function that returns the content
+
+`at-university (bool*)`: Whether the document is written at university or not, default is `false`
+
+`bibliography (content)`: The bibliography function containing a path to the bibliography file (e.g. `bibliography("path/to/bibliography.bib")`)
+
+`bib-style (str)`: Style of the bibliography, default is `ieee`
+
+`city (str)`: City of the author (only needed when `at-university` is `true`)
+
+`confidentiality-marker: (dictionary)`: Configure the confidentially marker (red or green circle) on the title page (using this option reduces the maximum number of authors by 2 to 4 authors when in the company or 6 authors when at university)
+
+- display (bool*): Whether the confidentiality marker should be shown, default is `false`
+- offset-x (length): Horizontal offset of the confidentiality marker, default is `0pt`
+- offset-y (length): Vertical offset of the confidentiality marker, default is `0pt`
+- size (length): Size of the confidentiality marker, default is `7em`
+- title-spacing (length): Adds space below the title to make room for the confidentiality marker, default is `2em`
+
+`confidentiality-statement-content (content)`: Provide a custom confidentiality statement
+
+`date (datetime* | array*)`: Provide a datetime object to display one date (e.g. submission date) or a array containing two datetime objects to display a date range (e.g. start and end date of the project), default is `datetime.today()`
+
+`date-format (str)`: Format of the displayed dates, default is `"[day].[month].[year]"` (for more information on possible formats check the [Typst documentation](https://typst.app/docs/reference/foundations/datetime/#format))
+
+`declaration-of-authorship-content (content)`: Provide a custom declaration of authorship
+
+`glossary (dictionary)`: Pass a dictionary containing the glossary terms and their definitions (See the example in the `glossary.typ` file)
+
+`glossary-spacing (length)`: Spacing between the glossary term and its definition (check the [Typst documentation](https://typst.app/docs/reference/layout/length/) for examples on how to provide parameters of type length), default is `1.5em`
+
+`header (dictionary)`: Configure the header of the document
+
+- display (bool): Whether the header should be shown, default is `true`
+- show-chapter (bool): Whether the current chapter should be shown in the header, default is `true`
+- show-left-logo (bool): Whether the left logo should be shown in the header, default is `true`
+- show-right-logo (bool): Whether the right logo should be shown in the header, default is `true`
+- show-divider (bool): Whether the header divider should be shown, default is `true`
+- content (content): Content for a custom header, it is recommended that you pass a variable containing the content or a function that returns the content
+
+`heading-numering (str)`: Numbering style of the headings, default is `"1.1"` (for more information on possible numbering formats check the [Typst documentation](https://typst.app/docs/reference/model/numbering))
+
+`ignored-link-label-keys-for-highlighting (array)`: List of keys of labels that should be ignored when highlighting links in the document, default is `()`
+
+`language (str*)`: Language of the document which is either `en` or `de`, default is `en`
+
+`logo-left (content)`: Path to the logo on the left side of the title page (usage: image("path/to/image.png")), default is the `DHBW logo`
+
+`logo-right (content)`: Path to the logo on the right side of the title page (usage: image("path/to/image.png")), default is `no logo`
+
+`logo-size-ratio (str)`: Ratio between the right logo and the left logo height (left-logo:right-logo), default is `"1:1"`
+
+`math-numbering (str)`: Numbering style of the math equations, set to `none` to turn off equation numbering, default is `"(1)"` (for more information on possible numbering formats check the [Typst documentation](https://typst.app/docs/reference/model/numbering))
+
+`numbering-alignment (alignment)`: Alignment of the page numbering (for possible options check the [Typst documentation](https://typst.app/docs/reference/layout/alignment/)), default is `center`
+
+`page-numbering (dictionary)`: Configure the page numbering for the three sections (e.g. `page-numbering: (preface: "I", main: "1 / 1", appendix: "a")`)
+
+- preface (str): Page numbering for the preface, default is `I`
+- main (str): Page numbering for the main part, default is `1 / 1`
+- appendix (str): Page numbering for the appendix, default is `a`
+
+`show-abstract (bool)`: Whether the abstract should be shown, default is `true`
+
+`show-acronyms (bool)`: Whether the list of acronyms should be shown, default is `true`
+
+`show-code-snippets (bool)`: Whether the code snippets should be shown, default is `true`
+
+`show-confidentiality-statement (bool)`: Whether the confidentiality statement should be shown, default is `true`
+
+`show-declaration-of-authorship (bool)`: Whether the declaration of authorship should be shown, default is `true`
+
+`show-list-of-figures (bool)`: Whether the list of figures should be shown, default is `true`
+
+`show-list-of-tables (bool)`: Whether the list of tables should be shown, default is `true`
+
+`show-table-of-contents (bool)`: Whether the table of contents should be shown, default is `true`
+
+`supervisor (dictionary*)`: Name of the supervisor at the university and/or company (e.g. `supervisor: (company: "John Doe", university: "Jane Doe")`)
+
+- company (str): Name of the supervisor at the company (note while the argument is optional at least one of the two arguments must be provided)
+- university (str): Name of the supervisor at the university (note while the argument is optional at least one of the two arguments must be provided)
+
+`titlepage-content (content)`: Provide a custom title page
+
+`toc-depth (int)`: Depth of the table of contents, default is `3`
+
+`type-of-thesis (str)`: Type of the thesis, default is `none` (using this option reduces the maximum number of authors by 2 to 4 authors when in the company or 6 authors when at university)
+
+`type-of-degree (str)`: Type of the degree, default is `none` (using this option reduces the maximum number of authors by 2 to 4 authors when in the company or 6 authors when at university)
+
+`university (str*)`: Name of the university
+
+`university-location (str*)`: Campus or city of the university
+
+`university-short (str*)`: Short name of the university (e.g. `DHBW`), displayed for the university supervisor
+
+Behind the arguments the type of the value is given in parentheses. All arguments marked with `*` are required.
+
+## Acronyms
+
+This template provides functions to reference acronyms in the text. To use these functions, you need to define the acronyms in the `acronyms` attribute of the template.
+The acronyms referenced with the functions below will be linked to their definition in the list of acronyms.
+
+### Functions
+
+This template provides the following functions to reference acronyms:
+
+`acr`: Reference an acronym in the text (e.g. `acr("API")` -> `Application Programming Interface (API)` or `API`)
+
+`acrpl`: Reference an acronym in the text in plural form (e.g. `acrpl("API")` -> `Application Programming Interfaces (API)` or `APIs`)
+
+`acrs`: Reference an acronym in the text in short form (e.g. `acrs("API")` -> `API`)
+
+`acrspl`: Reference an acronym in the text in short form in plural form (e.g. `acrpl("API")` -> `APIs`)
+
+`acrl`: Reference an acronym in the text in long form (e.g. `acrl("API")` -> `Application Programming Interface`)
+
+`acrlpl`: Reference an acronym in the text in long form in plural form (e.g. `acrlpl("API")` -> `Application Programming Interfaces`)
+
+`acrf`: Reference an acronym in the text in full form (e.g. `acrf("API")` -> `Application Programming Interface (API)`)
+
+`acrfpl`: Reference an acronym in the text in full form in plural form (e.g. `acrfpl("API")` -> `Application Programming Interfaces (API)`)
+
+### Definition
+
+To define acronyms use a dictionary and pass it to the acronyms attribute of the template.
+The dictionary should contain the acronyms as keys and their long forms as values.
+
+```typst
+#let acronyms = (
+ API: "Application Programming Interface",
+ HTTP: "Hypertext Transfer Protocol",
+ REST: "Representational State Transfer",
+)
+```
+
+To define the plural form of an acronym use a array as value with the first element being the singular form and the second element being the plural form.
+If you don't define the plural form, the template will automatically add an "s" to the singular form.
+
+```typst
+#let acronyms = (
+ API: ("Application Programming Interface", "Application Programming Interfaces"),
+ HTTP: ("Hypertext Transfer Protocol", "Hypertext Transfer Protocols"),
+ REST: ("Representational State Transfer", "Representational State Transfers"),
+)
+```
+
+## Glossary
+
+Similar to the acronyms, this template provides a function to reference glossary terms in the text. To use the function, you need to define the glossary terms in the `glossary` attribute of the template.
+The glossary terms referenced with the function below will be linked to their definition in the list of glossary terms.
+
+### Reference
+
+`gls`: Reference a glossary term in the text (e.g. `gls("Vulnerability")` -> link to the definition of "Vulnerability" in the glossary)
+
+### Definition
+
+The definition works analogously to the acronyms.
+Define the glossary terms in a dictionary and pass it to the glossary attribute of the template.
+The dictionary should contain the glossary terms as keys and their definitions as values.
+
+```typst
+#let glossary = (
+ Vulnerability: "A Vulnerability is a flaw in a computer system that weakens the overall security of the system.",
+ Patch: "A patch is data that is intended to be used to modify an existing software resource such as a program or a file, often to fix bugs and security vulnerabilities.",
+ Exploit: "An exploit is a method or piece of code that takes advantage of vulnerabilities in software, applications, networks, operating systems, or hardware, typically for malicious purposes.",
+)
+```
diff --git a/packages/preview/supercharged-dhbw/3.4.1/acronym-lib.typ b/packages/preview/supercharged-dhbw/3.4.1/acronym-lib.typ
new file mode 100644
index 000000000..ee2274710
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/acronym-lib.typ
@@ -0,0 +1,126 @@
+#import "locale.typ": ACRONYMS
+#import "shared-lib.typ": display, display-link, is-in-dict
+
+#let prefix = "acronym-state-"
+#let acros = state("acronyms", none)
+
+#let init-acronyms(acronyms) = {
+ acros.update(acronyms)
+}
+
+
+#let acrs(acr, plural: false, link: true) = {
+ if plural {
+ display("acronyms", acros, acr, acr + "s", link: link)
+ } else {
+ display("acronyms", acros, acr, acr, link: link)
+ }
+}
+
+#let acrspl(acr, link: true) = {
+ acrs(acr, plural: true, link: link)
+}
+
+
+#let acrl(acr, plural: false, link: true) = {
+ context {
+ let acronyms = acros.get()
+
+ if is-in-dict("acronyms", acros, acr) {
+ let defs = acronyms.at(acr)
+ if type(defs) == "string" {
+ if plural {
+ display("acronyms", acros, acr, defs + "s", link: link)
+ } else {
+ display("acronyms", acros, acr, defs, link: link)
+ }
+ } else if type(defs) == "array" {
+ if defs.len() == 0 {
+ panic("No definitions found for acronym " + acr + ". Make sure it is defined in the dictionary passed to #init-acronyms(dict)")
+ }
+ if plural {
+ if defs.len() == 1 {
+ display("acronyms", acros, acr, defs.at(0) + "s", link: link)
+ } else if defs.len() == 2 {
+ display("acronyms", acros, acr, defs.at(1), link: link)
+ } else {
+ panic("Definitions should be arrays of one or two strings. Definition of " + acr + " is: " + type(defs))
+ }
+ } else {
+ display("acronyms", acros, acr, defs.at(0), link: link)
+ }
+ } else {
+ panic("Definitions should be arrays of one or two strings. Definition of " + acr + " is: " + type(defs))
+ }
+ }
+ }
+}
+
+#let acrlpl(acr, link: true) = {
+ acrl(acr, plural: true, link: link)
+}
+
+#let acrf(acr, plural: false, link: true) = {
+ if plural {
+ display("acronyms", acros, acr, [#acrlpl(acr) (#acr\s)], link: link)
+ } else {
+ display("acronyms", acros, acr, [#acrl(acr) (#acr)], link: link)
+ }
+ state(prefix + acr, false).update(true)
+}
+
+#let acrfpl(acr, link: true) = {
+ acrf(acr, plural: true, link: link)
+}
+
+#let acr(acr, plural: false, link: true) = {
+ context {
+ let seen = state(prefix + acr, false).get()
+
+ if seen {
+ if plural {
+ acrspl(acr, link: link)
+ } else {
+ acrs(acr, link: link)
+ }
+ } else {
+ if plural {
+ acrfpl(acr, link: link)
+ } else {
+ acrf(acr, link: link)
+ }
+ }
+ }
+}
+
+#let acrpl(acronym, link: true) = {
+ acr(acronym, plural: true, link: link)
+}
+
+#let print-acronyms(language, acronym-spacing) = {
+ heading(level: 1, outlined: false, numbering: none)[#ACRONYMS.at(language)]
+
+ context {
+ let acronyms = acros.get()
+ let acronym-keys = acronyms.keys()
+
+ let max-width = 0pt
+ for acr in acronym-keys {
+ let result = measure(acr).width
+
+ if (result > max-width) {
+ max-width = result
+ }
+ }
+
+ let acr-list = acronym-keys.sorted()
+
+ for acr in acr-list {
+ grid(
+ columns: (max-width + 0.5em, auto),
+ gutter: acronym-spacing,
+ [*#acr#label("acronyms-" + acr)*], [#acrl(acr, link: false)],
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/preview/supercharged-dhbw/3.4.1/check-attributes.typ b/packages/preview/supercharged-dhbw/3.4.1/check-attributes.typ
new file mode 100644
index 000000000..d277150c0
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/check-attributes.typ
@@ -0,0 +1,265 @@
+#let check-attributes(
+ title,
+ authors,
+ language,
+ at-university,
+ confidentiality-marker,
+ type-of-thesis,
+ type-of-degree,
+ show-confidentiality-statement,
+ show-declaration-of-authorship,
+ show-table-of-contents,
+ show-acronyms,
+ show-list-of-figures,
+ show-list-of-tables,
+ show-code-snippets,
+ show-abstract,
+ header,
+ numbering-alignment,
+ toc-depth,
+ acronym-spacing,
+ glossary-spacing,
+ abstract,
+ appendix,
+ acronyms,
+ university,
+ university-location,
+ supervisor,
+ date,
+ city,
+ bibliography,
+ bib-style,
+ logo-left,
+ logo-right,
+ logo-size-ratio,
+ university-short,
+ heading-numbering,
+ math-numbering,
+ ignored-link-label-keys-for-highlighting,
+ page-numbering,
+) = {
+ if (title == none or title == "") {
+ panic("Title is missing. Specify a title in the 'title' attribute of the template.")
+ }
+
+ if (header != none and type(header) != dictionary) {
+ panic("Header is invalid. Specify a dictionary in the 'header' attribute of the template. The following attributes can be set: 'display', 'show-chapter', 'show-left-logo', 'show-right-logo', 'show-divider', 'content'.")
+ }
+
+ let boolean-attributes = (
+ at-university: at-university,
+ show-confidentiality-statement: show-confidentiality-statement,
+ show-table-of-contents: show-table-of-contents,
+ show-acronyms: show-acronyms,
+ show-declaration-of-authorship: show-declaration-of-authorship,
+ show-list-of-figures: show-list-of-figures,
+ show-list-of-tables: show-list-of-tables,
+ show-code-snippets: show-code-snippets,
+ show-abstract: show-abstract,
+ )
+
+ for (key, attribute) in boolean-attributes {
+ if (type(attribute) != bool) {
+ panic("Attribute '" + key + "' is invalid. Specify 'true' or 'false' in the '" + key + "' attribute of the template.")
+ }
+ }
+
+ let string-attributes = (
+ university: university,
+ university-location: university-location,
+ university-short: university-short,
+ )
+
+ for (key, attribute) in string-attributes {
+ if (type(attribute) != str or attribute.len() == 0) {
+ panic("Attribute '" + key + "' is missing. Specify a " + key + " in the '" + key + "' attribute of the template.")
+ }
+ }
+
+ let optional-string-attributes = (
+ type-of-thesis: type-of-thesis,
+ type-of-degree: type-of-degree,
+ bib-style: bib-style,
+ heading-numbering: heading-numbering,
+ math-numbering: math-numbering,
+ )
+
+ if (page-numbering != none and type(page-numbering) != dictionary) {
+ panic("Page numbering is invalid. Specify a dictionary in the 'page-numbering' attribute of the template.")
+ }
+
+ if ("preface" in page-numbering) {
+ optional-string-attributes.insert("preface (page-numbering)", page-numbering.preface)
+ }
+
+ if ("main" in page-numbering) {
+ optional-string-attributes.insert("main (page-numbering)", page-numbering.main)
+ }
+
+ if ("appendix" in page-numbering) {
+ optional-string-attributes.insert("appendix (page-numbering)", page-numbering.appendix)
+ }
+
+ for (key, attribute) in optional-string-attributes {
+ if (attribute != none and (type(attribute) != str or attribute.len() == 0)) {
+ panic("Attribute '" + key + "' is invalid. Specify a string in the '" + key + "' attribute of the template.")
+ }
+ }
+
+ if (type(confidentiality-marker) != none) {
+ if (
+ type(confidentiality-marker) != dictionary or "display" not in confidentiality-marker or type(confidentiality-marker.display) != bool
+ ) {
+ panic("Confidentiality marker is invalid. Specify a dictionary in the 'confidentiality-marker' attribute of the template containing a 'display' attribute with a boolean value.")
+ }
+ }
+
+ let length-attributes = (
+ acronym-spacing: acronym-spacing,
+ glossary-spacing: glossary-spacing,
+ )
+
+ if ("offset-x" in confidentiality-marker) {
+ length-attributes.insert("offset-x (confidentiality-marker)", confidentiality-marker.offset-x)
+ }
+ if ("offset-y" in confidentiality-marker) {
+ length-attributes.insert("offset-y (confidentiality-marker)", confidentiality-marker.offset-y)
+ }
+ if ("size" in confidentiality-marker) {
+ length-attributes.insert("size (confidentiality-marker)", confidentiality-marker.size)
+ }
+ if ("title-spacing" in confidentiality-marker) {
+ length-attributes.insert("title-spacing (confidentiality-marker)", confidentiality-marker.title-spacing)
+ }
+
+ for (key, attribute) in length-attributes {
+ if (type(attribute) != length) {
+ panic("Attribute '" + key + "' is invalid. Specify a length in the '" + key + "' attribute of the template.")
+ }
+ }
+
+ if (authors == none or authors == ()) {
+ panic("Author is missing. Specify authors in the 'authors' attribute of the template.")
+ }
+
+ let max-authors = if at-university {
+ 8
+ } else {
+ 6
+ }
+
+ if (
+ (type-of-thesis != none and type-of-thesis != "") or (type-of-degree != none and type-of-degree != "") or (
+ confidentiality-marker.display == true
+ )
+ ) {
+ max-authors -= 2
+ }
+
+ if (authors.len() > max-authors) {
+ panic("Too many authors. Specify a maximum of " + str(max-authors) + " authors in the 'authors' attribute of the template. To increase the maximum number of authors (max. 8), change one of the following attributes: 'at-university', 'type-of-thesis', 'type-of-degree'. (See the package documentation for more information.)")
+ }
+
+ for author in authors {
+ if ("name" not in author or author.name == none or author.name == "") {
+ panic("Author name is missing. Specify a name for each author in the 'authors' attribute of the template.")
+ }
+
+ if ("student-id" not in author or author.student-id == none or author.student-id == "") {
+ panic("Student ID of '" + author.name + "' is missing. Specify a student ID for each author in the 'authors' attribute of the template.")
+ }
+
+ if ("course" not in author or author.course == none or author.course == "") {
+ panic("Course of '" + author.name + "' is missing. Specify a course for each author in the 'authors' attribute of the template.")
+ }
+
+ if ("course-of-studies" not in author or author.course-of-studies == none or author.course-of-studies == "") {
+ panic("Course of studies of '" + author.name + "' is missing. Specify a course of studies for each author in the 'authors' attribute of the template.")
+ }
+
+ if (at-university) {
+ if ("company" in author) {
+ panic("Company of '" + author.name + "' is not allowed. Remove the 'company' object from the author.")
+ }
+
+ if (type(city) != str or city == "") {
+ panic("City is invalid. Specify a string containing a city in the 'city' attribute.")
+ }
+ } else {
+ if (type(city) == str) {
+ panic("Remove the City attribute. When 'at-university' is true the city inside the company object is used.")
+ }
+
+ if ("company" not in author) {
+ panic("Author '" + author.name + "' is missing a company. Add the 'company' object to the author.")
+ }
+ }
+ }
+
+ if (language != "en" and language != "de") {
+ panic("Language is invalid. Specify 'en' for English or 'de' for German in the 'language' attribute of the template.")
+ }
+
+ if (type(numbering-alignment) != alignment) {
+ panic("Numbering alignment is invalid. Specify a alignment in the 'numbering-alignment' attribute of the template.")
+ }
+
+ if (type(toc-depth) != int) {
+ panic("TOC depth is invalid. Specify an integer in the 'toc-depth' attribute of the template.")
+ }
+
+ if (
+ type(date) != datetime and (
+ type(date) != array or date.len() != 2 or type(date.at(0)) != datetime or type(date.at(1)) != datetime
+ )
+ ) {
+ panic("Date is invalid. Specify a datetime in the 'date' attribute of the template to display a specific date or use a array containing two datetime elements to display a date range.")
+ }
+
+ let image-attributes = (
+ logo-left: logo-left,
+ logo-right: logo-right,
+ )
+
+ for (key, attribute) in image-attributes {
+ if (type(attribute) != content and attribute != none) {
+ panic("Attribute '" + key + "' is invalid. Specify an image in the '" + key + "' attribute of the template.")
+ }
+ }
+
+ if (type(logo-size-ratio) != str or logo-size-ratio.len() == 0) {
+ panic("Logo size ratio is missing. Specify a ratio in the 'logo-size-ratio' attribute of the template.")
+ }
+
+ let ratio = logo-size-ratio.split(":")
+
+ if (ratio.len() != 2) {
+ panic("Invalid ratio. Specify a ratio in the format 'x:y' in the 'logo-size-ratio' attribute of the template.")
+ }
+
+ if (type(bibliography) != content and bibliography != none) {
+ panic("Bibliography is invalid. Specify a bibliography in the 'bibliography' attribute of the template.")
+ }
+
+ if (
+ type(supervisor) != dictionary or (
+ "company" not in supervisor or supervisor.company == none or supervisor.company == ""
+ ) and ("university" not in supervisor or supervisor.university == none or supervisor.university == "")
+ ) {
+ panic("Supervisor(s) is/are invalid. Specify a supervisor either for the company and/or the university in the 'supervisor' attribute of the template.")
+ }
+
+ let string-array-attributes = (
+ ignored-link-label-keys-for-highlighting: ignored-link-label-keys-for-highlighting,
+ )
+
+ for (key, attribute) in string-array-attributes {
+ if (type(attribute) != array) {
+ panic("Attribute '" + key + "' is invalid. Specify an array of strings in the '" + key + "' attribute of the template.")
+ } else if (attribute.len() > 0) {
+ if (type(attribute.at(0)) != str) {
+ panic("Attribute '" + key + "' is invalid. Specify an array of strings in the '" + key + "' attribute of the template.")
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/preview/supercharged-dhbw/3.4.1/confidentiality-statement.typ b/packages/preview/supercharged-dhbw/3.4.1/confidentiality-statement.typ
new file mode 100644
index 000000000..b30a321c5
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/confidentiality-statement.typ
@@ -0,0 +1,75 @@
+#import "locale.typ": *
+
+#let confidentiality-statement(
+ authors,
+ title,
+ confidentiality-statement-content,
+ university,
+ university-location,
+ date,
+ language,
+ many-authors,
+ date-format,
+) = {
+ let authors-by-city = authors.map(author => author.company.city).dedup()
+
+ v(2em)
+ text(size: 20pt, weight: "bold", CONFIDENTIALITY_STATEMENT_TITLE.at(language))
+ v(1em)
+
+ if (confidentiality-statement-content != none) {
+ confidentiality-statement-content
+ } else {
+ let authors-by-company = authors.map(author => author.company.name).dedup()
+ let authors-by-study = authors.map(author => author.course-of-studies).dedup()
+ let companies = authors-by-company.join(", ", last: AND.at(language))
+
+ let institution = if (authors-by-company.len() == 1) {
+ INSTITUTION_SINGLE.at(language)
+ } else {
+ INSTITUTION_PLURAL.at(language)
+ }
+
+ text(CONFIDENTIALITY_STATEMENT_SECTION_A.at(language))
+ v(1em)
+ align(
+ center,
+ text(weight: "bold", title),
+ )
+
+ v(1em)
+
+ par(
+ justify: true,
+ CONFIDENTIALITY_STATEMENT_SECTION_B.at(language) + [ ] + companies + CONFIDENTIALITY_STATEMENT_SECTION_C.at(language) + [ ] + authors-by-study.join(" | ") + CONFIDENTIALITY_STATEMENT_SECTION_D.at(language) + university + [ ] + university-location + CONFIDENTIALITY_STATEMENT_SECTION_E.at(language) + institution + [ (#companies)] + CONFIDENTIALITY_STATEMENT_SECTION_F.at(language),
+ )
+ }
+
+ let end-date = if (type(date) == datetime) {
+ date
+ } else {
+ date.at(1)
+ }
+
+ v(2em)
+ text(authors-by-city.dedup().join(", ", last: AND.at(language)) + [ ] + end-date.display(date-format))
+
+ v(0.5em)
+ if (many-authors) {
+ grid(
+ columns: (1fr, 1fr),
+ gutter: 20pt,
+ ..authors.map(author => {
+ v(3.5em)
+ line(length: 80%)
+ author.name
+ })
+ )
+ } else {
+ for author in authors {
+ v(4em)
+ line(length: 40%)
+ author.name
+ }
+ }
+}
diff --git a/packages/preview/supercharged-dhbw/3.4.1/declaration-of-authorship.typ b/packages/preview/supercharged-dhbw/3.4.1/declaration-of-authorship.typ
new file mode 100644
index 000000000..ae02e1221
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/declaration-of-authorship.typ
@@ -0,0 +1,69 @@
+#import "locale.typ": *
+
+#let declaration-of-authorship(
+ authors,
+ title,
+ declaration-of-authorship-content,
+ date,
+ language,
+ many-authors,
+ at-university,
+ city,
+ date-format,
+) = {
+ v(2em)
+ text(size: 20pt, weight: "bold", DECLARATION_OF_AUTHORSHIP_TITLE.at(language))
+ v(1em)
+
+ if (declaration-of-authorship-content != none) {
+ declaration-of-authorship-content
+ } else {
+ if (authors.len() == 1) {
+ par(justify: true, DECLARATION_OF_AUTHORSHIP_SECTION_A_SINGLE)
+ v(1em)
+ align(center, text(weight: "bold", title))
+ v(1em)
+ par(justify: true, DECLARATION_OF_AUTHORSHIP_SECTION_B_SINGLE)
+ } else {
+ par(justify: true, DECLARATION_OF_AUTHORSHIP_SECTION_A_PLURAL)
+ v(1em)
+ align(center, text(weight: "bold", title))
+ v(1em)
+ par(justify: true, DECLARATION_OF_AUTHORSHIP_SECTION_B_PLURAL)
+ }
+ }
+
+ let end-date = if (type(date) == datetime) {
+ date
+ } else {
+ date.at(1)
+ }
+
+ v(2em)
+ if (at-university) {
+ text(city + [, ] + end-date.display(date-format))
+ } else {
+ let authors-by-city = authors.map(author => author.company.city).dedup()
+
+ text(authors-by-city.join(", ", last: AND.at(language)) + [ ] + end-date.display(date-format))
+ }
+
+ v(1em)
+ if (many-authors) {
+ grid(
+ columns: (1fr, 1fr),
+ gutter: 20pt,
+ ..authors.map(author => {
+ v(3.5em)
+ line(length: 80%)
+ author.name
+ })
+ )
+ } else {
+ for author in authors {
+ v(4em)
+ line(length: 40%)
+ author.name
+ }
+ }
+}
diff --git a/packages/preview/supercharged-dhbw/3.4.1/dhbw.svg b/packages/preview/supercharged-dhbw/3.4.1/dhbw.svg
new file mode 100644
index 000000000..4a9598b7a
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/dhbw.svg
@@ -0,0 +1,2 @@
+
\ No newline at end of file
diff --git a/packages/preview/supercharged-dhbw/3.4.1/examples/example-acronyms.typ b/packages/preview/supercharged-dhbw/3.4.1/examples/example-acronyms.typ
new file mode 100644
index 000000000..f7c4ab14a
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/examples/example-acronyms.typ
@@ -0,0 +1,5 @@
+#let acronyms = (
+ API: "Application Programming Interface",
+ HTTP: "Hypertext Transfer Protocol",
+ REST: "Representational State Transfer",
+)
\ No newline at end of file
diff --git a/packages/preview/supercharged-dhbw/3.4.1/examples/example-glossary.typ b/packages/preview/supercharged-dhbw/3.4.1/examples/example-glossary.typ
new file mode 100644
index 000000000..432b6f098
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/examples/example-glossary.typ
@@ -0,0 +1,5 @@
+#let glossary = (
+ Vulnerability: "A Vulnerability is a flaw in a computer system that weakens the overall security of the system.",
+ Patch: "A patch is data that is intended to be used to modify an existing software resource such as a program or a file, often to fix bugs and security vulnerabilities.",
+ Exploit: "An exploit is a method or piece of code that takes advantage of vulnerabilities in software, applications, networks, operating systems, or hardware, typically for malicious purposes.",
+)
\ No newline at end of file
diff --git a/packages/preview/supercharged-dhbw/3.4.1/examples/example-sources.bib b/packages/preview/supercharged-dhbw/3.4.1/examples/example-sources.bib
new file mode 100644
index 000000000..ec119dedd
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/examples/example-sources.bib
@@ -0,0 +1,6 @@
+@inproceedings{iso18004,
+ title = {{ISO/IEC 18004: Information technology -- Automatic identification and data capture techniques -- QR code bar code symbology specification}},
+ booktitle = {ISO/IEC 18004:2015},
+ author = {{International Organization for Standardization}},
+ year = {2015}
+}
\ No newline at end of file
diff --git a/packages/preview/supercharged-dhbw/3.4.1/examples/example-sources.yml b/packages/preview/supercharged-dhbw/3.4.1/examples/example-sources.yml
new file mode 100644
index 000000000..5da2c816c
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/examples/example-sources.yml
@@ -0,0 +1,13 @@
+examplesource:
+ type: article
+ title: "Example article about an important topic"
+ authors:
+ - name: Seidel, Danny
+ - name: Gingele, Thomas
+ volume: 5
+ page-range: 123-456
+ date: 2024-08-01
+ serial-number:
+ doi: IMPORTANT/10.123456789
+ parent:
+ title: "Very important internation conference"
\ No newline at end of file
diff --git a/packages/preview/supercharged-dhbw/3.4.1/examples/example.typ b/packages/preview/supercharged-dhbw/3.4.1/examples/example.typ
new file mode 100644
index 000000000..f46f96cc7
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/examples/example.typ
@@ -0,0 +1,34 @@
+#import "@preview/supercharged-dhbw:3.4.1": *
+
+#let acronyms = (
+ "VIP": "Very important person",
+)
+
+#show: supercharged-dhbw.with(
+ title: "Exploration of Typst for the Composition of a University Thesis",
+ authors: (
+ (name: "Max Mustermann", student-id: "7654321", course: "TIS21", course-of-studies: "IT-Security", company: (
+ (name: "YXZ GmbH", post-code: "70435", city: "Stuttgart")
+ )),
+ (name: "Juan Pérez", student-id: "1234567", course: "TIM21", course-of-studies: "Mobile Computer Science", company: (
+ (name: "ABC S.L.", post-code: "08005", city: "Barcelona", country: "Spain")
+ )),
+ ),
+ acronyms: acronyms, // displays the acronyms defined in the acronyms dictionary
+ at-university: false, // if true the company name on the title page and the confidentiality statement are hidden
+ confidentiality-marker: (display: true),
+ bibliography: bibliography("example-sources.yml"),
+ date: datetime.today(),
+ language: "en", // en, de
+ supervisor: (company: "John Appleseed"),
+ university: "Cooperative State University Baden-Württemberg",
+ university-location: "Ravensburg Campus Friedrichshafen",
+ university-short: "DHBW",
+ // for more options check the package documentation (https://typst.app/universe/package/supercharged-dhbw)
+)
+
+= Section A
+
+A #acr("VIP") once said this:
+
+#lorem(250) @examplesource
\ No newline at end of file
diff --git a/packages/preview/supercharged-dhbw/3.4.1/glossary-lib.typ b/packages/preview/supercharged-dhbw/3.4.1/glossary-lib.typ
new file mode 100644
index 000000000..181173a32
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/glossary-lib.typ
@@ -0,0 +1,43 @@
+#import "locale.typ": GLOSSARY
+#import "shared-lib.typ": display, display-link
+
+#let prefix = "glossary-state-"
+#let glossary-state = state("glossary", none)
+
+#let init-glossary(glossary) = {
+ glossary-state.update(glossary)
+}
+
+// Display acronym. Expands it if used for the first time
+#let gls(element, link: true) = {
+ display("glossary", glossary-state, element, element, link: link)
+}
+
+// Print an index of all the acronyms and their definitions.
+#let print-glossary(language, glossary-spacing) = {
+ heading(level: 1, outlined: false, numbering: none)[#GLOSSARY.at(language)]
+
+ context {
+ let glossary = glossary-state.get()
+ let glossary-keys = glossary.keys()
+
+ let max-width = 0pt
+ for key in glossary-keys {
+ let result = measure(key).width
+
+ if (result > max-width) {
+ max-width = result
+ }
+ }
+
+ let glossary-list = glossary-keys.sorted()
+
+ for element in glossary-list {
+ grid(
+ columns: (max-width + 1em, auto),
+ gutter: glossary-spacing,
+ [*#element#label("glossary-" + element)*], [#glossary.at(element)],
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/preview/supercharged-dhbw/3.4.1/lib.typ b/packages/preview/supercharged-dhbw/3.4.1/lib.typ
new file mode 100644
index 000000000..509ef634d
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/lib.typ
@@ -0,0 +1,512 @@
+#import "@preview/codelst:2.0.2": *
+#import "acronym-lib.typ": init-acronyms, print-acronyms, acr, acrpl, acrs, acrspl, acrl, acrlpl, acrf, acrfpl
+#import "glossary-lib.typ": init-glossary, print-glossary, gls
+#import "locale.typ": TABLE_OF_CONTENTS, LIST_OF_FIGURES, LIST_OF_TABLES, CODE_SNIPPETS, APPENDIX, REFERENCES
+#import "titlepage.typ": *
+#import "confidentiality-statement.typ": *
+#import "declaration-of-authorship.typ": *
+#import "check-attributes.typ": *
+
+// Workaround for the lack of an `std` scope.
+#let std-bibliography = bibliography
+
+#let page-numbering-symbols = (
+ "1",
+ "a",
+ "A",
+ "i",
+ "I",
+ "α",
+ "Α",
+ "*",
+ "א",
+ "一",
+ "壹",
+ "あ",
+ "い",
+ "ア",
+ "イ",
+ "ㄱ",
+ "가",
+ "\u{0661}",
+ "\u{06F1}",
+ "\u{0967}",
+ "\u{09E7}",
+ "\u{0995}",
+ "①",
+ "⓵",
+)
+
+#let supercharged-dhbw(
+ title: none,
+ authors: (:),
+ language: none,
+ at-university: none,
+ confidentiality-marker: (display: false),
+ type-of-thesis: none,
+ type-of-degree: none,
+ show-confidentiality-statement: true,
+ show-declaration-of-authorship: true,
+ show-table-of-contents: true,
+ show-acronyms: true,
+ show-list-of-figures: true,
+ show-list-of-tables: true,
+ show-code-snippets: true,
+ show-abstract: true,
+ numbering-alignment: center,
+ toc-depth: 3,
+ acronym-spacing: 5em,
+ glossary-spacing: 1.5em,
+ abstract: none,
+ appendix: none,
+ acronyms: none,
+ glossary: none,
+ header: none,
+ confidentiality-statement-content: none,
+ declaration-of-authorship-content: none,
+ titlepage-content: none,
+ university: none,
+ university-location: none,
+ university-short: none,
+ city: none,
+ supervisor: (:),
+ date: none,
+ date-format: "[day].[month].[year]",
+ bibliography: none,
+ bib-style: "ieee",
+ heading-numbering: "1.1",
+ math-numbering: "(1)",
+ page-numbering: (preface: "I", main: "1 / 1", appendix: "a"),
+ logo-left: image("dhbw.svg"),
+ logo-right: none,
+ logo-size-ratio: "1:1",
+ ignored-link-label-keys-for-highlighting: (),
+ body,
+) = {
+ // check required attributes
+ check-attributes(
+ title,
+ authors,
+ language,
+ at-university,
+ confidentiality-marker,
+ type-of-thesis,
+ type-of-degree,
+ show-confidentiality-statement,
+ show-declaration-of-authorship,
+ show-table-of-contents,
+ show-acronyms,
+ show-list-of-figures,
+ show-list-of-tables,
+ show-code-snippets,
+ show-abstract,
+ header,
+ numbering-alignment,
+ toc-depth,
+ acronym-spacing,
+ glossary-spacing,
+ abstract,
+ appendix,
+ acronyms,
+ university,
+ university-location,
+ supervisor,
+ date,
+ city,
+ bibliography,
+ bib-style,
+ logo-left,
+ logo-right,
+ logo-size-ratio,
+ university-short,
+ heading-numbering,
+ math-numbering,
+ ignored-link-label-keys-for-highlighting,
+ page-numbering,
+ )
+
+ // set the document's basic properties
+ set document(title: title, author: authors.map(author => author.name))
+ let many-authors = authors.len() > 3
+
+ init-acronyms(acronyms)
+ init-glossary(glossary)
+
+ // define logo size with given ration
+ let left-logo-height = 2.4cm // left logo is always 2.4cm high
+ let right-logo-height = 2.4cm // right logo defaults to 2.4cm but is adjusted below
+ let logo-ratio = logo-size-ratio.split(":")
+ if (logo-ratio.len() == 2) {
+ right-logo-height = right-logo-height * (float(logo-ratio.at(1)) / float(logo-ratio.at(0)))
+ }
+
+ // save heading and body font families in variables
+ let body-font = "Open Sans"
+ let heading-font = "Montserrat"
+
+ // customize look of figure
+ set figure.caption(separator: [ --- ], position: bottom)
+
+ // set body font family
+ set text(font: body-font, lang: language, 12pt)
+ show heading: set text(weight: "semibold", font: heading-font)
+
+ // heading numbering
+ set heading(numbering: heading-numbering)
+
+ // math numbering
+ set math.equation(numbering: math-numbering)
+
+ // set link style for links that are not acronyms
+ let acronym-keys = if (acronyms != none) {
+ acronyms.keys().map(acr => ("acronyms-" + acr))
+ } else {
+ ()
+ }
+ let glossary-keys = if (glossary != none) {
+ glossary.keys().map(gls => ("glossary-" + gls))
+ } else {
+ ()
+ }
+ show link: it => if (str(it.dest) not in (acronym-keys + glossary-keys + ignored-link-label-keys-for-highlighting)) {
+ text(fill: blue, it)
+ } else {
+ it
+ }
+
+ show heading.where(level: 1): it => {
+ pagebreak()
+ v(2em) + it + v(1em)
+ }
+ show heading.where(level: 2): it => v(1em) + it + v(0.5em)
+ show heading.where(level: 3): it => v(0.5em) + it + v(0.25em)
+
+ if (titlepage-content != none) {
+ titlepage-content
+ } else {
+ titlepage(
+ authors,
+ date,
+ heading-font,
+ language,
+ left-logo-height,
+ logo-left,
+ logo-right,
+ many-authors,
+ right-logo-height,
+ supervisor,
+ title,
+ type-of-degree,
+ type-of-thesis,
+ university,
+ university-location,
+ at-university,
+ date-format,
+ show-confidentiality-statement,
+ confidentiality-marker,
+ university-short,
+ )
+ }
+
+ // set header properties
+ let display-header = if (header != none and ("display" in header)) {
+ header.display
+ } else {
+ true
+ }
+
+ let header-content = if (header != none and ("content" in header)) {
+ header.content
+ } else {
+ none
+ }
+
+ let show-header-chapter = if (header != none and ("show-chapter" in header)) {
+ header.show-chapter
+ } else {
+ true
+ }
+
+ let show-header-left-logo = if (header != none and ("show-left-logo" in header)) {
+ header.show-left-logo
+ } else {
+ true
+ }
+
+ let show-header-right-logo = if (header != none and ("show-right-logo" in header)) {
+ header.show-right-logo
+ } else {
+ true
+ }
+
+ let show-header-divider = if (header != none and ("show-divider" in header)) {
+ header.show-divider
+ } else {
+ true
+ }
+
+ set page(
+ margin: (top: 8em, bottom: 8em),
+ header: [
+ #set block(spacing: 0.75em)
+ #context {
+ if (display-header) {
+ if (header-content != none) {
+ header.content
+ } else {
+ grid(
+ columns: (1fr, auto),
+ align: (left, right),
+ gutter: 2em,
+ if (show-header-chapter) {
+ align(left + bottom)[
+ #let headings = query(heading.where(level: 1))
+ #if headings.len() > 0 and not headings.any(it => (it.location().page() == here().page())) {
+ let elems = query(selector(heading.where(level: 1)).before(here()))
+
+ if (elems.len() > 0) {
+ let current-heading = elems.last()
+ let heading-counter = if current-heading.numbering == none {
+ none
+ } else {
+ counter(heading).get().first()
+ }
+
+ [#heading-counter #current-heading.body]
+ }
+ } else {
+ let elems = query(selector(heading.where(level: 1)).after(here()))
+
+ if (elems.len() > 0) {
+ let current-heading = elems.first()
+ let heading-counter = if current-heading.numbering == none {
+ none
+ } else {
+ counter(heading).get().first() + 1
+ }
+
+ [#heading-counter #current-heading.body]
+ }
+ }
+ ]
+ },
+ stack(
+ dir: ltr,
+ spacing: 1em,
+ if (show-header-left-logo and logo-left != none) {
+ set image(height: left-logo-height / 2)
+ logo-left
+ },
+ if (show-header-right-logo and logo-right != none) {
+ set image(height: right-logo-height / 2)
+ logo-right
+ },
+ ),
+ )
+ if (show-header-divider) {
+ line(length: 100%)
+ }
+ }
+ }
+ }
+ ],
+ )
+
+ // set page numbering for preface
+ let preface-numbering = "I"
+ if ("preface" in page-numbering) {
+ preface-numbering = page-numbering.preface
+ }
+
+ set page(
+ // necessary to apply numbering in the table of contents
+ numbering: preface-numbering,
+ footer: context {
+ let display-total-page-number = preface-numbering.clusters().filter(c => c in page-numbering-symbols).len() >= 2
+
+ align(
+ numbering-alignment,
+ numbering(
+ preface-numbering,
+ ..counter(page).get(),
+ ..if display-total-page-number {
+ counter(page).at()
+ },
+ ),
+ )
+ },
+ )
+ counter(page).update(1)
+
+ if (not at-university and show-confidentiality-statement) {
+ pagebreak()
+ confidentiality-statement(
+ authors,
+ title,
+ confidentiality-statement-content,
+ university,
+ university-location,
+ date,
+ language,
+ many-authors,
+ date-format,
+ )
+ }
+
+ if (show-declaration-of-authorship) {
+ pagebreak()
+ declaration-of-authorship(
+ authors,
+ title,
+ declaration-of-authorship-content,
+ date,
+ language,
+ many-authors,
+ at-university,
+ city,
+ date-format,
+ )
+ }
+
+ show outline.entry.where(level: 1): it => {
+ v(18pt, weak: true)
+ strong(it)
+ }
+
+ set par(justify: true, leading: 1em)
+
+ if (show-abstract and abstract != none) {
+ align(center + horizon, heading(level: 1, numbering: none, outlined: false)[Abstract])
+ text(abstract)
+ }
+
+ set par(leading: 0.65em)
+
+ if (show-table-of-contents) {
+ outline(
+ title: TABLE_OF_CONTENTS.at(language),
+ indent: auto,
+ depth: toc-depth,
+ )
+ }
+
+ context {
+ let elems = query(figure.where(kind: image))
+ let count = elems.len()
+
+ if (show-list-of-figures and count > 0) {
+ outline(
+ title: LIST_OF_FIGURES.at(language),
+ target: figure.where(kind: image),
+ )
+ }
+ }
+
+ context {
+ let elems = query(figure.where(kind: table))
+ let count = elems.len()
+
+ if (show-list-of-tables and count > 0) {
+ outline(
+ title: LIST_OF_TABLES.at(language),
+ target: figure.where(kind: table),
+ )
+ }
+ }
+
+ context {
+ let elems = query(figure.where(kind: raw))
+ let count = elems.len()
+
+ if (show-code-snippets and count > 0) {
+ outline(
+ title: CODE_SNIPPETS.at(language),
+ target: figure.where(kind: raw),
+ )
+ }
+ }
+
+ if (show-acronyms and acronyms != none and acronyms.len() > 0) {
+ print-acronyms(language, acronym-spacing)
+ }
+
+ if (glossary != none and glossary.len() > 0) {
+ print-glossary(language, glossary-spacing)
+ }
+
+ [#metadata(none)]
+
+ set par(leading: 1em, spacing: 2em)
+ set block(spacing: 2em)
+
+ // reset page numbering and set to main page numbering
+ let main-numbering = "1 / 1"
+ if ("main" in page-numbering) {
+ main-numbering = page-numbering.main
+ }
+
+ set page(
+ // necessary to apply numbering in the table of contents
+ numbering: main-numbering,
+ footer: context {
+ let display-total-page-number = main-numbering.clusters().filter(c => c in page-numbering-symbols).len() >= 2
+
+ align(
+ numbering-alignment,
+ numbering(
+ main-numbering,
+ ..counter(page).get(),
+ ..if display-total-page-number {
+ counter(page).at()
+ },
+ ),
+ )
+ },
+ )
+ counter(page).update(1)
+
+ body
+
+ [#metadata(none)]
+ // reset page numbering and set to appendix page numbering
+ let appendix-numbering = "a"
+ if ("appendix" in page-numbering) {
+ appendix-numbering = page-numbering.appendix
+ }
+
+ set page(
+ // necessary to apply numbering in the table of contents
+ numbering: appendix-numbering,
+ footer: context {
+ let display-total-page-number = appendix-numbering.clusters().filter(c => c in page-numbering-symbols).len() >= 2
+
+ align(
+ numbering-alignment,
+ numbering(
+ appendix-numbering,
+ ..counter(page).get(),
+ ..if display-total-page-number {
+ counter(page).at()
+ },
+ ),
+ )
+ },
+ )
+ counter(page).update(1)
+
+ // Display bibliography.
+ if bibliography != none {
+ set std-bibliography(
+ title: REFERENCES.at(language),
+ style: bib-style,
+ )
+ bibliography
+ }
+
+ if (appendix != none) {
+ heading(level: 1, numbering: none)[#APPENDIX.at(language)]
+ appendix
+ }
+
+ [#metadata(none)]
+}
diff --git a/packages/preview/supercharged-dhbw/3.4.1/locale.typ b/packages/preview/supercharged-dhbw/3.4.1/locale.typ
new file mode 100644
index 000000000..91f817373
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/locale.typ
@@ -0,0 +1,143 @@
+#let TITLEPAGE_SECTION_A = (
+ "de": "für den Erwerb des",
+ "en": "for the",
+)
+
+#let TITLEPAGE_SECTION_B = (
+ "de": "aus dem Studiengang ",
+ "en": "from the course of studies ",
+)
+
+#let TITLEPAGE_SECTION_C = (
+ "de": "an der ",
+ "en": "at the ",
+)
+
+#let TITLEPAGE_STUDENT_ID = (
+ "de": "Matrikelnummer, Kurs:",
+ "en": "Student ID, Course:",
+)
+
+#let TITLEPAGE_COMPANY = (
+ "de": "Unternehmen:",
+ "en": "Company:",
+)
+
+#let TITLEPAGE_COMPANY_SUPERVISOR = (
+ "de": "Betreuer im Unternehmen:",
+ "en": "Supervisor in the Company:",
+)
+
+#let TITLEPAGE_SUPERVISOR = (
+ "de": "Betreuer an der ",
+ "en": "Supervisor at ",
+)
+
+#let DECLARATION_OF_AUTHORSHIP_TITLE = (
+ "de": "Selbstständigkeitserklärung",
+ "en": "Declaration of Authorship",
+)
+
+#let DECLARATION_OF_AUTHORSHIP_SECTION_A_SINGLE = "Gemäß Ziffer 1.1.13 der Anlage 1 zu §§ 3, 4 und 5 der Studien- und Prüfungsordnung für die Bachelorstudiengänge im Studienbereich Technik der Dualen Hochschule Baden- Württemberg vom 29.09.2017. Ich versichere hiermit, dass ich meine Arbeit mit dem Thema:"
+
+#let DECLARATION_OF_AUTHORSHIP_SECTION_A_PLURAL = "Gemäß Ziffer 1.1.13 der Anlage 1 zu §§ 3, 4 und 5 der Studien- und Prüfungsordnung für die Bachelorstudiengänge im Studienbereich Technik der Dualen Hochschule Baden- Württemberg vom 29.09.2017. Wir versichern hiermit, dass wir unsere Arbeit mit dem Thema:"
+
+#let DECLARATION_OF_AUTHORSHIP_SECTION_B_SINGLE = "selbstständig verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel benutzt habe. Ich versichere zudem, dass alle eingereichten Fassungen übereinstimmen."
+
+#let DECLARATION_OF_AUTHORSHIP_SECTION_B_PLURAL = "selbstständig verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel benutzt haben. Wir versichern zudem, dass alle eingereichten Fassungen übereinstimmen."
+
+#let CONFIDENTIALITY_STATEMENT_TITLE = (
+ "de": "Sperrvermerk",
+ "en": "Confidentiality Statement",
+)
+
+#let CONFIDENTIALITY_STATEMENT_SECTION_A = (
+ "de": "Die vorliegende Arbeit mit dem Titel",
+ "en": "The Thesis on hand",
+)
+
+#let CONFIDENTIALITY_STATEMENT_SECTION_B = (
+ "de": "enthält unternehmensinterne bzw. vertrauliche Informationen der",
+ "en": "contains internal respective confidential data of",
+)
+#let CONFIDENTIALITY_STATEMENT_SECTION_C = (
+ "de": ", ist deshalb mit einem Sperrvermerk versehen und wird ausschließlich zu Prüfungszwecken im Studiengang",
+ "en": ". It is intended solely for inspection by the assigned examiner, the head of the",
+)
+#let CONFIDENTIALITY_STATEMENT_SECTION_D = (
+ "de": " der ",
+ "en": " department and, if necessary, the Audit Committee at the ",
+)
+#let CONFIDENTIALITY_STATEMENT_SECTION_E = (
+ "de": " vorgelegt.
+
+Der Inhalt dieser Arbeit darf weder als Ganzes noch in Auszügen Personen außerhalb des Prüfungsprozesses und des Evaluationsverfahrens zugänglich gemacht werden, sofern keine anders lautende Genehmigung der ",
+ "en": ".
+
+The content of this thesis may not be made available, either in its entirety or in excerpts, to persons outside of the examination process and the evaluation process, unless otherwise authorized by the training ",
+)
+
+#let CONFIDENTIALITY_STATEMENT_SECTION_F = (
+ "de": " vorliegt.",
+ "en": ".",
+)
+
+#let INSTITUTION_SINGLE = (
+ "de": "Ausbildungsstätte",
+ "en": "institution",
+)
+
+#let INSTITUTION_PLURAL = (
+ "de": "Ausbildungsstätten",
+ "en": "institutions",
+)
+
+#let AND = (
+ "de": " und ",
+ "en": " and ",
+)
+
+#let BY = (
+ "de": "von",
+ "en": "by",
+)
+
+#let TABLE_OF_CONTENTS = (
+ "de": "Inhaltsverzeichnis",
+ "en": "Table of Contents",
+)
+
+#let LIST_OF_FIGURES = (
+ "de": "Abbildungsverzeichnis",
+ "en": "List of Figures",
+)
+
+#let LIST_OF_TABLES = (
+ "de": "Tabellenverzeichnis",
+ "en": "List of Tables",
+)
+
+#let CODE_SNIPPETS = (
+ "de": "Codeverzeichnis",
+ "en": "Code Snippets",
+)
+
+#let ACRONYMS = (
+ "de": "Abkürzungsverzeichnis",
+ "en": "List of Acronyms",
+)
+
+#let GLOSSARY = (
+ "de": "Glossar",
+ "en": "Glossary",
+)
+
+#let REFERENCES = (
+ "de": "Literatur",
+ "en": "References",
+)
+
+#let APPENDIX = (
+ "de": "Anhang",
+ "en": "Appendix",
+)
diff --git a/packages/preview/supercharged-dhbw/3.4.1/shared-lib.typ b/packages/preview/supercharged-dhbw/3.4.1/shared-lib.typ
new file mode 100644
index 000000000..54811df3d
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/shared-lib.typ
@@ -0,0 +1,25 @@
+#let is-in-dict(dict-type, state, element) = {
+ context {
+ let list = state.get()
+ if element not in list {
+ panic(element + " is not a key in the " + dict-type + " dictionary.")
+ return false
+ }
+ }
+
+ return true
+}
+
+#let display-link(dict-type, state, element, text) = {
+ if is-in-dict(dict-type, state, element) {
+ link(label(dict-type + "-" + element), text)
+ }
+}
+
+#let display(dict-type, state, element, text, link: true) = {
+ if link {
+ display-link(dict-type, state, element, text)
+ } else {
+ text
+ }
+}
diff --git a/packages/preview/supercharged-dhbw/3.4.1/template/acronyms.typ b/packages/preview/supercharged-dhbw/3.4.1/template/acronyms.typ
new file mode 100644
index 000000000..f7c4ab14a
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/template/acronyms.typ
@@ -0,0 +1,5 @@
+#let acronyms = (
+ API: "Application Programming Interface",
+ HTTP: "Hypertext Transfer Protocol",
+ REST: "Representational State Transfer",
+)
\ No newline at end of file
diff --git a/packages/preview/supercharged-dhbw/3.4.1/template/assets/ts.svg b/packages/preview/supercharged-dhbw/3.4.1/template/assets/ts.svg
new file mode 100644
index 000000000..f5acd4ea8
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/template/assets/ts.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/preview/supercharged-dhbw/3.4.1/template/glossary.typ b/packages/preview/supercharged-dhbw/3.4.1/template/glossary.typ
new file mode 100644
index 000000000..432b6f098
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/template/glossary.typ
@@ -0,0 +1,5 @@
+#let glossary = (
+ Vulnerability: "A Vulnerability is a flaw in a computer system that weakens the overall security of the system.",
+ Patch: "A patch is data that is intended to be used to modify an existing software resource such as a program or a file, often to fix bugs and security vulnerabilities.",
+ Exploit: "An exploit is a method or piece of code that takes advantage of vulnerabilities in software, applications, networks, operating systems, or hardware, typically for malicious purposes.",
+)
\ No newline at end of file
diff --git a/packages/preview/supercharged-dhbw/3.4.1/template/main.typ b/packages/preview/supercharged-dhbw/3.4.1/template/main.typ
new file mode 100644
index 000000000..ccd9be16e
--- /dev/null
+++ b/packages/preview/supercharged-dhbw/3.4.1/template/main.typ
@@ -0,0 +1,138 @@
+#import "@preview/supercharged-dhbw:3.4.1": *
+#import "acronyms.typ": acronyms
+#import "glossary.typ": glossary
+
+#show: supercharged-dhbw.with(
+ title: "Exploration of Typst for the Composition of a University Thesis",
+ authors: (
+ (name: "Max Mustermann", student-id: "7654321", course: "TIS21", course-of-studies: "IT-Security", company: (
+ (name: "YXZ GmbH", post-code: "70435", city: "Stuttgart")
+ )),
+ (name: "Juan Pérez", student-id: "1234567", course: "TIM21", course-of-studies: "Mobile Computer Science", company: (
+ (name: "ABC S.L.", post-code: "08005", city: "Barcelona", country: "Spain")
+ )),
+ ),
+ acronyms: acronyms, // displays the acronyms defined in the acronyms dictionary
+ at-university: false, // if true the company name on the title page and the confidentiality statement are hidden
+ bibliography: bibliography("sources.bib"),
+ date: datetime.today(),
+ glossary: glossary, // displays the glossary terms defined in the glossary dictionary
+ language: "en", // en, de
+ supervisor: (company: "John Appleseed"),
+ university: "Cooperative State University Baden-Württemberg",
+ university-location: "Ravensburg Campus Friedrichshafen",
+ university-short: "DHBW",
+ // for more options check the package documentation (https://typst.app/universe/package/supercharged-dhbw)
+)
+
+// Edit this content to your liking
+
+= Introduction
+
+#lorem(100)
+
+#lorem(100)
+
+#lorem(100)
+
+= Examples
+
+#lorem(30)
+
+== Acronyms
+
+Use the `acr` function to insert acronyms, which looks like this #acr("HTTP").
+
+#acrlpl("API") are used to define the interaction between different software systems.
+
+#acrs("REST") is an architectural style for networked applications.
+
+== Glossary
+
+Use the `gls` function to insert glossary terms, which looks like this:
+
+A #gls("Vulnerability") is a weakness in a system that can be exploited.
+
+== Lists
+
+Create bullet lists or numbered lists.
+
+- This
+- is a
+- bullet list
+
++ It also
++ works with
++ numbered lists!
+
+== Figures and Tables
+
+Create figures or tables like this:
+
+=== Figures
+
+#figure(caption: "Image Example", image(width: 4cm, "assets/ts.svg"))
+
+=== Tables
+
+#figure(
+ caption: "Table Example",
+ table(
+ columns: (1fr, 50%, auto),
+ inset: 10pt,
+ align: horizon,
+ table.header(
+ [],
+ [*Area*],
+ [*Parameters*],
+ ),
+
+ text("cylinder.svg"),
+ $ pi h (D^2 - d^2) / 4 $,
+ [
+ $h$: height \
+ $D$: outer radius \
+ $d$: inner radius
+ ],
+
+ text("tetrahedron.svg"), $ sqrt(2) / 12 a^3 $, [$a$: edge length],
+ ),
+)