feat(glossy): add type-checking

- adds type-checking via the valkyrie package
- fixes handling of groups parameter on #glossary()
- new test for relevant changes
This commit is contained in:
swaits committed 2024-12-16 18:30:09 -07:00
1 parent d2e44f4131
commit 0a87404a18
9 files changed
+112 -10

No files matched your search

+13
View File
@@ -168,6 +168,19 @@ Display the glossary using the `glossary()` function:
)
```
Note that if you want to display terms without a group, you specify that with an
empty string. For example, to show the empty group and then the _Web_ group:
```typst
#glossary(groups: ("", "Web"))
```
Or to just show the empty group (i.e. terms without a group):
```typst
#glossary(groups: (""))
```
### Customizing Term Display
Control how terms appear in the document by providing a custom `show-term` function:
+29 -10
View File
@@ -1,3 +1,7 @@
// TODO: replace with @preview when back online
#import "@preview/valkyrie:0.2.1" as z
#import "./schemas.typ": *
#import "./themes.typ": *
#import "./utils.typ": *
@@ -332,10 +336,15 @@
show-term: (term-body) => term-body,
body
) = context {
// Validate entries parameter type
if type(entries) != dictionary {
panic("entries must be a dictionary, instead got: " + repr(entries))
// Type checking
let checked-entries = (:)
for (key, entry) in entries {
let checked-key = z.parse(key, z.string(), scope: ("dictionary key",))
let checked-entry = z.parse(entry, dict-schema, scope: ("dictionary entry",))
checked-entries.insert(checked-key, checked-entry)
}
let checked-show-term = z.parse(show-term, z.function(), scope: ("show-term",))
let checked-body = z.parse(body, z.content(), scope: ("body",))
// Process and store each glossary entry
for (key, entry) in entries {
@@ -396,6 +405,12 @@
ignore-case: false,
groups: (),
) = context {
// Type checking
let checked-title = z.parse(title, z.content(), scope: ("title",))
let checked-groups = z.parse(groups, groups-list-schema, scope: ("groups",))
let checked-ignore-case = z.parse(ignore-case, z.boolean(), scope: ("ignore-case",))
let checked-theme = z.parse(theme, theme-schema, scope: ("theme",))
// Collect and organize entries by group
let output = (:)
let all_entries = __gloss_entries.final()
@@ -405,19 +420,23 @@
let all_groups = all_entries
.values()
.map(e => e.at("group"))
.map(g => { if g == none { "" } else { g } })
.dedup()
.sorted()
let target_groups = if groups.len() == 0 {
let target_groups = if checked-groups.len() == 0 {
all_groups
} else {
// Validate requested groups exist
for g in groups {
for g in checked-groups {
if g == none {
g = ""
}
if g not in all_groups {
panic("Requested group not found: " + g)
panic("Requested group, '" + g + "', not found.")
}
}
groups
checked-groups
}
// Process entries group by group
@@ -459,15 +478,15 @@
// Render the glossary using the theme
let group_index = 0
(theme.section)(
(checked-theme.section)(
title,
for (group, entries) in output {
(theme.group)(
(checked-theme.group)(
group,
group_index,
output.len(),
for (i, entry) in entries.enumerate() {
(theme.entry)(entry, i, entries.len())
(checked-theme.entry)(entry, i, entries.len())
}
)
group_index += 1
+26
View File
@@ -0,0 +1,26 @@
// TODO: change to @preview when online
#import "@preview/valkyrie:0.2.1" as z
#let dict-schema = z.either(
z.string(),
z.dictionary(
(
short: z.content(), // this is the only required field
plural: z.content(optional: true),
long: z.content(optional: true),
longplural: z.content(optional: true),
description: z.content(optional: true),
group: z.content(optional: true),
)
)
)
#let theme-schema = z.dictionary(
(
section: z.function(),
group: z.function(),
entry: z.function(),
)
)
#let groups-list-schema = z.array(pre-transform: z.coerce.array)
@@ -0,0 +1,11 @@
{
"zbuffer": {
"short": "z-bufer",
"long": "the depth buffer"
},
"pbr": {
"short": "PBR",
"long": "physically based rendering",
"group": "abbreviations"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

+33
View File
@@ -0,0 +1,33 @@
#import "/lib.typ": *
#show: init-glossary.with(json("abbreviations.json"))
Reference: @pbr, @zbuffer
#let t(g) = [
#line(length: 100%)
*TESTING:* `#glossary(groups: ` #repr(g) `)`
#glossary(groups: g)
]
#t("abbreviations") // "string" : str
#t(("abbreviations")) // ("string") : str
#t(("abbreviations",)) // ("string",) : array(str)
#t(("abbreviations","abbreviations")) // ("string","string",) : array(str)
#pagebreak(weak: true)
#t("") // empty string should be the empty group
#t(("")) // empty string should be the empty group
#t(("",)) // empty string should be the empty group
#t(("","")) // empty string should be the empty group
#pagebreak(weak: true)
#t(none) // none should be all groups
#t((none)) // none should be all groups
#pagebreak(weak: true)
#t(("abbreviations",none)) // try to get both groups