Merge branch 'main' of https://git.montehaselino.de/DHBW/dhbw-abb-typst-template
Gitea Action for checking typst compilation / run-ci-linux (push) Successful in 34s Details

This commit is contained in:
Sven Vogel 2024-08-20 09:56:39 +02:00
commit dd902adebd
18 changed files with 553 additions and 521 deletions

View File

@ -40,7 +40,7 @@ SOFTWARE.*/
// key not found error
#let __not-found-panic-error-msg(key) = {
__glossarium_error_prefix+"key '"+key+"' not found"
__glossarium_error_prefix + "key '" + key + "' not found"
}
// Reference a term
@ -80,10 +80,10 @@ SOFTWARE.*/
let gloss = __query_labels_with_key(here(), key, before: true)
let is_first = gloss == ()
let entlongplural = entry.at("longplural", default: "");
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: "");
let entlong = entry.at("long", default: "")
if entlong != [] and entlong != "" {
[#entlong#suffix]
} else {
@ -93,7 +93,7 @@ SOFTWARE.*/
[#entlongplural]
}
let entplural = entry.at("plural", default: "");
let entplural = entry.at("plural", default: "")
let short = if entplural == [] or entplural == "" {
[#entry.short#suffix]
} else {
@ -171,23 +171,25 @@ SOFTWARE.*/
caption: {
context {
let term_references = __query_labels_with_key(here(), entry.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 != []
grid(
columns: 2,
column-gutter: 1em,
text(weight: "bold", entry.short),
{
if hasLong {
text(weight: "bold", entry.long)
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(
par(hanging-indent: 1em)[
#text(weight: "bold", entry.short)
#if hasLong {
text(entry.long)
}
if hasLong and hasDesc [:]
if hasDesc [ #desc ] else [. ]
if disable-back-references != true {
term_references.map(x => x.location()).sorted(key: x => x.page()).fold(
#if hasLong and hasDesc [:]
#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)
@ -196,25 +198,29 @@ SOFTWARE.*/
pages.push(x.page())
(values: values, pages: pages)
},
).values.map(x => {
let page-numbering = x.page-numbering();
)
.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(", ")
}
}
)
.join(", ")
}
],
)
]
}
},
)[] #label(entry.key)
#parbreak()
]
}
}
if enable-group-pagebreak { pagebreak(weak: true) }
if enable-group-pagebreak {
pagebreak(weak: true)
}
}
};

View File

@ -14,61 +14,81 @@
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")
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)
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")
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")
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")
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")
message: "The optional group of glossary entry `" + k + "` is not a string",
)
} else {
let group = if "long" in v {
if (context text.lang) == "de" {
let acronym_group = if (context text.lang) == "de" {
"Akronyme"
} else {
"Acronyms"
}
} else {
if (context text.lang) == "de" {
let glossary_group = if (context text.lang) == "de" {
"Begriffe"
} else {
"Terms"
"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, group: glossary_group))
} else {
processed_glossary.insert(k, v)
processed_glossary.at(k).group = group
}
}
}
entries.at(k).group = group
}
}
return entries.pairs().map(((key, entry)) => (
return processed_glossary.pairs().map(((key, entry)) => (
key: key,
short: eval(entry.short, mode: "markup"),
short: entry.short,
long: eval(entry.at("long", default: ""), mode: "markup"),
desc: eval(entry.at("desc", default: ""), mode: "markup"),
group: entry.at("group", default: "")
group: entry.at("group", default: ""),
))
}

View File

@ -7,23 +7,38 @@
// Edited: 27.06.2024
// License: MIT
#import "conf.typ": validate-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
#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()= {
#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,
)],
)
}
// start of template pages and styles
#let dhbw-template(config, body) = [
#let config = validate-config(config)
@ -36,12 +51,14 @@
#set document(
author: config.author.name,
keywords: config.thesis.keywords,
title: config.thesis.title)
title: config.thesis.title,
)
// configure text locale
#set text(
lang: config.lang,
region: config.region)
region: config.region,
)
// preppend title page
#new_title_page(config)
@ -66,9 +83,11 @@
#if "glossary" in config.thesis and config.thesis.glossary != none {
print-glossary(
show-all: true,
disable-back-references: true,
enable-group-pagebreak: true,
glossary(config.thesis.glossary))
glossary(config.thesis.glossary),
)
pagebreak(weak: true)
}

View File

@ -6,7 +6,8 @@
// Edited: 28.06.2024
// License: MIT
#let new_abstract(config) = context {
#let new_abstract(config) = (
context {
set align(center + horizon)
@ -24,4 +25,5 @@
heading("Abstract")
config.thesis.abstract
}
}
)

View File

@ -6,7 +6,8 @@
// Edited: 28.06.2024
// License: MIT
#let show-appendix(config: dictionary) = context {
#let show-appendix(config: dictionary) = (
context {
counter(heading).update(0)
let title = if text.lang == "en" {
@ -41,4 +42,5 @@
config.thesis.appendices
}
}
}
)

View File

@ -6,7 +6,8 @@
// Edited: 28.06.2024
// License: MIT
#let new_confidentiality_statement_page(config) = context {
#let new_confidentiality_statement_page(config) = (
context {
pagebreak(weak: true)
@ -59,4 +60,5 @@
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) }))
}
}
)

View File

@ -6,7 +6,8 @@
// Edited: 28.06.2024
// License: MIT
#let new_declaration_of_authorship(config) = context {
#let new_declaration_of_authorship(config) = (
context {
pagebreak(weak: true)
@ -61,4 +62,5 @@
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) }))
}
}
)

View File

@ -10,7 +10,8 @@
// 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 render_filtered_outline(title: str, kind: selector) = (
context {
let elems = query(figure.where(kind: kind), here())
let count = elems.len()
@ -20,11 +21,14 @@
pagebreak(weak: true)
outline(
title: title,
target: figure.where(kind: kind))
target: figure.where(kind: kind),
)
}
}
}
)
#let render_figures_outline() = context {
#let render_figures_outline() = (
context {
let title = if (text.lang == "de") {
"Abbildungsverzeichnis"
} else if text.lang == "en" {
@ -32,9 +36,11 @@
}
render_filtered_outline(title: title, kind: image)
}
}
)
#let render_table_outline() = context {
#let render_table_outline() = (
context {
let title = if (text.lang == "de") {
"Tabellenverzeichnis"
} else if text.lang == "en" {
@ -42,9 +48,11 @@
}
render_filtered_outline(title: title, kind: table)
}
}
)
#let render_raw_outline() = context {
#let render_raw_outline() = (
context {
let title = if (text.lang == "de") {
"Quelltextverzeichnis"
} else if text.lang == "en" {
@ -52,9 +60,11 @@
}
render_filtered_outline(title: title, kind: raw)
}
}
)
#let render_heading_outline() = context {
#let render_heading_outline() = (
context {
let title = if (text.lang == "de") {
"Inhaltsverzeichnis"
} else if text.lang == "en" {
@ -65,10 +75,13 @@
outline(
target: heading.where(supplement: [chapter]),
title: title,
indent: auto)
}
indent: auto,
)
}
)
#let render_appendix_outline() = context {
#let render_appendix_outline() = (
context {
let supplement = if text.lang == "en" {
[Appendix]
} else {
@ -86,16 +99,16 @@
outline(
target: heading.where(supplement: supplement),
title: title,
indent: auto)
indent: auto,
)
}
}
}
)
#let new_outline() = {
pagebreak(weak: true)
show outline.entry.where(
level: 1,
): it => {
show outline.entry.where(level: 1): it => {
v(1.5em, weak: true)
strong(it)
}

View File

@ -6,7 +6,8 @@
// Edited: 28.06.2024
// License: MIT
#let new_prerelease_note(config) = context {
#let new_prerelease_note(config) = (
context {
pagebreak(weak: true)
@ -53,4 +54,5 @@
v(1em)
h(1em)
[#author.name, #datetime.today().display()]
}
}
)

