ff-handbook/typst/template.typ

407 lines
10 KiB
Typst
Raw Normal View History

2025-02-02 11:09:32 +01:00
#import "@preview/codly:1.2.0": *
#import "@preview/codly-languages:0.1.2": *
#import "constants.typ"
#import "glossary.typ": make-glossary, print-glossary, gls, glspl
#import "utils.typ": draft, inwriting, showNumberedLines
#let localized_month(month) = {
month = calc.clamp(month, 1, 12)
return constants.localized_months.at(month - 1)
}
#let titlepage(
logo,
authors,
collaboration,
title,
subtitle,
details,
date
) = {
set page(margin: (left: 2.5cm, top: 3cm, bottom: 4cm, rest: 2.5cm))
page(footer: [])[
#if logo != none {
place(top + center, float: true, dx: 0cm, dy:2.5cm, image(logo, height:2.5cm))
place(bottom + left, float: true, dx: 0cm, dy:-2.3cm, image("./jkeffects.svg", height: 2cm))
}
// Information on the center
#set align(center)
// #text(constants.font_size * 1.5, authors.map(author => [
// #author.name#if author.at("enrollment_number", default: none) != none [, #author.enrollment_number]
// ]).join("\n"))
// #v(1cm, weak: true)
#v(3cm)
#set par(leading: 0.4em)
#text(
constants.font_size * 2.5,
weight: "medium",
fill: constants.accent_color,
title//smallcaps(title)
)
#if subtitle != none {
v(0.9cm, weak: true)
text(
constants.font_size * 1.5,
fill: constants.accent_color,
subtitle
)
}
#v(1fr)
// Information on the right
#set align(right)
// Information on the bottom right
#set par(leading: 0.65em)
#for line in details {
if line != "" [
#line\
] else {
v(0em)
}
}
#v(0em)
#date.display("[day].") #localized_month(date.month()) #date.year()
]
}
#let acknowledgmentpage(
acknowledgment
) = {
if acknowledgment != none {
v(1fr)
set par(first-line-indent: 0em, justify: true)
heading(constants.acknowledgment, numbering: none)
v(1.5em, weak: true)
acknowledgment
v(1fr)
pagebreak()
}
}
#let abstractpage(
abstract
) = {
if abstract != none {
v(1fr)
set par(first-line-indent: 0em, justify: true)
heading(constants.abstract, numbering: none)
v(1.5em, weak: true)
abstract
v(1fr)
pagebreak()
}
}
#let outlinepages() = {
show ref: none
{
show outline.entry.where(
level: 1
): it => {
v(constants.font_size * 1.25, weak: true)
if it.body.fields().at("children", default: none) != none {
strong(it)
} else {
it
}
}
// Contents
heading(constants.contents)
outline(
title: none,
target: heading.where(outlined: true),
indent: auto
)
}
}
#let listspages() = {
context {
// Figure list
if query(figure.where(kind: image)).len() > 2 {
pagebreak()
heading(constants.figure_list)
outline(
title: none,
target: figure.where(kind: image),
indent: auto
)
}
// Table list
if query(figure.where(kind: table)).len() > 2 {
pagebreak()
heading(constants.table_list)
outline(
title: none,
target: figure.where(kind: table),
indent: auto
)
}
// Code list
if query(figure.where(kind: "code")).len() > 2 {
pagebreak()
heading(constants.code_list)
outline(
title: none,
target: figure.where(kind: "code"),
indent: auto
)
}
}
}
#let glossarypage(glossary) = {
if glossary != none and glossary.len() > 0 {
pagebreak()
heading(constants.glossary)
v(1.5em, weak: true)
print-glossary(glossary, disable-back-references: true)
}
}
#let attachmentpages(attachments, references) = {
if attachments != none and attachments.len() > 0 {
if references != none {
pagebreak()
}
heading(constants.attachments, outlined: false)
v(1.5em, weak: true)
// Reset heading counter
counter(heading).update(0)
// Display heading count as: "Attachment X:"
set heading(
numbering: (..nums) => constants.attachments + " " + nums
.pos()
.slice(1) // All headings are level 2 headings
.map(str)
.join("."),
supplement: none,
outlined: constants.outline_other_headings
)
for (index, attachment) in attachments.enumerate() {
if index != 0 {
pagebreak()
}
if attachment.at("ref", default: none) != none [
#heading(depth: 2, "- " + attachment.title)
#label(attachment.ref)
] else {
heading(depth: 2, "- " + attachment.title)
}
if attachment.at("description", default: none) != none [
#set par(justify: true)
#text(attachment.description)
]
v(1em)
set align(horizon + center)
context{
let (width, height) = measure(image(attachment.file))
if width < (100% - 1pt).length and height < (80% - 1pt).length {
image(attachment.file, fit: "contain")
} else if height < width {
image(attachment.file, width: 100%, fit: "contain")
} else {
image(attachment.file, width: 100%, height: 80%, fit: "contain")
}
}
if attachment.at("note", default: none) != none {
v(1em, weak: true)
text(attachment.note)
}
}
}
}
#let referenceattachmentpages(references, attachments) = {
if references != none or (attachments != none and attachments.len() > 0) {
pagebreak()
set heading(numbering: none, outlined: constants.outline_other_headings)
set page(numbering: "I", number-align: right, header: none)
context {
counter(page).update(counter(page).at(<end-intro>))
counter(page).step()
}
if references != none {
heading(constants.references)
v(1.5em, weak: true)
bibliography("../" + references, title: none, style: constants.bibliography_style)
}
listspages()
attachmentpages(attachments, references)
}
}
#let main(title, alttitle, authors, body) = {
set page(numbering: "1", number-align: right)
set heading(numbering: "1.1", outlined: true)
show heading.where(level: 2): it => {
v(.75em)
it
v(.75em)
}
show heading.where(level: 3): it => {
v(.5em)
it
v(.5em)
}
// set par(justify: true, first-line-indent: 1em)
set par.line(numbering: "1") if showNumberedLines
show figure: set block(above: 3em, below: 2.5em)
show figure.caption: set text(size: .95em)
show figure.caption.where(kind: "source"): set text(size: .8em)
show table: set par(justify: false)
set page(
header: {
//smallcaps(
if alttitle != none {
alttitle
} else {
title
}
//)
context {
let headings_before = query(
heading.where(level: 1, outlined: true, numbering: "1.1").before(here())
)
let lastheadbefore = headings_before.at(-1, default: none)
let headings_after = query(
heading.where(level: 1, outlined: true, numbering: "1.1").after(here())
)
let firstheadafter = headings_after.at(0, default: none)
let currentpage = here().page()
if lastheadbefore != none {
text(" ")
if firstheadafter == none {
sym.dash.en
text(" ")
lastheadbefore.body//smallcaps(lastheadbefore.body)
} else if firstheadafter.location().page() != currentpage {
sym.dash.en
text(" ")
lastheadbefore.body//smallcaps(lastheadbefore.body)
}
}
}
//h(1fr)
//authors.map(a => a.name).join(", ")
}
)
counter(page).update(1)
show: codly-init.with()
codly(languages: codly-languages)
set par(justify: true)
body
}
#let template(
// The title of the report
title: [Report title],
// An optional alternative title as page heading
alttitle: none,
// An optional subtitle of the report
subtitle: none,
// Details displayed on the cover page
details: (),
// Authors of the report:
authors: (),
// optional collaboration with
collaboration: none,
// Logo for the cover page. Must be in the image folder. Can be omitted.
logo: "logo.svg",
// Date displayed on the cover page
date: datetime.today(),
// The report's abstract. Can be omitted.
abstract: none,
// The report's disclaimer. Can be omitted.
disclaimer: none,
// The report's acknowledments. Can be omitted.
acknowledgment: none,
// Glossary for the report. Can be omitted.
glossary: none,
// The result of a call to the `bibliography` function. Can be omitted.
references: none,
// Attachments of the report. Can be omitted.
attachments: none,
// Keywords of the report.
keywords: (),
// Language of the report
lang: "de",
// The report's content
body
) = {
// Set the document's basic properties.
set document(author: authors.map(a => a.name), title: title, keywords: keywords, date: date)
let draft_background = none
if draft {
draft_background = rotate(
45deg,
rect(stroke: 2pt + constants.draft_color, radius: 15pt, inset: 15pt, text(100pt, fill: constants.draft_color)[*#constants.draft*])
)
}
set page(paper: "a4", margin: (right: 2.5cm, bottom: 3.5cm, rest: 4cm), numbering: "I", number-align: right, background: draft_background)
set par(leading: .9em, spacing: .9em)
set text(size: constants.font_size, font: constants.textfont, stretch: 120%, lang: lang, region: lang)
set heading(numbering: none, outlined: constants.outline_other_headings)
show heading.where(level: 1): set text(size: constants.font_size * 2)
show heading.where(level: 2): set text(size: constants.font_size * 1.5)
show heading.where(level: 3): set text(size: constants.font_size * 5/4)
show link: set text(fill: constants.accent_color) //if inwriting
show ref: set text(fill: constants.accent_color) //if inwriting
show: make-glossary
show bibliography: set text(constants.font_size)
show math.equation: set text(size: constants.math_font_size, font: constants.mathfont)
// Raw block format
show raw: set text(size: constants.code_font_size, font: constants.codefont)
titlepage(logo, authors, collaboration, title, subtitle, details, date)
acknowledgmentpage(acknowledgment)
abstractpage(abstract)
show heading.where(level: 1): it => {
pagebreak(weak: true)
v(0cm)
it
v(1em)
}
outlinepages()
glossarypage(glossary)
// Main body
[
~ <end-intro>
#pagebreak()
]
main(title, alttitle, authors, body)
referenceattachmentpages(references, attachments)
}