ff-handbook/typst/glossary.typ

150 lines
4.6 KiB
Typst
Raw Normal View History

2025-02-02 11:09:32 +01:00
// glossary figure kind
#let __glossary_figure = "glossary_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 __query_labels_with_key(key, before: false) = {
if before {
query(selector(label(__glossary_label_prefix + key)).before(here(), inclusive: false))
} else {
query(selector(label(__glossary_label_prefix + key)))
}
}
// Reference a term
#let gls(key, suffix: none, long: none, display: none) = {
context {
let __glossary_entries = __glossary_entries.final()
if key in __glossary_entries {
let entry = __glossary_entries.at(key)
2025-04-22 10:21:05 +02:00
2025-02-02 11:09:32 +01:00
let gloss = __query_labels_with_key(key, before: true)
2025-04-22 10:21:05 +02:00
2025-02-02 11:09:32 +01:00
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#suffix (#entry.short#suffix)]
} else {
[#entry.short#suffix]
}
2025-04-22 10:21:05 +02:00
2025-02-02 11:09:32 +01:00
[#link(label(entry.key), textLink)#label(__glossary_label_prefix + entry.key)]
} else {
text(fill: red, "Glossary entry not found: " + key)
}
}
}
// reference to term with pluralisation
#let glspl(key) = gls(key, suffix: "s")
// show rule to make the references for glossary
#let make-glossary(body) = {
show ref: r => {
if r.element != none and r.element.func() == figure and r.element.kind == __glossary_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,
long: entry.at("long", 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,
)
}
2025-04-22 10:21:05 +02:00
2025-02-02 11:09:32 +01:00
x
})
2025-04-22 10:21:05 +02:00
2025-02-02 11:09:32 +01:00
let groups = entries.map(x => x.at("group", default: "")).dedup()
// move no group to the front
groups.insert(0, "")
groups.pop()
2025-04-22 10:21:05 +02:00
2025-02-02 11:09:32 +01:00
for group in groups.sorted() {
if group != "" [#heading(group, level: 2) ]
for entry in entries.sorted(key: x => x.short) {
if entry.group == group {
[
#show figure.where(kind: __glossary_figure): it => it.caption
2025-04-22 10:21:05 +02:00
#figure(
supplement: "",
kind: __glossary_figure,
numbering: none,
caption: {
context {
set align(left)
set par(justify: true)
let term_references = __query_labels_with_key(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 != []
{
set text(weight: 600)
if hasLong {
emph(entry.short) + [ -- ] + entry.long
2025-02-02 11:09:32 +01:00
} else {
2025-04-22 10:21:05 +02:00
emph(entry.short)
2025-02-02 11:09:32 +01:00
}
}
2025-04-22 10:21:05 +02:00
if hasDesc [: #desc ] else [ ]
if disable-back-references != true {
set text(weight: "bold")
box(width: 1fr, repeat[.])
[ ]
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 => link(x)[#numbering(x.page-numbering(), ..counter(page).at(x))]).join(", ")
} else {
h(1fr)
}
2025-02-02 11:09:32 +01:00
}
2025-04-22 10:21:05 +02:00
}
},
)[] #label(entry.key)
2025-02-02 11:09:32 +01:00
#parbreak()
]
}
}
2025-04-22 10:21:05 +02:00
if enable-group-pagebreak {pagebreak(weak: true)}
2025-02-02 11:09:32 +01:00
}
};