Compare commits
No commits in common. "f8f80dfa52c0de4ecf9cda86ba36abff73e7db39" and "ed9a5beac506dd4519f934344a74494fa1e23bd9" have entirely different histories.
f8f80dfa52
...
ed9a5beac5
|
@ -7,9 +7,6 @@ function abort() {
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "Compiling template..."
|
|
||||||
typst compile template/main.typ --root . || abort "template"
|
|
||||||
|
|
||||||
echo "Running tests..."
|
echo "Running tests..."
|
||||||
|
|
||||||
echo "Running test local-import..."
|
echo "Running test local-import..."
|
||||||
|
|
80
src/conf.typ
80
src/conf.typ
|
@ -6,83 +6,3 @@
|
||||||
// Author: Sven Vogel
|
// Author: Sven Vogel
|
||||||
// Edited: 27.06.2024
|
// Edited: 27.06.2024
|
||||||
// License: MIT
|
// License: MIT
|
||||||
|
|
||||||
// default configuration
|
|
||||||
#let default-config = (
|
|
||||||
lang: "en",
|
|
||||||
region: "en",
|
|
||||||
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: none,
|
|
||||||
abstract: none,
|
|
||||||
keywords: ( "IT", "other stuff" ),
|
|
||||||
bibliography: none /* bibliography("refs.bib") */,
|
|
||||||
glossary: none,
|
|
||||||
appendices: none),
|
|
||||||
style: (
|
|
||||||
header: (
|
|
||||||
bottom-padding: 1.5em,
|
|
||||||
underline-top-padding: 0pt,
|
|
||||||
logo-height: 3em),
|
|
||||||
page: (
|
|
||||||
format: "a4",
|
|
||||||
margin: (
|
|
||||||
left: 3cm,
|
|
||||||
right: 2.5cm,
|
|
||||||
top: 2.5cm,
|
|
||||||
bottom: 2.5cm)),
|
|
||||||
text: (
|
|
||||||
size: 12pt,
|
|
||||||
font: "Open Sans"),
|
|
||||||
heading: (
|
|
||||||
font: "Montserrat"),
|
|
||||||
link: (
|
|
||||||
color: red.darken(15%))))
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
|
|
41
src/lib.typ
41
src/lib.typ
|
@ -10,17 +10,7 @@
|
||||||
// start of template pages and styles
|
// start of template pages and styles
|
||||||
#let dhbw-template(config: dictionary, body) = [
|
#let dhbw-template(config: dictionary, body) = [
|
||||||
|
|
||||||
#import "conf.typ": validate-config
|
|
||||||
#import "style.typ": global_styled_doc, content_styled, end_styled
|
#import "style.typ": global_styled_doc, content_styled, end_styled
|
||||||
#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/appendix.typ": show-appendix
|
|
||||||
|
|
||||||
#let config = validate-config(config)
|
|
||||||
|
|
||||||
#let doc = body
|
#let doc = body
|
||||||
|
|
||||||
|
@ -33,25 +23,41 @@
|
||||||
// apply global style to every element in the argument content
|
// apply global style to every element in the argument content
|
||||||
#global_styled_doc(config: config, body: [
|
#global_styled_doc(config: config, body: [
|
||||||
|
|
||||||
|
#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/appendix.typ": show-appendix
|
||||||
|
|
||||||
// configure text locale
|
// configure text locale
|
||||||
#set text(
|
#set text(lang: config.lang, region: config.region)
|
||||||
lang: config.lang,
|
|
||||||
region: config.region)
|
|
||||||
|
|
||||||
// preppend title page
|
// preppend title page
|
||||||
#new_title_page(config)
|
#new_title_page(config)
|
||||||
|
|
||||||
// prelude includes: title, declaration of authorship, confidentiality statement, outline and abstract
|
// prelude includes: title, declaration of authorship, confidentiality statement, outline and abstract
|
||||||
// these will have roman page numbers
|
// these will have roman page numbers
|
||||||
|
|
||||||
|
#pagebreak(weak: true)
|
||||||
#new_declaration_of_authorship(config)
|
#new_declaration_of_authorship(config)
|
||||||
|
|
||||||
|
#pagebreak(weak: true)
|
||||||
#new_confidentiality_statement_page(config)
|
#new_confidentiality_statement_page(config)
|
||||||
|
|
||||||
|
#pagebreak(weak: true)
|
||||||
#new_prerelease_note(config)
|
#new_prerelease_note(config)
|
||||||
|
|
||||||
|
#pagebreak(weak: true)
|
||||||
#new_abstract(config)
|
#new_abstract(config)
|
||||||
|
|
||||||
|
#pagebreak(weak: true)
|
||||||
#new_outline()
|
#new_outline()
|
||||||
|
|
||||||
// glossary is built inline here because the links must be
|
// glossary is built inline here because the links must be
|
||||||
// exposed to the entire document
|
// exposed to the entire document
|
||||||
#import "@preview/glossarium:0.4.1": make-glossary, print-glossary
|
#import "@preview/glossarium:0.4.1": make-glossary, print-glossary, gls, glspl
|
||||||
#show: make-glossary
|
#show: make-glossary
|
||||||
|
|
||||||
#pagebreak(weak: true)
|
#pagebreak(weak: true)
|
||||||
|
@ -68,13 +74,16 @@
|
||||||
// mark end of prelude
|
// mark end of prelude
|
||||||
#metadata("prelude terminate") <end-of-prelude>
|
#metadata("prelude terminate") <end-of-prelude>
|
||||||
|
|
||||||
#content_styled(config: config, body: doc)
|
#content_styled(config: config, body: [
|
||||||
|
// code of document follows here
|
||||||
|
#doc
|
||||||
|
])
|
||||||
|
|
||||||
#metadata("content terminate") <end-of-content>
|
#metadata("content terminate") <end-of-content>
|
||||||
|
|
||||||
#end_styled(config: config, body: [
|
#end_styled(config: config, body: [
|
||||||
// add bibliography if set
|
// add bibliography if set
|
||||||
#if "bibliography" in config.thesis and config.thesis.bibliography != none {
|
#if config.thesis.bibliography != none {
|
||||||
pagebreak(weak: true)
|
pagebreak(weak: true)
|
||||||
set bibliography(style: "ieee")
|
set bibliography(style: "ieee")
|
||||||
config.thesis.bibliography
|
config.thesis.bibliography
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
|
|
||||||
#let new_abstract(config) = context [
|
#let new_abstract(config) = context [
|
||||||
|
|
||||||
#pagebreak(weak: true)
|
|
||||||
|
|
||||||
#let thesis = config.thesis
|
#let thesis = config.thesis
|
||||||
|
|
||||||
#pagebreak(weak: true)
|
#pagebreak(weak: true)
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
|
|
||||||
#let new_confidentiality_statement_page(config) = context [
|
#let new_confidentiality_statement_page(config) = context [
|
||||||
|
|
||||||
#pagebreak(weak: true)
|
|
||||||
|
|
||||||
#let thesis = config.thesis
|
#let thesis = config.thesis
|
||||||
#let author = config.author
|
#let author = config.author
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
|
|
||||||
#let new_declaration_of_authorship(config) = context [
|
#let new_declaration_of_authorship(config) = context [
|
||||||
|
|
||||||
#pagebreak(weak: true)
|
|
||||||
|
|
||||||
#let thesis = config.thesis
|
#let thesis = config.thesis
|
||||||
#let author = config.author
|
#let author = config.author
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
// can optionally insert a pagebreak after the outline
|
// can optionally insert a pagebreak after the outline
|
||||||
// NOTE: will not render in case the listing is empty
|
// 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 elems = query(figure.where(kind: kind), here())
|
||||||
let count = elems.len()
|
let count = elems.len()
|
||||||
|
|
||||||
|
@ -83,9 +82,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#let new_outline() = {
|
|
||||||
pagebreak(weak: true)
|
|
||||||
|
|
||||||
|
#let new_outline() = {
|
||||||
show outline.entry.where(
|
show outline.entry.where(
|
||||||
level: 1,
|
level: 1,
|
||||||
): it => {
|
): it => {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
|
|
||||||
#let new_prerelease_note(config) = context [
|
#let new_prerelease_note(config) = context [
|
||||||
|
|
||||||
#pagebreak(weak: true)
|
|
||||||
|
|
||||||
#let thesis = config.thesis
|
#let thesis = config.thesis
|
||||||
#let author = config.author
|
#let author = config.author
|
||||||
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
#import "@preview/glossarium:0.4.1": *
|
|
|
@ -7,38 +7,40 @@
|
||||||
// Edited: 27.06.2024
|
// Edited: 27.06.2024
|
||||||
// License: MIT
|
// License: MIT
|
||||||
|
|
||||||
|
#let HeaderPaddingBottom = 1.5em
|
||||||
|
#let LogoHeight = 3em
|
||||||
|
#let HeaderUnderlinePaddingTop = 0pt
|
||||||
|
|
||||||
// global style of document
|
// global style of document
|
||||||
#let global_styled_doc(config: dictionary, body: content) = context {
|
#let global_styled_doc(config: dictionary, body: content) = context [
|
||||||
let thesis = config.thesis
|
#let thesis = config.thesis
|
||||||
let style = config.style
|
|
||||||
|
|
||||||
// set page geometry
|
// set page geometry
|
||||||
// and paper format
|
// paper format of A4
|
||||||
set page(
|
#set page(
|
||||||
paper: style.page.format,
|
paper: "a4",
|
||||||
margin: style.page.margin)
|
margin: (left: 3cm, right: 2.5cm, top: 2.5cm, bottom: 2.5cm))
|
||||||
|
|
||||||
set text(
|
#set text(
|
||||||
size: style.text.size,
|
size: 12pt,
|
||||||
ligatures: true,
|
ligatures: true,
|
||||||
hyphenate: true,
|
hyphenate: true,
|
||||||
dir: ltr,
|
dir: ltr,
|
||||||
font: style.text.font)
|
font: "Open Sans")
|
||||||
|
|
||||||
show heading: set text(
|
#show heading: set text(
|
||||||
font: style.heading.font,
|
font: "Montserrat",
|
||||||
weight: "semibold")
|
weight: "semibold")
|
||||||
|
|
||||||
set heading(supplement: [chapter])
|
#set heading(supplement: [chapter])
|
||||||
|
|
||||||
// Set header spacing
|
// Set header spacing
|
||||||
show heading.where(level: 1): it => v(2em) + it + v(1em)
|
#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: 2): it => v(1em) + it + v(0.5em)
|
||||||
show heading.where(level: 3): it => v(0.5em) + it + v(0.25em)
|
#show heading.where(level: 3): it => v(0.5em) + it + v(0.25em)
|
||||||
|
|
||||||
// set theme for code blocks
|
#set raw(tab-size: 4, theme: "res/github.tmTheme")
|
||||||
set raw(tab-size: 4, theme: "res/github.tmTheme")
|
#show raw.where(block: true): code => {
|
||||||
show raw.where(block: true): code => {
|
|
||||||
show raw.line: line => {
|
show raw.line: line => {
|
||||||
text(fill: gray)[#line.number]
|
text(fill: gray)[#line.number]
|
||||||
h(1em)
|
h(1em)
|
||||||
|
@ -47,23 +49,20 @@
|
||||||
code
|
code
|
||||||
}
|
}
|
||||||
|
|
||||||
set block(spacing: 2em)
|
#set block(spacing: 2em)
|
||||||
set par(
|
#set par(
|
||||||
justify: true,
|
justify: true,
|
||||||
first-line-indent: 1em,
|
first-line-indent: 1em,
|
||||||
leading: 1em)
|
leading: 1em)
|
||||||
|
|
||||||
// give links a color
|
#show link: set text(fill: red.darken(15%))
|
||||||
show link: set text(fill: style.link.color)
|
#show ref: set text(fill: red.darken(15%))
|
||||||
show ref: set text(fill: style.link.color)
|
|
||||||
|
|
||||||
set heading(numbering: none)
|
#set heading(numbering: none)
|
||||||
set page(
|
#set page(
|
||||||
header-ascent: style.header.underline-top-padding + style.header.bottom-padding,
|
header-ascent: HeaderUnderlinePaddingTop + HeaderPaddingBottom,
|
||||||
footer-descent: 1em,
|
footer-descent: 1em,
|
||||||
margin: (
|
margin: (top: 2.5cm + LogoHeight + HeaderUnderlinePaddingTop + HeaderPaddingBottom, bottom: 2.5cm + 1em),
|
||||||
top: style.page.margin.top + style.header.logo-height + style.header.underline-top-padding + style.header.bottom-padding,
|
|
||||||
bottom: style.page.margin.bottom + 1em),
|
|
||||||
numbering: (..nums) => {
|
numbering: (..nums) => {
|
||||||
let current-page = here().page()
|
let current-page = here().page()
|
||||||
if current-page == 1{
|
if current-page == 1{
|
||||||
|
@ -85,9 +84,9 @@
|
||||||
// we need two, so make both half the page width
|
// we need two, so make both half the page width
|
||||||
columns: (50%, 50%),
|
columns: (50%, 50%),
|
||||||
// left align logo of ABB
|
// left align logo of ABB
|
||||||
align(left, image("res/ABB.svg", height: style.header.logo-height)),
|
align(left, image("res/ABB.svg", height: LogoHeight)),
|
||||||
// right align logo of DHBW
|
// right align logo of DHBW
|
||||||
align(right, image("res/DHBW.svg", height: style.header.logo-height)))
|
align(right, image("res/DHBW.svg", height: LogoHeight)))
|
||||||
|
|
||||||
} else if query(<end-of-prelude>).first().location().page() <= here().page() {
|
} else if query(<end-of-prelude>).first().location().page() <= here().page() {
|
||||||
let headers-before = query(selector(heading.where(numbering: "1.", level: 1)).before(here()))
|
let headers-before = query(selector(heading.where(numbering: "1.", level: 1)).before(here()))
|
||||||
|
@ -108,24 +107,24 @@
|
||||||
columns: (1fr, auto),
|
columns: (1fr, auto),
|
||||||
align: (horizon, bottom),
|
align: (horizon, bottom),
|
||||||
context [ _ #header-title _ ],
|
context [ _ #header-title _ ],
|
||||||
image("res/DHBW.svg", height: style.header.logo-height))
|
image("res/DHBW.svg", height: LogoHeight))
|
||||||
|
|
||||||
v(style.header.underline-top-padding - 1em)
|
v(HeaderUnderlinePaddingTop - 1em)
|
||||||
line(length: 100%)
|
line(length: 100%)
|
||||||
} else {
|
} else {
|
||||||
grid(
|
grid(
|
||||||
columns: (1fr, auto),
|
columns: (1fr, auto),
|
||||||
align: (horizon, bottom),
|
align: (horizon, bottom),
|
||||||
context [ _ #config.thesis.title _ ],
|
context [ _ #config.thesis.title _ ],
|
||||||
image("res/DHBW.svg", height: style.header.logo-height)
|
image("res/DHBW.svg", height: LogoHeight)
|
||||||
)
|
)
|
||||||
v(style.header.underline-top-padding - 1em)
|
v(HeaderUnderlinePaddingTop - 1em)
|
||||||
line(length: 100%)
|
line(length: 100%)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
body
|
#body
|
||||||
}
|
]
|
||||||
|
|
||||||
#let content_styled(config: dictionary, body: content) = [
|
#let content_styled(config: dictionary, body: content) = [
|
||||||
#set heading(numbering: "1.")
|
#set heading(numbering: "1.")
|
||||||
|
|
Loading…
Reference in New Issue