93 lines
3.0 KiB
Plaintext
93 lines
3.0 KiB
Plaintext
// Copyright 2023 Rolf Bremer, Jutta Klebe
|
|
// Use of this code is governed by the License in the LICENSE.txt file.
|
|
// For a 'how to use this package', see the accompanying .md, .pdf + .typ documents.
|
|
|
|
// Index Entry; used to mark an entry in the document to be included in the Index.
|
|
// An optional initial may be provided.
|
|
#let index(
|
|
content,
|
|
initial: none
|
|
) = locate(loc => [#metadata((initial: initial, content: content, location: loc.position()))<jkrb_index>])
|
|
|
|
// Create the index page.
|
|
#let make-index(title: none, outlined: false) = {
|
|
|
|
// This function combines the text(s) of a content.
|
|
let content-text(content) = {
|
|
let ct = ""
|
|
if content.has("text") {
|
|
ct = content.text
|
|
}
|
|
else {
|
|
for cc in content.children {
|
|
if cc.has("text") {
|
|
ct += cc.text
|
|
}
|
|
}
|
|
}
|
|
return ct
|
|
}
|
|
|
|
locate(loc => {
|
|
let elements = query(<jkrb_index>, loc)
|
|
let pages = (:)
|
|
let words = (:)
|
|
for el in elements {
|
|
let ct = content-text(el.value.content)
|
|
|
|
// Have we already know that entry text? If not,
|
|
// add it to our list of entry words
|
|
if pages.keys().contains(ct) != true {
|
|
pages.insert(ct, ())
|
|
}
|
|
|
|
// Add the new page entry to the list.
|
|
let ent = (page: el.value.location.page)
|
|
if not pages.at(ct).contains(ent){
|
|
pages.at(ct).push(ent)
|
|
}
|
|
}
|
|
|
|
for el in elements {
|
|
let ct = content-text(el.value.content)
|
|
if words.keys().contains(ct) != true {
|
|
words.insert(ct, ())
|
|
words.at(ct) = (content: el.value.content, initial: el.value.initial, pages: pages.at(ct))
|
|
}
|
|
}
|
|
|
|
// Sort the entries.
|
|
let initial-sorted(ct) = {
|
|
let char = words.at(ct).initial
|
|
if char == none {
|
|
char = content-text(words.at(ct).content)
|
|
}
|
|
return char
|
|
}
|
|
let sortedkeys = words.keys().sorted(key: initial-sorted)
|
|
|
|
// Output.
|
|
let register = ""
|
|
if title != none { heading(outlined: outlined, numbering: none, title) }
|
|
for sk in sortedkeys [
|
|
// Use class specific formatting for the page numbers.
|
|
#let formattedPageNumbers = words.at(sk).pages.map(en => {
|
|
link((page: en.page, x:0pt, y:0pt))[#strong[#en.page]]
|
|
})
|
|
|
|
#let firstCharacter = content-text(words.at(sk).content).first()
|
|
#if (words.at(sk).initial != none) {
|
|
firstCharacter = words.at(sk).initial
|
|
}
|
|
|
|
#if firstCharacter != register {
|
|
heading(level: 2, numbering: none, outlined: false, firstCharacter)
|
|
register = firstCharacter
|
|
}
|
|
#words.at(sk).content
|
|
#box(width: 1fr)
|
|
#formattedPageNumbers.join(", ")
|
|
]
|
|
})
|
|
}
|