// 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 }