Compare commits

...

8 Commits

Author SHA1 Message Date
Sven Vogel c06fecec4c changed: read glossary from YAML file
Gitea Action for checking typst compilation / run-ci-linux (push) Successful in 28s Details
2024-07-08 14:25:56 +02:00
Sven Vogel 5ea73081a6 changed: outline only lists heading supplemented with chapter 2024-07-08 13:55:57 +02:00
Sven Vogel 39a33e327b added: custom glossarium theme 2024-07-08 13:49:04 +02:00
Sven Vogel 256827d07b changed: disabled back glossary references 2024-07-08 10:27:48 +02:00
Sven Vogel 18979f8f81 changed: raw block font is option in config 2024-07-08 10:18:03 +02:00
Sven Vogel fb03bfc414 added: numbering to equations 2024-07-08 09:58:46 +02:00
Sven Vogel 600d348b13 added: ABB branding colors 2024-07-08 09:55:38 +02:00
Sven Vogel c3d65f93b2 added: APA style table 2024-07-08 09:34:33 +02:00
11 changed files with 366 additions and 33 deletions

18
src/branding.typ Normal file
View File

@ -0,0 +1,18 @@
// 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%)

View File

@ -7,6 +7,8 @@
// Edited: 27.06.2024 // Edited: 27.06.2024
// License: MIT // License: MIT
#import "branding.typ": *
// default configuration // default configuration
#let default-config = ( #let default-config = (
// language settings used to make decisions about hyphenation and others // language settings used to make decisions about hyphenation and others
@ -60,8 +62,12 @@
font: "Open Sans"), font: "Open Sans"),
heading: ( heading: (
font: "Montserrat"), font: "Montserrat"),
code: (
theme: "res/abb.tmTheme",
font: "FiraCode Nerd Font",
tab-size: 4),
link: ( link: (
color: red.darken(15%)))) color: ABB-GRAY-02)))
// Insert a dictionary `update` into `base` but only the entries of update that also exist in base // Insert a dictionary `update` into `base` but only the entries of update that also exist in base
// Runs recursively on all sub dictionaries // Runs recursively on all sub dictionaries

220
src/glossarium.typ Normal file
View File

@ -0,0 +1,220 @@
// .--------------------------------------------------------------------------.
// | 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 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 hasLong and hasDesc [:]
if hasDesc [ #desc ] else [. ]
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)
#parbreak()
]
}
}
if enable-group-pagebreak { pagebreak(weak: true) }
}
};

60
src/glossary.typ Normal file
View File

@ -0,0 +1,60 @@
// .--------------------------------------------------------------------------.
// | Glossary Utilities |
// '--------------------------------------------------------------------------'
// Author: Sven Vogel
// Edited: 08.07.2024
// License: MIT
#let glossary(entries) = {
assert(
type(entries) == dictionary,
message: "The glossary is not a dictionary",
)
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 {
panic("Missing group for glossary entry: `" + k + "`")
}
}
return entries.pairs().map(((key, entry)) => (
key: key,
short: eval(entry.short, mode: "markup"),
long: eval(entry.at("long", default: ""), mode: "markup"),
desc: eval(entry.at("desc", default: ""), mode: "markup"),
group: entry.at("group", default: "")
))
}

View File

@ -8,7 +8,9 @@
// License: MIT // License: MIT
#import "conf.typ": validate-config #import "conf.typ": validate-config
#import "branding.typ": *
#import "style.typ": global_styled_doc, content_styled, end_styled #import "style.typ": global_styled_doc, content_styled, end_styled
#import "glossary.typ": glossary
#import "pages/titlepage.typ": new_title_page #import "pages/titlepage.typ": new_title_page
#import "pages/declaration-of-authorship.typ": new_declaration_of_authorship #import "pages/declaration-of-authorship.typ": new_declaration_of_authorship
#import "pages/confidentiality-statement.typ": new_confidentiality_statement_page #import "pages/confidentiality-statement.typ": new_confidentiality_statement_page
@ -18,6 +20,10 @@
#import "pages/preface.typ": new-preface #import "pages/preface.typ": new-preface
#import "pages/appendix.typ": show-appendix #import "pages/appendix.typ": show-appendix
#let group-break()= {
[#pagebreak()]
}
// start of template pages and styles // start of template pages and styles
#let dhbw-template(config, body) = [ #let dhbw-template(config, body) = [
#let config = validate-config(config) #let config = validate-config(config)
@ -53,15 +59,16 @@
// 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 "glossarium.typ": *
#show: make-glossary #show: make-glossary
#pagebreak(weak: true) #pagebreak(weak: true)
#if "glossary" in config.thesis and config.thesis.glossary != none { #if "glossary" in config.thesis and config.thesis.glossary != none {
heading(supplement: [outline], "Glossar") print-glossary(
disable-back-references: true,
print-glossary(config.thesis.glossary) enable-group-pagebreak: true,
glossary(config.thesis.glossary))
pagebreak(weak: true) pagebreak(weak: true)
} }

