Skip to content

Instantly share code, notes, and snippets.

@BlueskyFR
Last active March 25, 2024 14:26
Show Gist options
  • Save BlueskyFR/a4afce2db380baaabf3638100d2608c6 to your computer and use it in GitHub Desktop.
Save BlueskyFR/a4afce2db380baaabf3638100d2608c6 to your computer and use it in GitHub Desktop.
A glossary for Typst that uses native functions!
// Glossary code by Hugo Cartigny (BlueskyFR) 🍉
#let glossary(indent-defs: false, doc) = {
// ✨ The glossary displays its items using level 99 headings
let glossary = state("wow", (:))
// Hide the numbering for level 99 titles
show heading.where(level: 99): it => text(weight: "regular", it.body)
let page-refs-color = rgb("#7630EA")
show terms: list => {
let terms-grid = ()
// Add terms to glossary
for item in list.children {
glossary.update(v => {
v.insert(
item.term.text,
(
// Holds the list of the locations referencing the term
ref-locs: (),
// The actual term definition
def: item.description,
)
)
// Return the new state with the added entry
v
})
if indent-defs {
// Term
terms-grid.push([
#heading(level: 99, numbering: "1")[*#item.term*]
#label(item.term.text)
])
// Definition
terms-grid.push([
#item.description
// Pages where the term is referenced
#show: text.with(page-refs-color)
#locate(loc => {
glossary.final(loc).at(item.term.text).ref-locs
.map(l => link(l, str(l.page)))
.join(", ")
})
])
} else [
// Display items directly one by one since
// we don't need to build a grid
// Use a level 99 title so it doesn't conflict with regular ones
// and it can be refered to by @citations
#heading(level: 99, numbering: "1")[
*#item.term*:~~#item.description
// Pages where the term is referenced
#show: text.with(page-refs-color)
#locate(loc => {
glossary.final(loc).at(item.term.text).ref-locs
.map(l => link(l, str(l.page)))
.join(", ")
})
]
#label(item.term.text) \
]
}
if indent-defs {
grid(
columns: (1fr, 4fr),
column-gutter: 2mm,
row-gutter: 8mm,
..terms-grid
)
}
// 🐛 Debug
//glossary.display()
}
show ref: r => {
locate(loc => {
// Search for the source of the ref
let term = str(r.target)
let res = query(r.target, loc)
// If the source exists and is the glossary (heading level 99)
if res.len() > 0 and res.first().level == 99 {
let entry = glossary.at(loc).at(term)
// Replace term by the user-specified supplement if not none
let custom-term = {
if r.citation.supplement != none { r.citation.supplement }
else { term }
}
// If it is the first reference to the term, display its definition too
link(res.first().location(), {
if entry.ref-locs.len() == 0 [*#entry.def* (#custom-term)]
else [#custom-term]
})
// Add location to the term's ref list if the current page
// is not already listed
glossary.update(v => {
// If this page is not in, push the loc in!
if v.at(term).ref-locs.all(l => l.page != loc.page()) {
v.at(term).ref-locs.push(
// Current page loc
loc.position()
)
}
v
})
}
else { r } // Otherwise just return the ref as it is
})
}
doc
}
#import "glossary.typ": glossary
#show: glossary.with(indent-defs: true)
= Glossary
/ HPC: High Performance Computing
/ Typst: An awesome open-source project
/ Apple: A brand manufacturing expensive products/a fruit
/ Loooooong item but wait a minute: A coooooool coooooool coooooool coooooool coooooool coooooool coooooool coooooool coooooool coooooool coooooool coooooool definition! 🙃
= Introduction
So today we are going to talk about @HPC.
But what is @HPC exactly you may wonder?
Sometimes you also need to talk about multiple @HPC[HPCs]!
This document was made using @Typst.
Can you use both @Typst and eat an @Apple at the same time?
#pagebreak()
I like @HPC and @HPC[HPCs],
#pagebreak(); #pagebreak()
@Apple and \
@Typst!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment