Compare commits
2 Commits
main
...
draft/t300
Author | SHA1 | Date |
---|---|---|
Sven Vogel | 3ebcccd74d | |
Sven Vogel | eaf803dc8d |
|
@ -1,18 +0,0 @@
|
||||||
|
|
||||||
// Reference color scheme can be found here:
|
|
||||||
// https://brand.abb/portal/en/branding-principles/basic-brand-elements/color
|
|
||||||
|
|
||||||
// ABB branding colors
|
|
||||||
#let ABB-RED = cmyk(0%, 100%, 95%, 0%)
|
|
||||||
#let ABB-BLACK = cmyk(0%, 0%, 0%, 100%)
|
|
||||||
#let ABB-GRAY-01 = cmyk(0%, 0%, 0%, 90%)
|
|
||||||
#let ABB-GRAY-02 = cmyk(0%, 0%, 0%, 75%)
|
|
||||||
#let ABB-GRAY-03 = cmyk(0%, 0%, 0%, 55%)
|
|
||||||
#let ABB-GRAY-04 = cmyk(0%, 0%, 0%, 35%)
|
|
||||||
#let ABB-GRAY-05 = cmyk(0%, 0%, 0%, 15%)
|
|
||||||
#let ABB-GRAY-06 = cmyk(0%, 0%, 0%, 5%)
|
|
||||||
#let ABB-WHITE = cmyk(0%, 0%, 0%, 0%)
|
|
||||||
// ABB branding functinal colors
|
|
||||||
#let ABB-BLUE = cmyk(100%, 53%, 2%, 16%)
|
|
||||||
#let ABB-GREEN = cmyk(91%, 4%, 100%, 25%)
|
|
||||||
#let ABB-YELLOW = cmyk(0%, 9%, 100%, 0%)
|
|
106
src/conf.typ
106
src/conf.typ
|
@ -1,106 +0,0 @@
|
||||||
|
|
||||||
// .--------------------------------------------------------------------------.
|
|
||||||
// | Configuration |
|
|
||||||
// '--------------------------------------------------------------------------'
|
|
||||||
|
|
||||||
// Author: Sven Vogel
|
|
||||||
// Edited: 27.06.2024
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
#import "branding.typ": *
|
|
||||||
|
|
||||||
// default configuration
|
|
||||||
#let default-config = (
|
|
||||||
// language settings used to make decisions about hyphenation and others
|
|
||||||
lang: "en", // ISO 3166 language code of text: "de", "en"
|
|
||||||
region: "en", // region code
|
|
||||||
// mark this thesis as draft
|
|
||||||
// Adds preleminarry note page and watermark
|
|
||||||
draft: true,
|
|
||||||
// information about author(s)
|
|
||||||
author: (
|
|
||||||
name: "Sven Vogel",
|
|
||||||
semester: 4,
|
|
||||||
program: "Informationtechnology",
|
|
||||||
course: "TINF19IT1",
|
|
||||||
faculty: "Technik",
|
|
||||||
university: "DHBW Mannheim",
|
|
||||||
company: "ABB AG",
|
|
||||||
supervisor: "Benny Goodman",
|
|
||||||
matriculation-number: 123456789),
|
|
||||||
// information about thesis
|
|
||||||
thesis: (
|
|
||||||
title: "Unofficial ABB/DHBW Typst template",
|
|
||||||
subtitle: "for reports and thesises", // subtitle may be none
|
|
||||||
submission-date: "23rd march 2020",
|
|
||||||
timeframe: "1st january 2020 - 20th march 2020",
|
|
||||||
kind: "T2000",
|
|
||||||
// translated version of abstract, only used in case language is not english
|
|
||||||
summary: none,
|
|
||||||
abstract: none,
|
|
||||||
preface: none,
|
|
||||||
keywords: ( "IT", "other stuff" ),
|
|
||||||
bibliography: none /* bibliography("refs.bib") */,
|
|
||||||
glossary: none,
|
|
||||||
appendices: none),
|
|
||||||
style: (
|
|
||||||
header: (
|
|
||||||
content-padding: 1.5em,
|
|
||||||
underline-top-padding: 0pt,
|
|
||||||
logo-height: 3em),
|
|
||||||
footer: (
|
|
||||||
content-padding: 1.5em),
|
|
||||||
page: (
|
|
||||||
format: "a4",
|
|
||||||
margin: (
|
|
||||||
left: 3cm,
|
|
||||||
right: 2.5cm,
|
|
||||||
top: 2.5cm,
|
|
||||||
bottom: 2.5cm)),
|
|
||||||
text: (
|
|
||||||
size: 12pt,
|
|
||||||
font: "Fira Sans"),
|
|
||||||
heading: (
|
|
||||||
font: "Fira Sans"),
|
|
||||||
code: (
|
|
||||||
theme: "res/abb.tmTheme",
|
|
||||||
font: "FiraCode Nerd Font",
|
|
||||||
lines: false,
|
|
||||||
size: 10pt,
|
|
||||||
tab-size: 4),
|
|
||||||
link: (
|
|
||||||
color: ABB-GRAY-02)))
|
|
||||||
|
|
||||||
// Insert a dictionary `update` into `base` but only the entries of update that also exist in base
|
|
||||||
// Runs recursively on all sub dictionaries
|
|
||||||
#let deep-insert-checked(base, update) = {
|
|
||||||
if base == none {
|
|
||||||
panic("target dictionary is none")
|
|
||||||
}
|
|
||||||
|
|
||||||
if update == none {
|
|
||||||
return base
|
|
||||||
}
|
|
||||||
|
|
||||||
for (key, val) in base {
|
|
||||||
if key in update {
|
|
||||||
let update_val = update.at(key)
|
|
||||||
|
|
||||||
if type(val) == dictionary and type(update_val) == dictionary {
|
|
||||||
base.insert(key, deep-insert-checked(val, update_val))
|
|
||||||
} else if val == none or type(val) == type(update_val) {
|
|
||||||
base.insert(key, update_val)
|
|
||||||
} else {
|
|
||||||
panic("missmatched dictionary entry `" + key + "` type: expected `" + type(val) + "` got `" + type(update_val) + "`")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
base.insert(key, val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return base
|
|
||||||
}
|
|
||||||
|
|
||||||
#let validate-config(config) = {
|
|
||||||
return deep-insert-checked(default-config, config)
|
|
||||||
}
|
|
|
@ -1,255 +0,0 @@
|
||||||
// .--------------------------------------------------------------------------.
|
|
||||||
// | Glossarium@4.1.0 with custom format |
|
|
||||||
// '--------------------------------------------------------------------------'
|
|
||||||
|
|
||||||
// Authors: ENIB-Community
|
|
||||||
// Changed: Sven Vogel
|
|
||||||
// Edited: 08.07.2024
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
// Customized version of https://github.com/ENIB-Community/glossarium/tree/release-0.4.1
|
|
||||||
// in order to conform to DHBW requirements in terms of format
|
|
||||||
|
|
||||||
/* 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.*/
|
|
||||||
|
|
||||||
// glossarium figure kind
|
|
||||||
#let __glossarium_figure = "glossarium_entry"
|
|
||||||
// prefix of label for references query
|
|
||||||
#let __glossary_label_prefix = "glossary:"
|
|
||||||
// global state containing the glossary entry and their location
|
|
||||||
#let __glossary_entries = state("__glossary_entries", (:))
|
|
||||||
|
|
||||||
#let __glossarium_error_prefix = "glossarium error : "
|
|
||||||
|
|
||||||
#let __query_labels_with_key(loc, key, before: false) = {
|
|
||||||
if before {
|
|
||||||
query(
|
|
||||||
selector(label(__glossary_label_prefix + key)).before(
|
|
||||||
loc,
|
|
||||||
inclusive: false,
|
|
||||||
),
|
|
||||||
loc,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
query(selector(label(__glossary_label_prefix + key)), loc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// key not found error
|
|
||||||
#let __not-found-panic-error-msg(key) = {
|
|
||||||
__glossarium_error_prefix + "key '" + key + "' not found"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reference a term
|
|
||||||
#let gls(key, suffix: none, long: none, display: none) = {
|
|
||||||
context {
|
|
||||||
let __glossary_entries = __glossary_entries.final(here())
|
|
||||||
if key in __glossary_entries {
|
|
||||||
let entry = __glossary_entries.at(key)
|
|
||||||
|
|
||||||
let gloss = __query_labels_with_key(here(), key, before: true)
|
|
||||||
|
|
||||||
let is_first = gloss == ()
|
|
||||||
let entlong = entry.at("long", default: "")
|
|
||||||
let textLink = if display != none {
|
|
||||||
[#display]
|
|
||||||
} else if (
|
|
||||||
is_first or long == true
|
|
||||||
) and entlong != [] and entlong != "" and long != false {
|
|
||||||
[#entlong (#entry.short#suffix)]
|
|
||||||
} else {
|
|
||||||
[#entry.short#suffix]
|
|
||||||
}
|
|
||||||
|
|
||||||
[#link(
|
|
||||||
label(entry.key),
|
|
||||||
textLink,
|
|
||||||
)#label(__glossary_label_prefix + entry.key)]
|
|
||||||
} else {
|
|
||||||
panic(__not-found-panic-error-msg(key))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reference to term with pluralisation
|
|
||||||
#let glspl(key, long: none) = {
|
|
||||||
let suffix = "s"
|
|
||||||
context {
|
|
||||||
let __glossary_entries = __glossary_entries.final(here())
|
|
||||||
if key in __glossary_entries {
|
|
||||||
let entry = __glossary_entries.at(key)
|
|
||||||
|
|
||||||
let gloss = __query_labels_with_key(here(), key, before: true)
|
|
||||||
|
|
||||||
let is_first = gloss == ()
|
|
||||||
let entlongplural = entry.at("longplural", default: "")
|
|
||||||
let entlong = if entlongplural == [] or entlongplural == "" {
|
|
||||||
// if the entry long plural is not provided, then fallback to adding 's' suffix
|
|
||||||
let entlong = entry.at("long", default: "")
|
|
||||||
if entlong != [] and entlong != "" {
|
|
||||||
[#entlong#suffix]
|
|
||||||
} else {
|
|
||||||
entlong
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
[#entlongplural]
|
|
||||||
}
|
|
||||||
|
|
||||||
let entplural = entry.at("plural", default: "")
|
|
||||||
let short = if entplural == [] or entplural == "" {
|
|
||||||
[#entry.short#suffix]
|
|
||||||
} else {
|
|
||||||
[#entplural]
|
|
||||||
}
|
|
||||||
|
|
||||||
let textLink = if (
|
|
||||||
is_first or long == true
|
|
||||||
) and entlong != [] and entlong != "" and long != false {
|
|
||||||
[#entlong (#short)]
|
|
||||||
} else {
|
|
||||||
[#short]
|
|
||||||
}
|
|
||||||
|
|
||||||
[#link(
|
|
||||||
label(entry.key),
|
|
||||||
textLink,
|
|
||||||
)#label(__glossary_label_prefix + entry.key)]
|
|
||||||
} else {
|
|
||||||
panic(__not-found-panic-error-msg(key))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// show rule to make the references for glossarium
|
|
||||||
#let make-glossary(body) = {
|
|
||||||
show ref: r => {
|
|
||||||
if r.element != none and r.element.func() == figure and r
|
|
||||||
.element
|
|
||||||
.kind == __glossarium_figure {
|
|
||||||
// call to the general citing function
|
|
||||||
gls(str(r.target), suffix: r.citation.supplement)
|
|
||||||
} else {
|
|
||||||
r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
body
|
|
||||||
}
|
|
||||||
|
|
||||||
#let __normalize-entry-list(entry_list) = {
|
|
||||||
let new-list = ()
|
|
||||||
for entry in entry_list {
|
|
||||||
new-list.push((
|
|
||||||
key: entry.key,
|
|
||||||
short: entry.short,
|
|
||||||
plural: entry.at("plural", default: ""),
|
|
||||||
long: entry.at("long", default: ""),
|
|
||||||
longplural: entry.at("longplural", default: ""),
|
|
||||||
desc: entry.at("desc", default: ""),
|
|
||||||
group: entry.at("group", default: ""),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
return new-list
|
|
||||||
}
|
|
||||||
#let print-glossary(
|
|
||||||
entry_list,
|
|
||||||
show-all: false,
|
|
||||||
disable-back-references: false,
|
|
||||||
enable-group-pagebreak: false,
|
|
||||||
) = {
|
|
||||||
let entries = __normalize-entry-list(entry_list)
|
|
||||||
__glossary_entries.update(x => {
|
|
||||||
for entry in entry_list {
|
|
||||||
x.insert(entry.key, entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
x
|
|
||||||
})
|
|
||||||
|
|
||||||
let groups = entries.map(x => x.at("group")).dedup()
|
|
||||||
|
|
||||||
for group in groups.sorted() {
|
|
||||||
if group != "" [#heading(group, level: 1, outlined: false) ]
|
|
||||||
for entry in entries.sorted(key: x => x.key) {
|
|
||||||
if entry.group == group {
|
|
||||||
[
|
|
||||||
#show figure.where(kind: __glossarium_figure): it => it.caption
|
|
||||||
#figure(
|
|
||||||
supplement: "",
|
|
||||||
kind: __glossarium_figure,
|
|
||||||
numbering: none,
|
|
||||||
caption: {
|
|
||||||
context {
|
|
||||||
let key = if entry.key.ends-with("__glossary_entry") {
|
|
||||||
entry.key.replace("__glossary_entry", "")
|
|
||||||
} else {
|
|
||||||
entry.key
|
|
||||||
}
|
|
||||||
|
|
||||||
let term_references = __query_labels_with_key(here(), key)
|
|
||||||
if term_references.len() != 0 or show-all [
|
|
||||||
#let desc = entry.at("desc", default: "")
|
|
||||||
#let long = entry.at("long", default: "")
|
|
||||||
#let hasLong = long != "" and long != []
|
|
||||||
#let hasDesc = desc != "" and desc != []
|
|
||||||
|
|
||||||
#block(
|
|
||||||
below: 1.5em,
|
|
||||||
par(hanging-indent: 1em)[
|
|
||||||
#text(weight: "bold", entry.short)
|
|
||||||
#if hasLong and hasDesc [
|
|
||||||
(#text(entry.long))
|
|
||||||
] else if hasLong {
|
|
||||||
text(entry.long)
|
|
||||||
}
|
|
||||||
#if hasDesc [ #sym.dash.en ]
|
|
||||||
#if hasDesc [ #desc ]
|
|
||||||
#if disable-back-references != true {
|
|
||||||
term_references
|
|
||||||
.map(x => x.location())
|
|
||||||
.sorted(key: x => x.page())
|
|
||||||
.fold(
|
|
||||||
(values: (), pages: ()),
|
|
||||||
((values, pages), x) => if pages.contains(
|
|
||||||
x.page(),
|
|
||||||
) {
|
|
||||||
(values: values, pages: pages)
|
|
||||||
} else {
|
|
||||||
values.push(x)
|
|
||||||
pages.push(x.page())
|
|
||||||
(values: values, pages: pages)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.values
|
|
||||||
.map(x => {
|
|
||||||
let page-numbering = x.page-numbering()
|
|
||||||
if page-numbering == none {
|
|
||||||
page-numbering = "1"
|
|
||||||
}
|
|
||||||
link(x)[#numbering(
|
|
||||||
page-numbering,
|
|
||||||
..counter(page).at(x),
|
|
||||||
)]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.join(", ")
|
|
||||||
}
|
|
||||||
],
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)[] #label(entry.key)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if enable-group-pagebreak {
|
|
||||||
pagebreak(weak: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
100
src/glossary.typ
100
src/glossary.typ
|
@ -1,100 +0,0 @@
|
||||||
|
|
||||||
// .--------------------------------------------------------------------------.
|
|
||||||
// | Glossary Utilities |
|
|
||||||
// '--------------------------------------------------------------------------'
|
|
||||||
|
|
||||||
// Author: Sven Vogel
|
|
||||||
// Edited: 08.07.2024
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
#let glossary(entries, config) = {
|
|
||||||
|
|
||||||
assert(
|
|
||||||
type(entries) == dictionary,
|
|
||||||
message: "The glossary is not a dictionary",
|
|
||||||
)
|
|
||||||
|
|
||||||
let processed_glossary = (:)
|
|
||||||
|
|
||||||
for (k, v) in entries.pairs() {
|
|
||||||
assert(
|
|
||||||
type(v) == dictionary,
|
|
||||||
message: "The glossary entry `" + k + "` is not a dictionary",
|
|
||||||
)
|
|
||||||
|
|
||||||
for key in v.keys() {
|
|
||||||
assert(
|
|
||||||
key in ("short", "long", "desc", "group"),
|
|
||||||
message: "Found unexpected key `" + key + "` in glossary entry `" + k,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(
|
|
||||||
type(v.short) == str,
|
|
||||||
message: "The short form of glossary entry `" + k + "` is not a string",
|
|
||||||
)
|
|
||||||
|
|
||||||
if "long" in v {
|
|
||||||
assert(
|
|
||||||
type(v.long) == str,
|
|
||||||
message: "The long form of glossary entry `" + k + "` is not a string",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if "desc" in v {
|
|
||||||
assert(
|
|
||||||
type(v.desc) == str,
|
|
||||||
message: "The description of glossary entry `" + k + "` is not a string",
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if "group" in v {
|
|
||||||
assert(
|
|
||||||
type(v.group) == str,
|
|
||||||
message: "The optional group of glossary entry `" + k + "` is not a string",
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
let acronym_group = if config.lang == "de" {
|
|
||||||
"Abkürzungsverzeichnis"
|
|
||||||
} else {
|
|
||||||
"List of Acronyms"
|
|
||||||
}
|
|
||||||
|
|
||||||
let glossary_group = if config.lang == "de" {
|
|
||||||
"Begriffe"
|
|
||||||
} else {
|
|
||||||
"Glossary"
|
|
||||||
}
|
|
||||||
|
|
||||||
let group = if "long" in v {
|
|
||||||
acronym_group
|
|
||||||
} else {
|
|
||||||
glossary_group
|
|
||||||
}
|
|
||||||
|
|
||||||
// create dedicated entries for
|
|
||||||
// acronym and glossary
|
|
||||||
if "long" in v and "desc" in v {
|
|
||||||
processed_glossary.insert(
|
|
||||||
k,
|
|
||||||
(short: v.short, long: v.long, group: acronym_group),
|
|
||||||
)
|
|
||||||
processed_glossary.insert(
|
|
||||||
k + "__glossary_entry",
|
|
||||||
(short: v.short, desc: v.desc, long: v.long, group: glossary_group),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
processed_glossary.insert(k, v)
|
|
||||||
processed_glossary.at(k).group = group
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return processed_glossary.pairs().map(((key, entry)) => (
|
|
||||||
key: key,
|
|
||||||
short: entry.short,
|
|
||||||
long: eval(entry.at("long", default: ""), mode: "markup"),
|
|
||||||
desc: eval(entry.at("desc", default: ""), mode: "markup"),
|
|
||||||
group: entry.at("group", default: ""),
|
|
||||||
))
|
|
||||||
}
|
|
153
src/lib.typ
153
src/lib.typ
|
@ -4,133 +4,54 @@
|
||||||
// '--------------------------------------------------------------------------'
|
// '--------------------------------------------------------------------------'
|
||||||
|
|
||||||
// Author: Sven Vogel
|
// Author: Sven Vogel
|
||||||
// Edited: 27.06.2024
|
// Edited: 01.10.2024
|
||||||
// License: MIT
|
// License: MIT
|
||||||
|
|
||||||
#import "conf.typ": validate-config, default-config
|
|
||||||
#import "branding.typ": *
|
|
||||||
#import "style.typ": global_styled_doc, content_styled, end_styled
|
|
||||||
#import "glossary.typ": glossary
|
|
||||||
#import "pages/titlepage.typ": new_title_page
|
|
||||||
#import "pages/declaration-of-authorship.typ": new_declaration_of_authorship
|
|
||||||
#import "pages/confidentiality-statement.typ": new_confidentiality_statement_page
|
|
||||||
#import "pages/prerelease-note.typ": new_prerelease_note
|
|
||||||
#import "pages/outline.typ": new_outline
|
|
||||||
#import "pages/abstract.typ": new_abstract
|
|
||||||
#import "pages/preface.typ": new-preface
|
|
||||||
#import "pages/appendix.typ": show-appendix
|
|
||||||
|
|
||||||
#let group-break() = {
|
|
||||||
[#pagebreak()]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let inline-color(color, content) = {
|
|
||||||
box(
|
|
||||||
stroke: 1pt + ABB-GRAY-05,
|
|
||||||
radius: 2pt,
|
|
||||||
inset: (left: 2pt, right: 2pt),
|
|
||||||
outset: (top: 4pt, bottom: 4pt),
|
|
||||||
fill: ABB-GRAY-06,
|
|
||||||
[#box(
|
|
||||||
fill: rgb(color),
|
|
||||||
radius: 2pt,
|
|
||||||
inset: 0pt,
|
|
||||||
width: 0.75em,
|
|
||||||
height: 0.75em,
|
|
||||||
) #text(
|
|
||||||
font: default-config.style.code.font,
|
|
||||||
size: default-config.style.code.size,
|
|
||||||
content,
|
|
||||||
)],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let url(label, content) = {
|
|
||||||
link(label)[#underline(
|
|
||||||
offset: 2pt,
|
|
||||||
stroke: 0.5pt + blue,
|
|
||||||
text(fill: blue)[
|
|
||||||
#content
|
|
||||||
#let domain = label.find(regex("\w+\.\w+(?:\.\w+)*"))
|
|
||||||
#if domain.len() > 0 [
|
|
||||||
(#domain)
|
|
||||||
]
|
|
||||||
],
|
|
||||||
)]
|
|
||||||
}
|
|
||||||
|
|
||||||
// start of template pages and styles
|
// start of template pages and styles
|
||||||
#let dhbw-template(config, body) = [
|
#let dhbw-template(body) = [
|
||||||
#let config = validate-config(config)
|
|
||||||
#let doc = body
|
|
||||||
|
|
||||||
// apply global style to every element in the argument content
|
#set page(margin: 2.5cm, footer: counter(page).display())
|
||||||
#global_styled_doc(config)[
|
#set text(size: 10pt, font: "Times New Roman")
|
||||||
|
#set par(justify: true)
|
||||||
|
#set block(below: 1em, above: 0pt)
|
||||||
|
|
||||||
// set document properties
|
#show heading.where(level: 1): it => align(center, pad(top: 0.85cm, text(size: 12pt, it)))
|
||||||
#set document(
|
#show heading.where(level: 2): it => text(size: 10pt, it)
|
||||||
author: config.author.name,
|
|
||||||
keywords: config.thesis.keywords,
|
#show raw: it => text(font: "Consolas", size: 8pt, it)
|
||||||
title: config.thesis.title,
|
|
||||||
|
#set align(center)
|
||||||
|
#block(below: 0.85cm, text(size: 16pt, weight: "bold", "Title"))
|
||||||
|
|
||||||
|
#let authors = (
|
||||||
|
(
|
||||||
|
name: "Johann Goethe",
|
||||||
|
matriculation-number: 123456789,
|
||||||
|
company: "SAP",
|
||||||
|
e-mail: "johann-goether@sap.de",
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
// configure text locale
|
#grid(columns: authors.len(), column-gutter: 0.95cm, rows: 1, ..authors.map(author => block()[
|
||||||
#set text(
|
#text(size: 10pt, weight: "bold", author.name)
|
||||||
lang: config.lang,
|
#set text(size: 9pt)
|
||||||
region: config.region,
|
#linebreak()
|
||||||
)
|
#author.matriculation-number, #author.company
|
||||||
|
#linebreak()
|
||||||
|
#author.e-mail
|
||||||
|
]))
|
||||||
|
|
||||||
// preppend title page
|
#v(10pt)
|
||||||
#new_title_page(config)
|
|
||||||
|
|
||||||
// prelude includes: title, declaration of authorship, confidentiality statement, outline and abstract
|
#set align(left)
|
||||||
// these will have roman page numbers
|
#columns(gutter: 0.95cm)[
|
||||||
#new_declaration_of_authorship(config)
|
#align(center, text(weight: "bold", size: 10pt, "Abstract"))
|
||||||
#new_confidentiality_statement_page(config)
|
#lorem(20)
|
||||||
#if config.draft {
|
|
||||||
new_prerelease_note(config)
|
|
||||||
}
|
|
||||||
#new_abstract(config)
|
|
||||||
#new-preface(config)
|
|
||||||
#new_outline()
|
|
||||||
|
|
||||||
// glossary is built inline here because the links must be
|
#body
|
||||||
// exposed to the entire document
|
|
||||||
#import "glossarium.typ": *
|
|
||||||
#show: make-glossary
|
|
||||||
|
|
||||||
#pagebreak(weak: true)
|
#align(center, pad(top: 1em, text(weight: "bold", size: 10pt, "Citations and references")))
|
||||||
|
|
||||||
#if "glossary" in config.thesis and config.thesis.glossary != none {
|
#bibliography("../template/refs.bib", title: none, style: "annual-reviews-author-date")
|
||||||
print-glossary(
|
|
||||||
show-all: false,
|
|
||||||
disable-back-references: true,
|
|
||||||
enable-group-pagebreak: true,
|
|
||||||
glossary(config.thesis.glossary, config),
|
|
||||||
)
|
|
||||||
|
|
||||||
pagebreak(weak: true)
|
|
||||||
}
|
|
||||||
#counter(page).update(1)
|
|
||||||
|
|
||||||
// mark end of prelude
|
|
||||||
#metadata("prelude terminate") <end-of-prelude>
|
|
||||||
|
|
||||||
#content_styled(config, doc)
|
|
||||||
|
|
||||||
#metadata("content terminate") <end-of-content>
|
|
||||||
|
|
||||||
#end_styled(config)[
|
|
||||||
// add bibliography if set
|
|
||||||
#if "bibliography" in config.thesis and config.thesis.bibliography != none {
|
|
||||||
pagebreak(weak: true)
|
|
||||||
counter(page).update(1)
|
|
||||||
set bibliography(style: "ieee")
|
|
||||||
config.thesis.bibliography
|
|
||||||
}
|
|
||||||
|
|
||||||
// appendix
|
|
||||||
#show-appendix(config: config)
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
// .--------------------------------------------------------------------------.
|
|
||||||
// | Abstract |
|
|
||||||
// '--------------------------------------------------------------------------'
|
|
||||||
|
|
||||||
// Author: Sven Vogel
|
|
||||||
// Edited: 28.06.2024
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
#let new_abstract(config) = (
|
|
||||||
context {
|
|
||||||
|
|
||||||
set align(center + horizon)
|
|
||||||
|
|
||||||
// only include summary when a language other than english is used
|
|
||||||
if text.lang == "de" [
|
|
||||||
// Summary is supposed to be on separate page
|
|
||||||
#pagebreak(weak: true)
|
|
||||||
|
|
||||||
= Zusammenfassung
|
|
||||||
#config.thesis.summary
|
|
||||||
]
|
|
||||||
|
|
||||||
// abstract is supposed to be on separate page
|
|
||||||
pagebreak(weak: true)
|
|
||||||
|
|
||||||
heading("Abstract")
|
|
||||||
config.thesis.abstract
|
|
||||||
}
|
|
||||||
)
|
|
|
@ -1,46 +0,0 @@
|
||||||
// .--------------------------------------------------------------------------.
|
|
||||||
// | Appendix |
|
|
||||||
// '--------------------------------------------------------------------------'
|
|
||||||
|
|
||||||
// Author: Sven Vogel
|
|
||||||
// Edited: 28.06.2024
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
#let show-appendix(config: dictionary) = (
|
|
||||||
context {
|
|
||||||
counter(heading).update(0)
|
|
||||||
|
|
||||||
let title = if text.lang == "en" {
|
|
||||||
"Appendix"
|
|
||||||
} else {
|
|
||||||
"Anhang"
|
|
||||||
}
|
|
||||||
|
|
||||||
if "appendices" in config.thesis {
|
|
||||||
pagebreak(weak: true)
|
|
||||||
|
|
||||||
// appendix will be invisible on the appendecies page
|
|
||||||
// but still listed in the ToC
|
|
||||||
show heading: it => []
|
|
||||||
heading(level: 1, numbering: none, title)
|
|
||||||
|
|
||||||
// APA style appendix
|
|
||||||
show heading: it => {
|
|
||||||
let number = if it.numbering != none {
|
|
||||||
counter(heading).display(it.numbering)
|
|
||||||
}
|
|
||||||
block()[
|
|
||||||
#title #number - #it.body
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
show heading.where(level: 1): it => 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)
|
|
||||||
|
|
||||||
set heading(numbering: "A.1", supplement: title)
|
|
||||||
|
|
||||||
config.thesis.appendices
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
|
@ -1,64 +0,0 @@
|
||||||
// .--------------------------------------------------------------------------.
|
|
||||||
// | Confidentiality Statement |
|
|
||||||
// '--------------------------------------------------------------------------'
|
|
||||||
|
|
||||||
// Author: Sven Vogel
|
|
||||||
// Edited: 28.06.2024
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
#let new_confidentiality_statement_page(config) = (
|
|
||||||
context {
|
|
||||||
|
|
||||||
pagebreak(weak: true)
|
|
||||||
|
|
||||||
let thesis = config.thesis
|
|
||||||
let author = config.author
|
|
||||||
|
|
||||||
if text.lang == "de" [
|
|
||||||
#heading(level: 1, "Sperrvermerk")
|
|
||||||
] else if text.lang == "en" [
|
|
||||||
#heading(level: 1, "Confidentiality Statement")
|
|
||||||
]
|
|
||||||
|
|
||||||
if text.lang == "de" [
|
|
||||||
Der Inhalt dieser Arbeit mit dem Thema
|
|
||||||
] else if text.lang == "en" [
|
|
||||||
The content of this work with the topic
|
|
||||||
]
|
|
||||||
|
|
||||||
v(1em)
|
|
||||||
|
|
||||||
set align(center)
|
|
||||||
|
|
||||||
text(weight: "bold", thesis.title)
|
|
||||||
|
|
||||||
if thesis.subtitle != none {
|
|
||||||
linebreak()
|
|
||||||
thesis.subtitle
|
|
||||||
}
|
|
||||||
|
|
||||||
set align(left)
|
|
||||||
|
|
||||||
v(1em)
|
|
||||||
|
|
||||||
set par(justify: true)
|
|
||||||
|
|
||||||
if text.lang == "de" [
|
|
||||||
darf weder als Ganzes noch in Auszügen Personen außerhalb des Prüfungsprozesses und des Evaluationsverfahrens zugänglich gemacht werden, sofern keine anderslautende Genehmigung der Ausbildungsstätte vorliegt.
|
|
||||||
] else if text.lang == "en" [
|
|
||||||
may not be made accessible to persons outside the examination process and the evaluation procedure, either as a whole or in excerpts, unless otherwise authorized by the training institution.
|
|
||||||
]
|
|
||||||
|
|
||||||
set align(horizon)
|
|
||||||
|
|
||||||
grid(
|
|
||||||
// set width of columns
|
|
||||||
// we need two, so make both half the page width
|
|
||||||
columns: (50%, 50%),
|
|
||||||
row-gutter: 0.75em,
|
|
||||||
align(left, {line(length: 6cm)}),
|
|
||||||
align(left, {line(length: 6cm)}),
|
|
||||||
align(left, if text.lang == "de" [ Ort, Datum ] else if text.lang == "en" [ Place, Date ] else { panic("no translation for language: ", text.lang) }),
|
|
||||||
align(left, if text.lang == "de" [ Unterschrift ] else if text.lang == "en" [ Signature ] else { panic("no translation for language: ", text.lang) }))
|
|
||||||
}
|
|
||||||
)
|
|
|
@ -1,66 +0,0 @@
|
||||||
// .--------------------------------------------------------------------------.
|
|
||||||
// | Declaration of Authorship |
|
|
||||||
// '--------------------------------------------------------------------------'
|
|
||||||
|
|
||||||
// Author: Sven Vogel
|
|
||||||
// Edited: 28.06.2024
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
#let new_declaration_of_authorship(config) = (
|
|
||||||
context {
|
|
||||||
|
|
||||||
pagebreak(weak: true)
|
|
||||||
|
|
||||||
let thesis = config.thesis
|
|
||||||
let author = config.author
|
|
||||||
|
|
||||||
if text.lang == "de" [
|
|
||||||
#heading("Selbständigkeitserklärung")
|
|
||||||
] else if text.lang == "en" [
|
|
||||||
#heading("Declaration of Authorship")
|
|
||||||
]
|
|
||||||
|
|
||||||
v(1em)
|
|
||||||
|
|
||||||
if text.lang == "de" [
|
|
||||||
Ich versichere hiermit, dass ich meine Prüfung mit dem Thema
|
|
||||||
] else if text.lang == "en" [
|
|
||||||
I hereby confirm that I have written this thesis with the subject
|
|
||||||
]
|
|
||||||
|
|
||||||
v(1em)
|
|
||||||
|
|
||||||
set align(center)
|
|
||||||
|
|
||||||
text(weight: "bold", thesis.title)
|
|
||||||
|
|
||||||
if thesis.subtitle != none {
|
|
||||||
linebreak()
|
|
||||||
thesis.subtitle
|
|
||||||
}
|
|
||||||
|
|
||||||
set align(left)
|
|
||||||
|
|
||||||
v(1em)
|
|
||||||
|
|
||||||
set par(justify: true)
|
|
||||||
|
|
||||||
if text.lang == "de" [
|
|
||||||
selbständig verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel benutzt habe. Ich versichere zudem, dass die eingereichte elektronische Fassung mit der gedruckten Fassung übereinstimmt.
|
|
||||||
] else if text.lang == "en" [
|
|
||||||
independently and have not used any sources or aids other than those specified. I also confirm that the electronic version submitted is identical to the printed version.
|
|
||||||
]
|
|
||||||
|
|
||||||
set align(horizon)
|
|
||||||
|
|
||||||
grid(
|
|
||||||
// set width of columns
|
|
||||||
// we need two, so make both half the page width
|
|
||||||
columns: (50%, 50%),
|
|
||||||
row-gutter: 0.75em,
|
|
||||||
align(left, {line(length: 6cm)}),
|
|
||||||
align(left, {line(length: 6cm)}),
|
|
||||||
align(left, if text.lang == "de" [ Ort, Datum ] else if text.lang == "en" [ Place, Date ] else { panic("no translation for language: ", text.lang) }),
|
|
||||||
align(left, if text.lang == "de" [ Unterschrift ] else if text.lang == "en" [ Signature ] else { panic("no translation for language: ", text.lang) }))
|
|
||||||
}
|
|
||||||
)
|
|
|
@ -1,140 +0,0 @@
|
||||||
// .--------------------------------------------------------------------------.
|
|
||||||
// | Document Outline |
|
|
||||||
// '--------------------------------------------------------------------------'
|
|
||||||
|
|
||||||
// Author: Sven Vogel
|
|
||||||
// Edited: 28.06.2024
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
// render an outline of figures
|
|
||||||
// with a specific title and filter by a specifc kind of figure
|
|
||||||
// can optionally insert a pagebreak after the outline
|
|
||||||
// NOTE: will not render in case the listing is empty
|
|
||||||
#let render_filtered_outline(title: str, kind: selector) = (
|
|
||||||
context {
|
|
||||||
|
|
||||||
let elems = query(figure.where(kind: kind), here())
|
|
||||||
let count = elems.len()
|
|
||||||
|
|
||||||
show outline.entry: it => {
|
|
||||||
link(it.element.location())[
|
|
||||||
#v(12pt, weak: true)
|
|
||||||
#text(weight: "regular", it.body)
|
|
||||||
#box(width: 1fr, it.fill)
|
|
||||||
#[ #it.page]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// only show outline if there is something to list
|
|
||||||
if count > 0 {
|
|
||||||
pagebreak(weak: true)
|
|
||||||
outline(
|
|
||||||
title: title,
|
|
||||||
target: figure.where(kind: kind),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
#let render_figures_outline() = (
|
|
||||||
context {
|
|
||||||
let title = if (text.lang == "de") {
|
|
||||||
"Abbildungsverzeichnis"
|
|
||||||
} else if text.lang == "en" {
|
|
||||||
"List of Figures"
|
|
||||||
}
|
|
||||||
|
|
||||||
render_filtered_outline(title: title, kind: image)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
#let render_table_outline() = (
|
|
||||||
context {
|
|
||||||
let title = if (text.lang == "de") {
|
|
||||||
"Tabellenverzeichnis"
|
|
||||||
} else if text.lang == "en" {
|
|
||||||
"List of Tables"
|
|
||||||
}
|
|
||||||
|
|
||||||
render_filtered_outline(title: title, kind: table)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
#let render_raw_outline() = (
|
|
||||||
context {
|
|
||||||
let title = if (text.lang == "de") {
|
|
||||||
"Quelltextverzeichnis"
|
|
||||||
} else if text.lang == "en" {
|
|
||||||
"Code Snippets"
|
|
||||||
}
|
|
||||||
|
|
||||||
render_filtered_outline(title: title, kind: raw)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
#let render_heading_outline() = (
|
|
||||||
context {
|
|
||||||
let title = if (text.lang == "de") {
|
|
||||||
"Inhaltsverzeichnis"
|
|
||||||
} else if text.lang == "en" {
|
|
||||||
"Table of Contents"
|
|
||||||
}
|
|
||||||
|
|
||||||
let header-supplement = if (text.lang == "de") {
|
|
||||||
"Kapitel"
|
|
||||||
} else {
|
|
||||||
"chapter"
|
|
||||||
}
|
|
||||||
|
|
||||||
pagebreak(weak: true)
|
|
||||||
outline(
|
|
||||||
target: heading.where(supplement: [#header-supplement]),
|
|
||||||
title: title,
|
|
||||||
indent: auto,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
#let render_appendix_outline() = (
|
|
||||||
context {
|
|
||||||
let supplement = if text.lang == "en" {
|
|
||||||
[Appendix]
|
|
||||||
} else {
|
|
||||||
[Anhang]
|
|
||||||
}
|
|
||||||
|
|
||||||
if query(heading.where(supplement: supplement)).len() > 0 {
|
|
||||||
let title = if (text.lang == "de") {
|
|
||||||
"Anhangsverzeichnis"
|
|
||||||
} else if text.lang == "en" {
|
|
||||||
"Table of Appendices"
|
|
||||||
}
|
|
||||||
|
|
||||||
pagebreak(weak: true)
|
|
||||||
outline(
|
|
||||||
target: heading.where(supplement: supplement),
|
|
||||||
title: title,
|
|
||||||
indent: auto,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
#let new_outline() = {
|
|
||||||
pagebreak(weak: true)
|
|
||||||
|
|
||||||
show outline.entry.where(level: 1): it => {
|
|
||||||
v(1.5em, weak: true)
|
|
||||||
strong(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
render_heading_outline()
|
|
||||||
|
|
||||||
render_figures_outline()
|
|
||||||
|
|
||||||
render_table_outline()
|
|
||||||
|
|
||||||
render_raw_outline()
|
|
||||||
|
|
||||||
render_appendix_outline()
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
// .--------------------------------------------------------------------------.
|
|
||||||
// | Preface |
|
|
||||||
// '--------------------------------------------------------------------------'
|
|
||||||
|
|
||||||
// Author: Sven Vogel
|
|
||||||
// Edited: 28.06.2024
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
#let new-preface(config) = {
|
|
||||||
if config.thesis.preface != none {
|
|
||||||
pagebreak(weak: true)
|
|
||||||
config.thesis.preface
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
// .--------------------------------------------------------------------------.
|
|
||||||
// | Preleminary release Notice |
|
|
||||||
// '--------------------------------------------------------------------------'
|
|
||||||
|
|
||||||
// Author: Sven Vogel
|
|
||||||
// Edited: 28.06.2024
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
#let new_prerelease_note(config) = (
|
|
||||||
context {
|
|
||||||
|
|
||||||
pagebreak(weak: true)
|
|
||||||
|
|
||||||
let thesis = config.thesis
|
|
||||||
let author = config.author
|
|
||||||
|
|
||||||
if text.lang == "de" [
|
|
||||||
#heading("Vorabfassung")
|
|
||||||
] else if text.lang == "en" [
|
|
||||||
#heading("Preliminary Version")
|
|
||||||
]
|
|
||||||
|
|
||||||
v(1em)
|
|
||||||
|
|
||||||
if text.lang == "de" [
|
|
||||||
Bei dieser Ausgabe der Arbeit mit dem Thema
|
|
||||||
] else if text.lang == "en" [
|
|
||||||
This edition of the work with the subject
|
|
||||||
]
|
|
||||||
|
|
||||||
v(1em)
|
|
||||||
|
|
||||||
set align(center)
|
|
||||||
|
|
||||||
text(weight: "bold", thesis.title)
|
|
||||||
|
|
||||||
if thesis.subtitle != none {
|
|
||||||
linebreak()
|
|
||||||
thesis.subtitle
|
|
||||||
}
|
|
||||||
|
|
||||||
set align(left)
|
|
||||||
|
|
||||||
v(1em)
|
|
||||||
|
|
||||||
set par(justify: true)
|
|
||||||
|
|
||||||
if text.lang == "de" [
|
|
||||||
handelt es sich _nicht_ um die fertige Fassung. Das Dokument kann Inhaltliche-, Grammatikalische- sowie Format-Fehler enthalten. Das Dokument ist im Rahmen der Aufgabenstellung von Seiten der #author.university nicht zur Bewertung freigegeben und ein anderer Verwendungszweck als eine Vorschau ist nicht gestattet.
|
|
||||||
] else if text.lang == "en" [
|
|
||||||
is not the final version. The document may contain errors in content, grammar and formatting. The document may not be released for evaluation to #author.university as part of the assignment, and any use other than a preview is not permitted.
|
|
||||||
]
|
|
||||||
|
|
||||||
v(1em)
|
|
||||||
h(1em)
|
|
||||||
[#author.name, #datetime.today().display()]
|
|
||||||
}
|
|
||||||
)
|
|
|
@ -1,110 +0,0 @@
|
||||||
// .--------------------------------------------------------------------------.
|
|
||||||
// | Titlepage |
|
|
||||||
// '--------------------------------------------------------------------------'
|
|
||||||
|
|
||||||
// Author: Sven Vogel
|
|
||||||
// Edited: 28.06.2024
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
#let new_title_page(config) = (
|
|
||||||
context [
|
|
||||||
|
|
||||||
#let thesis = config.thesis
|
|
||||||
#let author = config.author
|
|
||||||
|
|
||||||
#set align(center)
|
|
||||||
|
|
||||||
// title
|
|
||||||
#v(2cm)
|
|
||||||
#par(justify: false, leading: 1.5em)[
|
|
||||||
#text(size: 2em, weight: "bold", hyphenate: false, thesis.title)
|
|
||||||
#linebreak()
|
|
||||||
// subtitle
|
|
||||||
#text(size: 2em, weight: "light", thesis.subtitle)
|
|
||||||
]
|
|
||||||
|
|
||||||
#set align(center + horizon)
|
|
||||||
|
|
||||||
// type of paper
|
|
||||||
#text(size: 1.5em, weight: "medium", thesis.kind)
|
|
||||||
|
|
||||||
// faculty
|
|
||||||
#pad()[
|
|
||||||
#if text.lang == "de" [
|
|
||||||
Praxisphase des #author.semester Semesters an der Fakultät für #author.faculty
|
|
||||||
#linebreak()
|
|
||||||
im Studiengang #author.program
|
|
||||||
] else if text.lang == "en" [
|
|
||||||
Practical phase of the #author.semester semester at the Faculty of #author.faculty
|
|
||||||
#linebreak()
|
|
||||||
in the degree program #author.program
|
|
||||||
] else [
|
|
||||||
#context panic("no translation for language: ", text.lang)
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
// university
|
|
||||||
#pad()[
|
|
||||||
#if text.lang == "de" [
|
|
||||||
an der
|
|
||||||
] else if text.lang == "en" [
|
|
||||||
at
|
|
||||||
] else [
|
|
||||||
#context panic("no translation for language: ", text.lang)
|
|
||||||
]
|
|
||||||
#linebreak()
|
|
||||||
#author.university
|
|
||||||
]
|
|
||||||
|
|
||||||
#set align(bottom + left)
|
|
||||||
|
|
||||||
#if text.lang == "de" [
|
|
||||||
#table(
|
|
||||||
columns: 2,
|
|
||||||
column-gutter: 1cm,
|
|
||||||
align: left,
|
|
||||||
stroke: none,
|
|
||||||
[*Verfasser:*], author.name,
|
|
||||||
[*Bearbeitungszeitraum:*], thesis.timeframe,
|
|
||||||
[*Matrikelnummer, Kurs:*], str(author.matriculation-number) + ", " + author.course,
|
|
||||||
[*Ausbildungsbetrieb:*], author.company,
|
|
||||||
[*Betrieblicher Betreuer:*], author.supervisor,
|
|
||||||
[*Abgabedatum:*], thesis.submission-date,
|
|
||||||
)
|
|
||||||
] else if text.lang == "en" [
|
|
||||||
#table(
|
|
||||||
columns: 2,
|
|
||||||
column-gutter: 1cm,
|
|
||||||
align: left,
|
|
||||||
stroke: none,
|
|
||||||
[*Author:*], author.name,
|
|
||||||
[*Editing period:*], thesis.timeframe,
|
|
||||||
[*Matriculation number, course:*], str(author.matriculation-number) + ", " + author.course,
|
|
||||||
[*Training company:*], author.company,
|
|
||||||
[*Company supervisor:*], author.supervisor,
|
|
||||||
[*Submission date:*], thesis.submission-date,
|
|
||||||
)
|
|
||||||
] else [
|
|
||||||
#context panic("no translation for language: ", text.lang)
|
|
||||||
]
|
|
||||||
|
|
||||||
#align(
|
|
||||||
bottom,
|
|
||||||
grid(
|
|
||||||
// set width of columns
|
|
||||||
// we need two, so make both half the page width
|
|
||||||
columns: (60%, 40%),
|
|
||||||
align(left, if text.lang == "de" [
|
|
||||||
Unterschrift des betrieblichen Betreuers
|
|
||||||
] else if text.lang == "en" [
|
|
||||||
Signature of the company supervisor
|
|
||||||
] else [
|
|
||||||
#context panic("no translation for language: ", text.lang)
|
|
||||||
]
|
|
||||||
),
|
|
||||||
align(right, {line(length: 6cm)})),
|
|
||||||
)
|
|
||||||
|
|
||||||
#counter(page).update(0)
|
|
||||||
]
|
|
||||||
)
|
|
|
@ -1,10 +0,0 @@
|
||||||
|
|
||||||
// .--------------------------------------------------------------------------.
|
|
||||||
// | Required packages for template use |
|
|
||||||
// '--------------------------------------------------------------------------'
|
|
||||||
|
|
||||||
// Author: Sven Vogel
|
|
||||||
// Edited: 05.07.2024
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
#import "glossary.typ": *
|
|
342
src/style.typ
342
src/style.typ
|
@ -1,342 +0,0 @@
|
||||||
|
|
||||||
// .--------------------------------------------------------------------------.
|
|
||||||
// | Global style of document |
|
|
||||||
// '--------------------------------------------------------------------------'
|
|
||||||
|
|
||||||
// Author: Sven Vogel
|
|
||||||
// Edited: 27.06.2024
|
|
||||||
// License: MIT
|
|
||||||
|
|
||||||
#import "branding.typ": *
|
|
||||||
|
|
||||||
#let watermark-color = luma(50%).transparentize(70%)
|
|
||||||
|
|
||||||
#let watermark-pattern = pattern(size: (5pt, 5pt))[
|
|
||||||
#place(
|
|
||||||
line(
|
|
||||||
start: (50%, 0%),
|
|
||||||
end: (50%, 100%),
|
|
||||||
stroke: (paint: watermark-color, thickness: 3pt),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
#let watermark(config) = if config.draft {
|
|
||||||
rotate(-22.5deg)[
|
|
||||||
#rect(
|
|
||||||
radius: 1em,
|
|
||||||
inset: 1em,
|
|
||||||
stroke: watermark-color,
|
|
||||||
)[
|
|
||||||
#text(size: 4em, weight: "bold", fill: watermark-pattern, "DRAFT")
|
|
||||||
#linebreak()
|
|
||||||
#text(size: 1.25em, weight: "bold", fill: watermark-color)[
|
|
||||||
This page is part of a preliminary
|
|
||||||
#linebreak()
|
|
||||||
document version.
|
|
||||||
#linebreak()
|
|
||||||
#text(
|
|
||||||
size: 0.75em,
|
|
||||||
"Further usage without the authors consent is not permitted.",
|
|
||||||
)]]]
|
|
||||||
}
|
|
||||||
|
|
||||||
#let numberingH(c) = {
|
|
||||||
return numbering(c.numbering, ..counter(heading).at(c.location()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#let currentH(level: 1) = {
|
|
||||||
let elems = query(selector(heading.where(level: level)).after(here()))
|
|
||||||
|
|
||||||
if elems.len() != 0 and elems.first().location().page() == here().page() {
|
|
||||||
return (numberingH(elems.first()), elems.first().body)
|
|
||||||
} else {
|
|
||||||
elems = query(selector(heading.where(level: level)).before(here()))
|
|
||||||
if elems.len() != 0 {
|
|
||||||
return (numberingH(elems.last()), elems.last().body)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// global style of document
|
|
||||||
#let global_styled_doc(config, body) = {
|
|
||||||
let thesis = config.thesis
|
|
||||||
let style = config.style
|
|
||||||
|
|
||||||
set text(
|
|
||||||
size: style.text.size,
|
|
||||||
ligatures: true,
|
|
||||||
hyphenate: true,
|
|
||||||
dir: ltr,
|
|
||||||
font: style.text.font,
|
|
||||||
fill: ABB-BLACK,
|
|
||||||
)
|
|
||||||
|
|
||||||
show heading: set text(
|
|
||||||
font: style.heading.font,
|
|
||||||
weight: "bold"
|
|
||||||
)
|
|
||||||
|
|
||||||
let header-supplement = if config.lang == "de" {
|
|
||||||
"Kapitel"
|
|
||||||
} else {
|
|
||||||
"chapter"
|
|
||||||
}
|
|
||||||
|
|
||||||
set heading(supplement: [#header-supplement])
|
|
||||||
|
|
||||||
set math.equation(numbering: "(1)")
|
|
||||||
show math.equation: set text(font: "Fira Math", size: 12pt)
|
|
||||||
|
|
||||||
// Set header spacing
|
|
||||||
show heading.where(level: 1): it => 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)
|
|
||||||
|
|
||||||
// set theme for code blocks
|
|
||||||
set raw(tab-size: style.code.tab-size)
|
|
||||||
show raw.where(block: false): it => box(
|
|
||||||
stroke: 1pt + ABB-GRAY-05,
|
|
||||||
radius: 2pt,
|
|
||||||
inset: (left: 2pt, right: 2pt),
|
|
||||||
outset: (top: 4pt, bottom: 4pt),
|
|
||||||
fill: ABB-GRAY-06,
|
|
||||||
text(font: style.code.font, size: style.code.size, it.text),
|
|
||||||
)
|
|
||||||
show figure.where(kind: raw): it => align(left)[
|
|
||||||
#let content = it.body
|
|
||||||
#let lang = if content.has("lang") {
|
|
||||||
it.body.lang
|
|
||||||
} else {
|
|
||||||
none
|
|
||||||
}
|
|
||||||
#block(
|
|
||||||
width: 100%,
|
|
||||||
fill: ABB-GRAY-06,
|
|
||||||
stroke: 1pt + ABB-GRAY-05,
|
|
||||||
radius: 0.5em,
|
|
||||||
inset: 0.75em,
|
|
||||||
clip: false,
|
|
||||||
{
|
|
||||||
let (columns, align, make_row) = {
|
|
||||||
if style.code.lines {
|
|
||||||
(
|
|
||||||
(auto, 1fr),
|
|
||||||
(right + top, left),
|
|
||||||
e => {
|
|
||||||
let (i, l) = e
|
|
||||||
let n = i + 1
|
|
||||||
let n_str = if (calc.rem(n, 1) == 0) or (true and i == 0) {
|
|
||||||
text(
|
|
||||||
font: style.code.font,
|
|
||||||
size: style.code.size,
|
|
||||||
fill: ABB-BLACK,
|
|
||||||
str(n),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
none
|
|
||||||
}
|
|
||||||
(n_str + h(0.5em), raw(block: true, lang: lang, l))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
(1fr,),
|
|
||||||
(left,),
|
|
||||||
e => {
|
|
||||||
let (i, l) = e
|
|
||||||
raw(block: true, lang: lang, l)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
grid(
|
|
||||||
stroke: none,
|
|
||||||
columns: columns,
|
|
||||||
rows: (auto,),
|
|
||||||
gutter: 0pt,
|
|
||||||
inset: 0.25em,
|
|
||||||
align: (col, _) => align.at(col),
|
|
||||||
fill: ABB-GRAY-06,
|
|
||||||
..content
|
|
||||||
.text
|
|
||||||
.split("\n")
|
|
||||||
.enumerate()
|
|
||||||
.map(make_row)
|
|
||||||
.flatten()
|
|
||||||
.map(c => if c.has("text") and c.text == "" {
|
|
||||||
v(1em)
|
|
||||||
} else {
|
|
||||||
c
|
|
||||||
})
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
#v(-1em)
|
|
||||||
#align(center + top, it.caption)
|
|
||||||
]
|
|
||||||
|
|
||||||
show figure: set block(breakable: true)
|
|
||||||
|
|
||||||
// make figure supplements bold
|
|
||||||
// based on: https://github.com/typst/typst/discussions/3871
|
|
||||||
show figure.caption: c => [
|
|
||||||
#if c.body.fields().len() > 0 {
|
|
||||||
text(weight: "medium")[
|
|
||||||
#c.supplement #c.counter.display("1.1.1")
|
|
||||||
]
|
|
||||||
c.separator
|
|
||||||
}
|
|
||||||
#c.body
|
|
||||||
]
|
|
||||||
|
|
||||||
// change the display supplement according to the text langugae
|
|
||||||
// based on: https://github.com/typst/typst/issues/3273
|
|
||||||
show figure.where(kind: raw): set figure(supplement: context {
|
|
||||||
if text.lang == "de" {
|
|
||||||
"Quelltext"
|
|
||||||
} else {
|
|
||||||
"Listing"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// APA style table
|
|
||||||
set table(
|
|
||||||
inset: 0.5em,
|
|
||||||
align: left,
|
|
||||||
stroke: (x, y) => (
|
|
||||||
left: none,
|
|
||||||
right: none,
|
|
||||||
top: if y == 0 {
|
|
||||||
1.5pt
|
|
||||||
} else if y < 2 {
|
|
||||||
1pt
|
|
||||||
} else {
|
|
||||||
0.5pt
|
|
||||||
},
|
|
||||||
bottom: if y == 0 {
|
|
||||||
1pt
|
|
||||||
} else {
|
|
||||||
1.5pt
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
// make table header bold
|
|
||||||
show table.cell.where(y: 0): set text(weight: "bold")
|
|
||||||
|
|
||||||
set block(spacing: 2em)
|
|
||||||
set par(
|
|
||||||
justify: true,
|
|
||||||
first-line-indent: 1em,
|
|
||||||
leading: 1em,
|
|
||||||
)
|
|
||||||
|
|
||||||
// give links a color
|
|
||||||
show link: set text(fill: style.link.color)
|
|
||||||
show ref: set text(fill: style.link.color)
|
|
||||||
|
|
||||||
set heading(numbering: none)
|
|
||||||
set page(
|
|
||||||
paper: style.page.format,
|
|
||||||
foreground: watermark(config),
|
|
||||||
header-ascent: style.header.content-padding,
|
|
||||||
footer-descent: style.header.content-padding,
|
|
||||||
margin: (
|
|
||||||
top: style.page.margin.top + style.header.underline-top-padding + style
|
|
||||||
.header
|
|
||||||
.content-padding,
|
|
||||||
bottom: style.page.margin.bottom + style.footer.content-padding,
|
|
||||||
left: style.page.margin.left,
|
|
||||||
right: style.page.margin.right,
|
|
||||||
),
|
|
||||||
numbering: (..nums) => {
|
|
||||||
let current-page = here().page()
|
|
||||||
if current-page == 1 {
|
|
||||||
[]
|
|
||||||
} else if query(<end-of-prelude>)
|
|
||||||
.first()
|
|
||||||
.location()
|
|
||||||
.page() > current-page {
|
|
||||||
numbering("I", nums.pos().first())
|
|
||||||
} else if query(<end-of-content>)
|
|
||||||
.first()
|
|
||||||
.location()
|
|
||||||
.page() >= current-page {
|
|
||||||
numbering("1", nums.pos().first())
|
|
||||||
} else {
|
|
||||||
numbering("a", nums.pos().first())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
footer: context [
|
|
||||||
#let page-counter = counter(page).get().first()
|
|
||||||
#let page-number = here().page()
|
|
||||||
#set align(center)
|
|
||||||
|
|
||||||
#if page-number == 1 {
|
|
||||||
[]
|
|
||||||
} else if query(<end-of-prelude>).first().location().page() > page-number {
|
|
||||||
set align(center)
|
|
||||||
numbering("I", page-counter)
|
|
||||||
} else if query(<end-of-content>).first().location().page() >= page-number {
|
|
||||||
numbering(
|
|
||||||
"1 / 1",
|
|
||||||
page-counter,
|
|
||||||
counter(page).at(<end-of-content>).last(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
numbering("a", page-counter)
|
|
||||||
}
|
|
||||||
],
|
|
||||||
header: context {
|
|
||||||
set align(left)
|
|
||||||
let current-page = here().page()
|
|
||||||
|
|
||||||
if current-page == 1 {
|
|
||||||
// logo of ABB and DHBW
|
|
||||||
grid(
|
|
||||||
// set width of columns
|
|
||||||
// we need two, so make both half the page width
|
|
||||||
columns: (50%, 50%),
|
|
||||||
// left align logo of ABB
|
|
||||||
align(left, image("res/ABB.svg", height: style.header.logo-height)),
|
|
||||||
// right align logo of DHBW
|
|
||||||
align(right, image("res/DHBW.svg", height: style.header.logo-height)))
|
|
||||||
|
|
||||||
} else if query(<end-of-content>)
|
|
||||||
.first()
|
|
||||||
.location()
|
|
||||||
.page() >= current-page and query(<end-of-prelude>)
|
|
||||||
.first()
|
|
||||||
.location()
|
|
||||||
.page() < current-page + 1 {
|
|
||||||
let heading = currentH()
|
|
||||||
|
|
||||||
heading.at(0)
|
|
||||||
h(0.5em)
|
|
||||||
heading.at(1)
|
|
||||||
v(style.header.underline-top-padding - 1em)
|
|
||||||
line(length: 100%)
|
|
||||||
} else {
|
|
||||||
config.thesis.title
|
|
||||||
v(style.header.underline-top-padding - 1em)
|
|
||||||
line(length: 100%)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
body
|
|
||||||
}
|
|
||||||
|
|
||||||
#let content_styled(config, body) = {
|
|
||||||
set heading(numbering: "1.1.1")
|
|
||||||
|
|
||||||
body
|
|
||||||
}
|
|
||||||
|
|
||||||
#let end_styled(config, body) = {
|
|
||||||
set heading(numbering: "1.1.1")
|
|
||||||
|
|
||||||
body
|
|
||||||
}
|
|
|
@ -2,54 +2,21 @@
|
||||||
|
|
||||||
#import "abstract.typ": abstract, summary
|
#import "abstract.typ": abstract, summary
|
||||||
|
|
||||||
#show: dhbw-template.with((
|
#show: dhbw-template.with()
|
||||||
lang: "de",
|
|
||||||
region: "de",
|
|
||||||
draft: false,
|
|
||||||
author: (
|
|
||||||
name: "Sven Vogel",
|
|
||||||
semester: 4,
|
|
||||||
program: "Informationtechnology",
|
|
||||||
course: "TINF19IT1",
|
|
||||||
faculty: "Technik",
|
|
||||||
university: "DHBW Mannheim",
|
|
||||||
company: "ABB AG",
|
|
||||||
supervisor: "Benny Goodman",
|
|
||||||
matriculation-number: 123456789,
|
|
||||||
),
|
|
||||||
thesis: (
|
|
||||||
title: "Unofficial ABB/DHBW Typst template",
|
|
||||||
subtitle: "for reports and thesises",
|
|
||||||
submission-date: "23rd march 2020",
|
|
||||||
timeframe: "1st january 2020 - 20th march 2020",
|
|
||||||
kind: "T2000",
|
|
||||||
summary: summary,
|
|
||||||
abstract: abstract,
|
|
||||||
preface: include "preface.typ",
|
|
||||||
keywords: ("IT", "other stuff"),
|
|
||||||
bibliography: bibliography("refs.bib"),
|
|
||||||
glossary: yaml("glossary.yml"),
|
|
||||||
appendices: include "appendix.typ",
|
|
||||||
),
|
|
||||||
))
|
|
||||||
|
|
||||||
#import "@preview/wrap-it:0.1.0": wrap-content
|
#import "@preview/wrap-it:0.1.0": wrap-content
|
||||||
|
|
||||||
= Lorem Ipsum
|
= Lorem Ipsum
|
||||||
|
|
||||||
#text(fill: ABB-RED, "Hello ABB branding")
|
|
||||||
|
|
||||||
#lorem(25)
|
#lorem(25)
|
||||||
@oidc
|
|
||||||
@potato
|
@einstein
|
||||||
|
|
||||||
#lorem(100)
|
#lorem(100)
|
||||||
@Anhang-A
|
|
||||||
|
|
||||||
== Lorem Ipsum 2
|
== Lorem Ipsum 2
|
||||||
|
|
||||||
#lorem(200)
|
#lorem(230)
|
||||||
@einstein
|
|
||||||
|
|
||||||
= Lorem Ipsum 3 <sec:hello>
|
= Lorem Ipsum 3 <sec:hello>
|
||||||
|
|
||||||
|
@ -64,12 +31,7 @@ $
|
||||||
|
|
||||||
#lorem(140)
|
#lorem(140)
|
||||||
|
|
||||||
#wrap-content(
|
#figure(image("assets/digitaldog.jpg", width: 200pt), caption: [ Some image caption ])
|
||||||
figure(image("assets/digitaldog.jpg", width: 200pt), caption: [ Some image caption ]),
|
|
||||||
lorem(200),
|
|
||||||
)
|
|
||||||
|
|
||||||
#url("https://github.com", "text") @sec:hello
|
|
||||||
|
|
||||||
#lorem(50)
|
#lorem(50)
|
||||||
|
|
||||||
|
@ -90,10 +52,7 @@ $
|
||||||
caption: [ Some table ],
|
caption: [ Some table ],
|
||||||
)
|
)
|
||||||
|
|
||||||
#pagebreak()
|
|
||||||
|
|
||||||
#lorem(100)
|
#lorem(100)
|
||||||
#inline-color("#ff0000", "red") @HTTP
|
|
||||||
|
|
||||||
#figure(
|
#figure(
|
||||||
```rust
|
```rust
|
||||||
|
@ -110,8 +69,6 @@ $
|
||||||
|
|
||||||
#lorem(100)
|
#lorem(100)
|
||||||
|
|
||||||
#pagebreak()
|
|
||||||
|
|
||||||
= Conclusion
|
= Conclusion
|
||||||
|
|
||||||
#lorem(320)
|
#lorem(320)
|
||||||
|
|
Loading…
Reference in New Issue