View File

@ -19,7 +19,7 @@
if count > 0 { if count > 0 {
pagebreak(weak: true) pagebreak(weak: true)
outline( outline(
title: heading(level: 3, title), title: title,
target: figure.where(kind: kind)) target: figure.where(kind: kind))
} }
} }
@ -64,7 +64,7 @@
pagebreak(weak: true) pagebreak(weak: true)
outline( outline(
target: heading.where(supplement: [chapter]), target: heading.where(supplement: [chapter]),
title: heading(level: 3, title), title: title,
indent: auto) indent: auto)
} }
@ -85,7 +85,7 @@
pagebreak(weak: true) pagebreak(weak: true)
outline( outline(
target: heading.where(supplement: supplement), target: heading.where(supplement: supplement),
title: heading(level: 3, title), title: title,
indent: auto) indent: auto)
} }
} }
@ -100,6 +100,8 @@
strong(it) strong(it)
} }
render_heading_outline()
render_figures_outline() render_figures_outline()
render_table_outline() render_table_outline()
@ -107,6 +109,4 @@
render_raw_outline() render_raw_outline()
render_appendix_outline() render_appendix_outline()
render_heading_outline()
} }

View File

@ -7,4 +7,4 @@
// Edited: 05.07.2024 // Edited: 05.07.2024
// License: MIT // License: MIT
#import "@preview/glossarium:0.4.1": * #import "glossary.typ": *

View File

@ -7,6 +7,8 @@
// Edited: 27.06.2024 // Edited: 27.06.2024
// License: MIT // License: MIT
#import "branding.typ": *
#let watermark-color = luma(50%).transparentize(70%) #let watermark-color = luma(50%).transparentize(70%)
#let watermark(config) = if config.draft { #let watermark(config) = if config.draft {
@ -34,7 +36,8 @@
ligatures: true, ligatures: true,
hyphenate: true, hyphenate: true,
dir: ltr, dir: ltr,
font: style.text.font) font: style.text.font,
fill: ABB-BLACK)
show heading: set text( show heading: set text(
font: style.heading.font, font: style.heading.font,
@ -42,16 +45,34 @@
set heading(supplement: [chapter]) set heading(supplement: [chapter])
set math.equation(numbering: "(1)")
// 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 theme for code blocks
set raw(tab-size: 4, theme: "res/abb.tmTheme") set raw(
tab-size: style.code.tab-size,
theme: style.code.theme)
show raw: set text(font: style.code.font)
show figure: set block(breakable: true) show figure: set block(breakable: true)
// 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 { 0pt },
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 block(spacing: 2em)
set par( set par(
justify: true, justify: true,

View File

@ -1,15 +0,0 @@
#let glossary = (
(
key: "oidc",
short: "OIDC",
long: "OpenID Connect",
desc: [OpenID is an open standard and decentralized authentication protocol promoted by the non-profit #link("https://en.wikipedia.org/wiki/OpenID#OpenID_Foundation")[OpenID Foundation].]
),
(
key: "potato",
short: "potato",
plural: "potatoes",
desc: [#lorem(10)]
),
)

11
template/glossary.yml Normal file
View File

@ -0,0 +1,11 @@
oidc:
short: OIDC
long: OpenID Connect
desc: "OpenID is an open standard and decentralized authentication protocol promoted by the non-profit #link(\"https://en.wikipedia.org/wiki/OpenID#OpenID_Foundation\")[OpenID Foundation]."
group: Acronym
potato:
short: potato
desc: "#lorem(50)"
group: Acronym

View File

@ -1,6 +1,5 @@
#import "../src/lib.typ": dhbw-template #import "../src/lib.typ": *
#import "glossary.typ": glossary
#import "abstract.typ": abstract, summary #import "abstract.typ": abstract, summary
#show: dhbw-template.with(( #show: dhbw-template.with((
@ -27,15 +26,18 @@
preface: include "preface.typ", preface: include "preface.typ",
keywords: ( "IT", "other stuff" ), keywords: ( "IT", "other stuff" ),
bibliography: bibliography("refs.bib"), bibliography: bibliography("refs.bib"),
glossary: glossary, glossary: yaml("glossary.yml"),
appendices: include "appendix.typ"))) 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 @oidc
@potato
#lorem(100) #lorem(100)
@Anhang-A @Anhang-A
@ -63,8 +65,11 @@ $
#figure( #figure(
table( table(
columns: 2, columns: 3,
"Hello", "World"), table.header[Date][Exercise Type][Calories Burned],
[2023-03-15], [Swimming], [400],
[2023-03-17], [Weightlifting], [250],
[2023-03-18], [Yoga], [200]),
caption: [ Some table ]) caption: [ Some table ])
#pagebreak() #pagebreak()