377 lines
9.5 KiB
Typst
377 lines
9.5 KiB
Typst
#import "../theme.typ": faculty_logotype, tul_logomark, faculty_color
|
|
#import "../lang.typ": get_lang_item
|
|
#import "../utils.typ": is_none, assert_dict_has
|
|
|
|
#let base_font = "Inter";
|
|
#let mono_font = "Noto Sans Mono";
|
|
#let serif_font = "Merriweather";
|
|
#let tul_logomark_size = 6.5em;
|
|
|
|
// COUNTERS
|
|
|
|
#let image_count = counter("image_count");
|
|
#let table_count = counter("table_count");
|
|
|
|
// TYPST ELEMENT STYLING
|
|
|
|
#let default_styling(flip_bonding, faculty_color, content) = {
|
|
// page
|
|
set page(
|
|
margin: if flip_bonding {
|
|
(inside: 4cm, top: 3cm, bottom: 3cm)
|
|
} else {
|
|
(left: 4cm, top: 3cm, bottom: 3cm)
|
|
},
|
|
numbering: "1", footer: {
|
|
context {
|
|
let page = counter(page).get().at(0);
|
|
if flip_bonding {
|
|
align(str(page), if calc.rem(page, 2) == 1 { right } else { left });
|
|
} else {
|
|
align(str(page), right);
|
|
}
|
|
}
|
|
});
|
|
|
|
// text
|
|
set text(font: serif_font);
|
|
set par(justify: true);
|
|
|
|
// figures
|
|
let figure_numbering(realcount, c) = {
|
|
context realcount.step();
|
|
context numbering("1. 1", counter(heading).get().at(0), c)
|
|
};
|
|
show figure.where(kind: image): set figure(numbering: figure_numbering.with(image_count));
|
|
show figure.where(kind: table): set figure(numbering: figure_numbering.with(table_count));
|
|
show figure.where(kind: table): set figure.caption(position: top);
|
|
show figure: it => {
|
|
block(it, above: 2em, below: 2em);
|
|
}
|
|
set image(width: 80%);
|
|
|
|
// heading
|
|
set heading(numbering: "1.1.1 ");
|
|
show heading: it => {
|
|
set par(justify: false);
|
|
block(
|
|
above: 2em,
|
|
below: 2em,
|
|
text(it, faculty_color, font: "TUL Mono", size: 1.2em)
|
|
);
|
|
};
|
|
show heading.where(level: 1): it => {
|
|
// reset figure counters
|
|
context counter(figure.where(kind: image)).update(0);
|
|
context counter(figure.where(kind: table)).update(0);
|
|
|
|
pagebreak(weak: true);
|
|
v(2cm);
|
|
it
|
|
};
|
|
|
|
// other
|
|
show raw: set text(font: mono_font);
|
|
show raw.where(block: true): it => {
|
|
block(it, fill: rgb("#eee"), inset: 1em)
|
|
};
|
|
set highlight(fill: faculty_color.lighten(90%));
|
|
|
|
content
|
|
}
|
|
|
|
|
|
#let header(faculty_id, language) = {
|
|
let logotype = faculty_logotype(faculty_id, language);
|
|
grid(
|
|
block(logotype, width: 100%),
|
|
block(align(right, block(tul_logomark(faculty_id), height: tul_logomark_size))),
|
|
columns: 2
|
|
);
|
|
}
|
|
|
|
// DOCUMENT INFO
|
|
|
|
#let person_info(record, item_name) = {
|
|
if is_none(record) {
|
|
none
|
|
} else if type(record) == str {
|
|
record
|
|
} else if type(record) == dictionary {
|
|
if "name" in record {
|
|
record.at("name");
|
|
if "institute" in record {
|
|
text("\n " + record.at("institute"), style: "italic")
|
|
}
|
|
} else {
|
|
let panic_message = (
|
|
item_name + " name is required (or try not specifying " + item_name + " at all)"
|
|
);
|
|
panic(panic_message);
|
|
}
|
|
} else {
|
|
let panic_message = "invalid " + item_name + " - expected a string or a dictionary";
|
|
panic(panic_message);
|
|
}
|
|
}
|
|
|
|
#let info(
|
|
faculty_id,
|
|
language,
|
|
document_type,
|
|
title, author, supervisor, consultant, study_programme, study_branch,
|
|
) = {
|
|
let info_name_value_padding = 5em;
|
|
let info_name_min_width = 10em;
|
|
let gutter = .7em;
|
|
|
|
// document type
|
|
if type(document_type) != type(none) {
|
|
text(get_lang_item(language, document_type), weight: "bold", font: base_font);
|
|
v(0em);
|
|
}
|
|
|
|
// title
|
|
text(
|
|
title, weight: "bold", size: 2em,
|
|
faculty_color(faculty_id), font: base_font,
|
|
);
|
|
v(0em);
|
|
|
|
// other info
|
|
// [field_name, field_value, bold]
|
|
let info_fields = (
|
|
("study_programme", study_programme, false),
|
|
("study_branch", study_branch, false),
|
|
("author", author, true),
|
|
("supervisor", person_info(supervisor, "supervisor"), false),
|
|
("consultant", person_info(consultant, "consultant"), false),
|
|
)
|
|
context {
|
|
let max_field_name_width = calc.max(..info_fields.map((v) => {
|
|
if type(v.at(1)) == type(none) {
|
|
0pt
|
|
} else {
|
|
measure(get_lang_item(language, v.at(0)) + ":").width
|
|
}
|
|
}), info_name_min_width.to-absolute());
|
|
grid(
|
|
columns: 2,
|
|
gutter: gutter,
|
|
..info_fields.filter((v) => { type(v.at(1)) != type(none) }).map((v) => {
|
|
(
|
|
align(top, block(
|
|
text(get_lang_item(language, v.at(0)) + ":", style: "italic", font: base_font),
|
|
width: max_field_name_width + info_name_value_padding
|
|
)),
|
|
text(v.at(1), font: base_font, weight: if v.at(2) { "bold" } else { "regular" })
|
|
)
|
|
}).flatten(),
|
|
);
|
|
v(1em);
|
|
h(max_field_name_width + info_name_value_padding + gutter);
|
|
text(get_lang_item(language, "city") + " " + str(datetime.today().year()), font: base_font);
|
|
}
|
|
}
|
|
|
|
// MAINPAGE
|
|
|
|
#let mainpage(
|
|
faculty_id,
|
|
language,
|
|
document_type,
|
|
title, author, supervisor, consultant, study_programme, study_branch
|
|
) = {
|
|
import "../utils.typ": has_all_none, map_none
|
|
let nonetype = type(none);
|
|
page({
|
|
if has_all_none((
|
|
document_type, title, author, supervisor, consultant, study_programme,
|
|
)) {
|
|
place(center + horizon, align(left, faculty_logotype(faculty_id, language)));
|
|
} else {
|
|
header(faculty_id, language);
|
|
align({
|
|
info(
|
|
faculty_id, language, document_type, map_none(title, (v) => v.at(language)),
|
|
author, supervisor, consultant, map_none(study_programme, (v) => v.at(language)),
|
|
map_none(study_branch, (v) => v.at(language)),
|
|
);
|
|
v(5em);
|
|
}, bottom);
|
|
}
|
|
}, margin: 2cm);
|
|
}
|
|
|
|
// ASSIGNMENT PAGE
|
|
|
|
#let assignment(language, document) = {
|
|
if type(document) == type(none) {
|
|
page(
|
|
place(center + horizon, text(
|
|
get_lang_item(language, "place_assignment"),
|
|
fill: red,
|
|
size: 3em,
|
|
font: base_font,
|
|
weight: "bold",
|
|
)),
|
|
margin: 0em,
|
|
footer: none,
|
|
);
|
|
return;
|
|
}
|
|
import "@preview/muchpdf:0.1.1": muchpdf
|
|
set page(margin: 0em);
|
|
muchpdf(read(document, encoding: none));
|
|
}
|
|
|
|
// DISCLAIMER PAGE
|
|
|
|
#let disclaimer(language, faculty_id, disclaimer_type, author, author_gender) = {
|
|
import "../lang.typ": disclaimer
|
|
heading(get_lang_item(language, "disclaimer"), numbering: none, outlined: false);
|
|
par(
|
|
text(disclaimer(language, disclaimer_type, author_gender))
|
|
);
|
|
v(5em);
|
|
grid(
|
|
columns: 2,
|
|
gutter: 1em,
|
|
block(
|
|
text(datetime.today().display(get_lang_item(language, "date")), lang: "cs"), width: 100%
|
|
),
|
|
text(author),
|
|
);
|
|
}
|
|
|
|
// ACKNOWLEDGEMENT PAGE
|
|
|
|
#let acknowledgement(language, content) = {
|
|
if is_none(content) {
|
|
return;
|
|
}
|
|
heading(get_lang_item(language, "acknowledgement"), numbering: none, outlined: false);
|
|
par(content.at(language));
|
|
}
|
|
|
|
// ABSTRACT
|
|
|
|
#let abstract(language, title, content, keywords) = {
|
|
heading(text(title.at(language), font: base_font), numbering: none, outlined: false);
|
|
v(2em);
|
|
heading(
|
|
level: 2,
|
|
get_lang_item(language, "abstract"),
|
|
numbering: none,
|
|
outlined: false,
|
|
);
|
|
text(content.at(language));
|
|
if not is_none(keywords) and type(keywords.at(language)) != type(none) {
|
|
linebreak();
|
|
linebreak();
|
|
text(get_lang_item(language, "keywords") + ": ", weight: "bold", font: base_font);
|
|
text(keywords.at(language).join(", "));
|
|
}
|
|
}
|
|
|
|
// _ OUTLINE FIGURE INNER
|
|
#let _outline_figure_inner(selector, title, body_mapper) = {
|
|
let entry(selector, element) = {
|
|
link(
|
|
element.location(),
|
|
grid(
|
|
columns: 3,
|
|
gutter: .5em,
|
|
stack(
|
|
dir: ltr,
|
|
text(numbering(
|
|
"1.1",
|
|
counter(heading).at(element.location()).at(0),
|
|
counter(selector).at(element.location()).at(0),
|
|
)),
|
|
h(.5em),
|
|
text(body_mapper(element)),
|
|
),
|
|
box(repeat([.], gap: 0.15em)),
|
|
str(element.location().page()),
|
|
),
|
|
)
|
|
}
|
|
heading(title, numbering: none);
|
|
for el in query(figure.where(kind: selector)) {
|
|
if is_none(el.caption) {
|
|
continue;
|
|
}
|
|
entry(figure.where(kind: selector), el);
|
|
}
|
|
}
|
|
|
|
// _ FIGURE OUTLINE
|
|
|
|
#let _figure_outline(realcount, target, title) = {
|
|
context {
|
|
if realcount.final().at(0) == 0 {
|
|
return;
|
|
}
|
|
_outline_figure_inner(target, title, (it) => it.caption.body);
|
|
}
|
|
}
|
|
|
|
// IMAGE LIST
|
|
|
|
#let imagelist(language) = {
|
|
_figure_outline(image_count, image, get_lang_item(language, "image_list"));
|
|
}
|
|
|
|
// TABLE LIST
|
|
|
|
#let tablelist(language) = {
|
|
_figure_outline(table_count, table, get_lang_item(language, "table_list"));
|
|
}
|
|
|
|
// ABBREVIATION LIST
|
|
|
|
#let abbrlist(language) = {
|
|
import "../abbreviations.typ": abbrlist
|
|
context {
|
|
let abbrs = abbrlist();
|
|
let max_abbr_width = if abbrs.len() > 0 {
|
|
calc.max(abbrs.keys().map((v) => measure(v).width)).at(0)
|
|
} else { return };
|
|
pagebreak(weak: true);
|
|
heading(get_lang_item(language, "abbrs"), numbering: none);
|
|
align(center, grid(
|
|
columns: 2,
|
|
gutter: 1em,
|
|
..abbrs.pairs().map((a) => {
|
|
(
|
|
align(left, block(text(a.at(0), weight: "bold"), width: max_abbr_width + 1em)),
|
|
text(a.at(1))
|
|
)
|
|
}).flatten()
|
|
));
|
|
}
|
|
}
|
|
|
|
// TABLE OF CONTENTS
|
|
|
|
#let toc(language) = {
|
|
show outline.entry.where(level: 1): it => {
|
|
show repeat: none;
|
|
block(text(it, weight: "bold", size: 1.2em), above: 1.5em);
|
|
};
|
|
outline(title: get_lang_item(language, "toc"));
|
|
}
|
|
|
|
// BIBLIOGRAPHY
|
|
|
|
#let bibliogr(language, citations_file) = {
|
|
if language == "cs" {
|
|
bibliography(citations_file, style: "../tul_citace.csl");
|
|
} else if language == "en" {
|
|
bibliography(citations_file, style: "iso-690-numeric");
|
|
} else {
|
|
panic("unknown language for bibliography '" + language + "'");
|
|
}
|
|
}
|