View File

@ -6,7 +6,8 @@
// Edited: 28.06.2024
// License: MIT
#let new_title_page(config) = context [
#let new_title_page(config) = (
context [
#let thesis = config.thesis
#let author = config.author
@ -60,24 +61,12 @@
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
[*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(
@ -85,30 +74,19 @@
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
[*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,
#align(
bottom,
grid(
// set width of columns
// we need two, so make both half the page width
@ -121,7 +99,9 @@
#context panic("no translation for language: ", text.lang)
]
),
align(right, {line(length: 6cm)})))
align(right, {line(length: 6cm)})),
)
#counter(page).update(0)
]
]
)

View File

@ -111,22 +111,17 @@
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
}
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,),
})
}
else {
( ( 1fr, ),
( left, ),
e => {
let (i, l) = e
raw(block: true, lang: lang, l)
},
}
)
}
}
@ -138,19 +133,15 @@
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
})
)
if lang != none {
place(
top + right,
text(font: style.code.font, size: style.code.size, ligatures: true, fill: ABB-GRAY-03, lang),
..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)
@ -187,20 +178,8 @@
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
},
),
)
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")
@ -209,8 +188,7 @@
set par(
justify: true,
first-line-indent: 1em,
leading: 1em,
)
leading: 1em)
// give links a color
show link: set text(fill: style.link.color)
@ -226,11 +204,10 @@
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,
),
right: style.page.margin.right),
numbering: (..nums) => {
let current-page = here().page()
if current-page == 1 {
if current-page == 1{
[]
} else if query(<end-of-prelude>).first().location().page() > current-page {
numbering("I", nums.pos().first())
@ -271,10 +248,7 @@
// 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 {
} 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)
@ -287,8 +261,7 @@
v(style.header.underline-top-padding - 1em)
line(length: 100%)
}
},
)
})
body
}

View File

@ -8,7 +8,5 @@
#lorem(50)
#figure(
```
```
)
#figure(```
```)

View File

@ -7,3 +7,7 @@ oidc:
potato:
short: potato
desc: "#lorem(50)"
HTTP:
short: HTTP
long: Hyper Text Transfer Protocol

View File

@ -15,7 +15,8 @@
university: "DHBW Mannheim",
company: "ABB AG",
supervisor: "Benny Goodman",
matriculation-number: 123456789),
matriculation-number: 123456789,
),
thesis: (
title: "Unofficial ABB/DHBW Typst template",
subtitle: "for reports and thesises",
@ -25,10 +26,12 @@
summary: summary,
abstract: abstract,
preface: include "preface.typ",
keywords: ( "IT", "other stuff" ),
keywords: ("IT", "other stuff"),
bibliography: bibliography("refs.bib"),
glossary: yaml("glossary.yml"),
appendices: include "appendix.typ")))
appendices: include "appendix.typ",
),
))
#import "@preview/wrap-it:0.1.0": wrap-content
@ -62,7 +65,8 @@ $
#wrap-content(
figure(image("assets/digitaldog.jpg", width: 200pt), caption: [ Some image caption ]),
lorem(200))
lorem(200),
)
#figure(
table(
@ -76,23 +80,28 @@ $
[2023-03-18], [Yoga], [200],
[2023-03-15], [Swimming], [400],
[2023-03-17], [Weightlifting], [250],
[2023-03-18], [Yoga], [200]),
caption: [ Some table ])
[2023-03-18], [Yoga], [200],
),
caption: [ Some table ],
)
#pagebreak()
#lorem(100)
#inline-color("#ff0000", "red") @HTTP
#figure(
```rust
use std::env;
use std::fs::OpenOptions;
use std::io::Write;
use std::env;
use std::fs::OpenOptions;
use std::io::Write;
fn main() {
fn main() {
println!("Hello, World!!!");
}
```, caption: [Some code])
}
```,
caption: [Some code],
)
#lorem(100)