diff --git a/!!! DO-NOT-USE-THIS-REPO !!! b/!!! DO-NOT-USE-THIS-REPO !!!
new file mode 100644
index 0000000..8d927f3
--- /dev/null
+++ b/!!! DO-NOT-USE-THIS-REPO !!!
@@ -0,0 +1,6 @@
+STOP! This repository is being migrated.
+
+All packages have moved to:
+https://github.com/swaits-typst-packages
+
+Do NOT create new issues or PRs here.
diff --git a/MIGRATION_IN_PROGRESS b/MIGRATION_IN_PROGRESS
new file mode 100644
index 0000000..2572638
--- /dev/null
+++ b/MIGRATION_IN_PROGRESS
@@ -0,0 +1,9 @@
+Migration started: 2025-10-26 21:22
+
+This repository is being split into individual package repositories.
+During this transition:
+- No new issues or PRs should be created
+- Existing issues are being triaged and moved
+- The repository will be archived once migration is complete
+
+New organization: https://github.com/swaits-typst-packages
diff --git a/README.md b/README.md
index a061bc6..47a5478 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,54 @@
+# π¨ REPOSITORY MOVING - DO NOT CREATE NEW ISSUES OR PRS HERE π¨
+
+
+
+## β THIS REPOSITORY IS BEING MIGRATED β
+
+### **ALL PACKAGES ARE MOVING TO:** [github.com/swaits-typst-packages](https://github.com/swaits-typst-packages)
+
+**DO NOT:**
+- β Create new issues here
+- β Submit new pull requests here
+- β Start new work based on this repo
+
+**INSTEAD:**
+- β
Go to the new organization: [swaits-typst-packages](https://github.com/swaits-typst-packages)
+- β
Find your specific package repository there
+- β
Create issues/PRs in the individual package repos
+
+
+
+---
+
+## π¦ New Repository Locations
+
+| If you're looking for... | Go to... |
+|--------------------------|----------|
+| **codly-languages** | β‘οΈ [github.com/swaits-typst-packages/codly-languages](https://github.com/swaits-typst-packages/codly-languages) |
+| **easy-typography** | β‘οΈ [github.com/swaits-typst-packages/easy-typography](https://github.com/swaits-typst-packages/easy-typography) |
+| **finely-crafted-cv** | β‘οΈ [github.com/swaits-typst-packages/finely-crafted-cv](https://github.com/swaits-typst-packages/finely-crafted-cv) |
+| **glossy** | β‘οΈ [github.com/swaits-typst-packages/glossy](https://github.com/swaits-typst-packages/glossy) |
+| **pro-letter** | β‘οΈ [github.com/swaits-typst-packages/pro-letter](https://github.com/swaits-typst-packages/pro-letter) |
+| **rfc-vibe** | β‘οΈ [github.com/swaits-typst-packages/rfc-vibe](https://github.com/swaits-typst-packages/rfc-vibe) |
+| **run-liners** | β‘οΈ [github.com/swaits-typst-packages/run-liners](https://github.com/swaits-typst-packages/run-liners) |
+| **swank-tex** | β‘οΈ [github.com/swaits-typst-packages/swank-tex](https://github.com/swaits-typst-packages/swank-tex) |
+| **tasteful-pairings** | β‘οΈ [github.com/swaits-typst-packages/tasteful-pairings](https://github.com/swaits-typst-packages/tasteful-pairings) |
+
+## β³ Migration In Progress
+
+We are currently:
+1. Moving existing issues to the appropriate new repositories
+2. Redirecting pull requests to the new locations
+3. Setting up the new package infrastructure
+
+**Expected completion: [Coming Soon]**
+
+---
+
+
+
+π Original README (click to expand)
+
# `typst-collection`
A collection of `typst` templates and packages by [swaits](https://swaits.com/about).
@@ -35,3 +86,5 @@ links below to their main page.
## License
All content licensed under the [MIT license](LICENSE).
+
+
diff --git a/README.md.backup-20251026-212233 b/README.md.backup-20251026-212233
new file mode 100644
index 0000000..a061bc6
--- /dev/null
+++ b/README.md.backup-20251026-212233
@@ -0,0 +1,37 @@
+# `typst-collection`
+
+A collection of `typst` templates and packages by [swaits](https://swaits.com/about).
+
+Everything in this collection is available for use at the [`typst`
+universe](https://typst.app/universe/). For details on each, please visit the
+links below to their main page.
+
+## Packages
+
+- [**codly-languages**](https://typst.app/universe/package/codly-languages): A
+ set of language configurations for use with
+ [codly](https://typst.app/universe/package/codly).
+- [easy-typography](https://typst.app/universe/package/easy-typography): Sets up
+ sensible typography defaults.
+- [**glossy**](https://typst.app/universe/package/glossy): A very simple
+ glossary system with easily customizable output.
+- [**rfc-vibe**](https://typst.app/universe/package/rfc-vibe): Bring RFC language
+ into everyday docs.
+- [**run-liners**](https://typst.app/universe/package/run-liners): Functions to
+ create various run-in lists.
+- [**swank-tex**](https://typst.app/universe/package/swank-tex): Render those
+ funky logos for TeX, LaTeX, and friends.
+- [**tasteful-pairings**](https://typst.app/universe/package/tasteful-pairings):
+ A carefully curated collection of font pairings focusing on readability and
+ typographic harmony.
+
+## Templates
+
+- [**finely-crafted-cv**](https://typst.app/universe/package/finely-crafted-cv):
+ A modern résumé/curriculum vitæ template with high attention to detail.
+- [**pro-letter**](https://typst.app/universe/package/pro-letter): A formal
+ business letter template.
+
+## License
+
+All content licensed under the [MIT license](LICENSE).
diff --git a/chug.sh b/chug.sh
new file mode 100755
index 0000000..8121a7a
--- /dev/null
+++ b/chug.sh
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+SRC_REPO_ROOT="$(pwd)"
+DEST_PARENT="../swaits-typst-collection" # change if you like
+
+DIRS=(
+ codly-languages
+)
+
+command -v git-filter-repo >/dev/null || {
+ echo "git-filter-repo is required. Install via 'uv tool install git-filter-repo' (or pipx/pip)."
+ exit 1
+}
+
+mkdir -p "$DEST_PARENT"
+
+for d in "${DIRS[@]}"; do
+ [ -d "$d" ] || {
+ echo "Skip: '$d' not found in $(pwd)"
+ continue
+ }
+
+ TARGET="$DEST_PARENT/$d"
+ echo
+ echo "==> Splitting '$d' β '$TARGET'"
+
+ rm -rf "$TARGET"
+ git clone --no-local --branch main --origin origin "$SRC_REPO_ROOT" "$TARGET"
+
+ (
+ cd "$TARGET"
+
+ git filter-repo --force \
+ --path "$d/" \
+ --path-rename "$d/:"
+
+ # ---- Tag rename: '-X.Y.Z' -> 'vX.Y.Z' (annotated, with message) ----
+ # Peel old tags to the commit/object they point to to avoid nested tags.
+ while IFS= read -r oldtag; do
+ # only proceed if the (filtered) repo still has this tag
+ git rev-parse -q --verify "refs/tags/$oldtag" >/dev/null || continue
+
+ peeled=$(git rev-parse -q --verify "${oldtag}^{}" || true)
+ [ -z "$peeled" ] && continue
+
+ ver="${oldtag#${d}-}"
+ newtag="v${ver}"
+
+ if git rev-parse -q --verify "refs/tags/$newtag" >/dev/null; then
+ echo "Tag exists, deleting old: $oldtag"
+ git tag -d "$oldtag" >/dev/null
+ else
+ # annotated tag with message equal to tag name (avoids interactive prompt)
+ git -c advice.nestedTag=false tag -a "$newtag" -m "$newtag" "$peeled"
+ git tag -d "$oldtag" >/dev/null
+ echo "Renamed: $oldtag -> $newtag (at $peeled)"
+ fi
+ done < <(git tag -l "${d}-*")
+
+ # standalone: drop the monorepo remote that filter-repo rewired
+ git remote remove origin || true
+
+ echo "Done: $TARGET"
+ )
+done
+
+echo
+echo "All splits complete under: $DEST_PARENT"
diff --git a/glossy/.gitignore b/glossy/.gitignore
index f1ca904..c2042bf 100644
--- a/glossy/.gitignore
+++ b/glossy/.gitignore
@@ -1,2 +1,3 @@
-tests/**/out/
+build/
tests/**/diff/
+tests/**/out/
diff --git a/glossy/LICENSE b/glossy/LICENSE
index 35d39a7..a4ad6f1 100644
--- a/glossy/LICENSE
+++ b/glossy/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2024 Stephen Waits
+Copyright (c) 2025 Stephen Waits
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/glossy/README.md b/glossy/README.md
index 2c04c5c..87a96cd 100644
--- a/glossy/README.md
+++ b/glossy/README.md
@@ -41,7 +41,7 @@ different goals:
### Import the package
```typst
-#import "@preview/glossy:0.8.0": *
+#import "@preview/glossy:0.9.0": *
```
### Defining Glossary Terms
@@ -128,9 +128,10 @@ And then loaded during initialization as follows:
`init-glossary()` supports the following parameters:
-- `format-term` // TODO: document this
+- `format-term` // Function deciding how to format a term, depending on
+ the 'mode' (short, long, both). See example below.
- `show-term` // Function which can customize display of a term (see example below)
-- `link-terms: false` // True if you want terms to link to their glossary entry
+- `term-links: false` // True if you want terms to link to their glossary entry
### Using Glossary Terms
@@ -141,19 +142,27 @@ In modern web development, languages like @html and @css are essential.
The @tps:pl need to be submitted by Friday.
```
-Available modifiers:
+Available *modes* (they determine which information is printed and are
+mutually exclusive):
-- **cap**: Capitalizes the term
-- **pl**: Uses the plural form
+- auto: (Default) Shows the form depending on the previous usage.
+ The mode when no other mode is appended with a colon.
- **both**: Shows "Long Form (Short Form)"
- **short**: Shows only short form
- **long**: Shows only long form
- **def** or **desc**: Shows the description
+- See [the reference](#reference-for-using-glossary-terms)
+ for a complete overview.
+
+Available *modifiers* (they modify how this information is printed):
+
+- **cap**: Capitalizes the term
+- **pl**: Uses the plural form
- **noref** or **noindex**: Don't show the term in the glossary.
- **a** or **an**: Include the article (`an` is just an alias of `a`, they're
equivalent)
-Modifiers can be combined with colons:
+Modes and modifiers can be combined with colons:
| **Input** | **Output** |
| ------------------- | -------------------------------------------------------------- |
@@ -198,21 +207,71 @@ which would normally render as something like "test procedure specification."
But for some reason you want it to actually say "an annoying report." You can do
that like this:
-| **Input** | **Output** |
-| ------------------------- | -------------------- |
-| `@tps[an annoying report` | "an annoying report" |
+| **Input** | **Output** |
+| -------------------------- | -------------------- |
+| `@tps[an annoying report]` | "an annoying report" |
+| `@tps[]` | #none |
+
+In case you want to reference a term from the Glossary/Index, but don't
+want to display it for whatever reason, the second form can be used.
### First use logic
-Any use of the `short`, `long`, or `both` modifier will not count against the
-term's first use.
+The 'mode' of a glossary term determines which information is printed about this
+term. When using a plain `@term`, possibly with some modifiers, the `auto` mode
+is selected. This mode displays the form depending on the usage counter. On the
+first use (`usage counter == 0`), 'both' forms are printed. On subsequent usage
+(`usage counter > 0`) the 'short' form is printed.
-This is useful, for example, when you want to use a term in a heading or a
-caption. In that case, your term might end up in an `outline()` at the top of
+Not all occurrences of a term are counted towards its usage, this depends on
+the mode of the term. Furthermore, this can be manually controlled by modifiers.
+Both are documented in the [reference tables](#reference-for-using-glossary-terms).
+
+This control over the usage counter is practical, for example, when you want to
+use a term in a heading or a caption.
+In that case, your term might end up in an `outline()` at the top of
your document. Normally you don't want that to count as a term's first real use.
Normally you want that to happen in the body of your document. So, by using
-these modifiers in such situations, you can not only specify exactly how you
-want your term to appear, but also control whether it counts as a "first use".
+the appropriate mode and modifiers in such situations, you can not only specify
+exactly how you want your term to appear, but also control whether it counts
+as a "first use".
+
+### Reference for Using Glossary Terms
+
+A reference about
+- the different 'modes' and how they determine which information is printed about a term
+- the impact of modes on the [usage counter and ensuing first use behaviour](#first-use-logic)
+- how modifiers can change the behaviour with respect to the usage counter
+- how modifiers impact the presentation of the information printed
+
+A glossary term can display different types of information, which is determined
+by the 'mode' in which it is printed. These modes are all mutually exclusive.
+
+| Mode | Utilization | Default first use behaviour | Description |
+| ------------- | ------------------- | --------------------------- | ----------- |
+| `auto` | `@term` | use | The default mode when no 'mode' modifier or supplement is specified. The form depends on the first use counter. |
+| `both` | `:both` | use | Shows both forms of the term, by default ([see `format-term`](#customizing-term-display)) like "Long Form (Short Form)". Falls back to short when long form not available. |
+| `short` | `:short` | no-use | Shows only short form. |
+| `long` | `:long` | no-use | Shows only long form. Falls back to short when long form not available. |
+| `description` | `:def`
`:desc` | no-use | Shows the description (None of the modifiers apply here & no link is created towards the glossary). |
+| `supplement` | `[content]` | no-use | Shows the content given by [the supplement](#overriding-term-text). |
+| `reset` | `:reset` | reset usage counter to 0 | Don't output any content & don't link to the glossary. Typical usage would be after an abstract or even before the start of each chapter, maybe in an injected rule. (This could be made a modifier like `:use` or `:nouse`, but would mostly be utilized as `@term:reset:noindex[]` anyways, thus this is a mode. Write `@term@term:reset` to utilize it as a modifier.) |
+
+Minor modifications to how these different types of information are printed,
+linked or counted towards the usage counter, are controlled by the 'modifiers'.
+They do not influence the default first use behaviour of the mode (unless
+explicitely created for this purpose). Moreover, they neatly compose together
+and with most modes (some exceptions exists, but will print a clear error -
+report a bug if not).
+
+| Modifier | Description |
+| ------------------------------ | ---------------------------------------------------------------------- |
+| `:cap` | Capitalizes the term |
+| `:pl` | Uses the plural form |
+| `:noref`
`:noindex` | Don't show the term in the glossary (i.e. no page will be linked - a link from the term towards the glossary is always provided.). |
+| `:a`
`a:`
`:an`
`an:` | Include the article (`an` is just an alias of `a`, they're equivalent) |
+| `:use`
`:spend` | After this occurrence, the term is 'used', i.e. the usage counter is increased by 1. Write `@term:use:noindex[]` to uniquely control the usage counter without output. |
+| `:nouse`
`:nospend` | After this occurrence, the usage counter remains exactly as the same as before. As if the term is transparent with respect to the usage counter. |
### Generating the Glossary
@@ -244,7 +303,7 @@ Or to just show the empty group (i.e. terms without a group):
### Customizing Term Display
-Control how terms appear in the document by providing a custom `show-term` function:
+Control how terms are styled in the document by providing a custom `show-term` function:
```typst
#let emph-term(term-body) = { emph(term-body) }
@@ -255,6 +314,26 @@ Control how terms appear in the document by providing a custom `show-term` funct
)
```
+Terms can be formatted depending on the 'mode' by providing a custom
+`format-term` function. The mode is one of ("short", "long", "both").
+
+```typst
+// When displaying both, reverse the display order by showing
+// "short (long)" instead of the normal "long (short)"
+#let short-long-term(mode, short-form, long-form) = {
+ if mode == "short" { short-form }
+ else if mode == "long" { long-form }
+ else { // mode assumed to be "both"
+ short-form + " (" + long-form + ")"
+ }
+}
+
+#show: init-glossary.with(
+ myGlossary,
+ format-term: short-long-term
+)
+```
+
### Glossary Themes
#### Included Themes
@@ -300,7 +379,7 @@ Customize glossary appearance by defining a theme with three functions:
columns: (auto, 1fr, auto),
output,
repeat([#h(0.25em) . #h(0.25em)]),
- entry.pages,
+ entry.pages.join(", "),
)
)
}
@@ -313,11 +392,24 @@ Entry fields available to themes:
- `long`: Long form (can be `none`)
- `description`: Term description (can be `none`)
- `label`: Term's dictionary label
-- `pages`: Linked page numbers where term appears
+- `pages`: Array of linked page numbers where term appears
-**NOTE:** If the theme does not emit `entry.label`, linking form terms to their
+**NOTE:** If the theme does not emit `entry.label`, linking from terms to their
glossary entry will not work.
## License
This project is licensed under the MIT License.
+
+## Changelog
+
+### v0.9.0
+- **Breaking**: In themes, entry.pages now returns an array of linked
+ page numbers, instead of opaque content. Use `#entry.pages.join(", ")`
+ in your custom theme to keep the previous behaviour.
+- **Breaking**: The `both` mode (previously called modifier) by default
+ now counts towards the first use of a term.
+- **Breaking**: When multiple conflicting modes are supplied (like 'short'
+ and 'long'), glossy now throws an error (with a clear message).
+- **Breaking**: When an unrecognized modifier is supplied with the term,
+ glossy will now panic instead of ignoring the modifier.
diff --git a/glossy/bin/autotest.sh b/glossy/bin/autotest.sh
deleted file mode 100755
index 63765d8..0000000
--- a/glossy/bin/autotest.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-watchexec \
- --watch . \
- --clear \
- --ignore 'tests/**/diff/**' \
- --ignore 'tests/**/out/**' \
- "typst-test r"
diff --git a/glossy/justfile b/glossy/justfile
new file mode 100644
index 0000000..45fa947
--- /dev/null
+++ b/glossy/justfile
@@ -0,0 +1,151 @@
+# Global settings
+set shell := ["bash", "-eu", "-o", "pipefail", "-c"]
+set unstable := true
+
+# Tooling knobs (overridable via env)
+TT := env_var_or_default("TT", "tt")
+TT_JOBS := env_var_or_default("TT_JOBS", "4")
+TYPST := env_var_or_default("TYPST", "typst")
+TYPSTYLE := env_var_or_default("TYPSTYLE", "typstyle")
+
+# Paths
+THUMB_SRC := "tests/demo/test.typ"
+THUMB_OUT := "thumbnail.png"
+THEME_SRC := "tests/theme-gallery/test.typ"
+THEME_OUT := "themeshots.png"
+DEMO_SRC := "tests/demo/test.typ"
+DEMO_OUT := "build/demo.pdf"
+
+# Aliases
+alias c := check
+alias f := fmt
+alias t := test
+alias w := watch
+
+# Default entrypoint
+[default]
+help:
+ @just --list --unsorted
+
+# ---------------------------- CI / quality ----------------------------
+
+# Format all Typst files
+[group('ci')]
+fmt:
+ rg --files -g '*.typ' | xargs -r {{TYPSTYLE}} --inplace
+
+# Check formatting without modifying files
+[group('ci')]
+fmt-check:
+ rg --files -g '*.typ' | xargs -r {{TYPSTYLE}} --check
+
+# Run all quality checks
+[group('ci')]
+check: fmt-check test
+
+# Run tests with optional arguments
+[group('ci')]
+test *args:
+ {{TT}} run --jobs {{TT_JOBS}} {{args}}
+
+# Accept test outputs as new references
+[group('ci')]
+accept *args:
+ {{TT}} accept {{args}}
+
+# ---------------------------- Dev UX ----------------------------
+
+# Watch for changes and run tests automatically
+[group('dev')]
+watch *args:
+ watchexec \
+ --watch . \
+ --clear \
+ --delay-run 5s \
+ --ignore 'tests/**/diff/**' \
+ --ignore 'tests/**/out/**' \
+ --ignore 'tests/**/ref/**' \
+ "{{TT}} run --jobs {{TT_JOBS}} {{args}}"
+
+# ---------------------------- Artifacts ----------------------------
+
+# Build demo.typ -> demo.pdf
+[group('artifacts')]
+demo:
+ mkdir -p "$(dirname {{DEMO_OUT}})"
+ {{TYPST}} compile --root . {{DEMO_SRC}} {{DEMO_OUT}}
+ @echo "Wrote {{DEMO_OUT}}"
+
+# Build all preview images
+# Build all preview images
+[group('artifacts')]
+images:
+ {{TT}} run theme-gallery && cp tests/theme-gallery/out/*.png {{THEME_OUT}}
+ {{TT}} run demo && cp tests/demo/out/*.png {{THUMB_OUT}}
+
+# ---------------------------- Housekeeping ----------------------------
+
+# Remove all generated test files and build artifacts
+[group('housekeeping')]
+clean:
+ rg --files tests -g '**/diff/**' -g '**/out/**' 2>/dev/null \
+ | xargs -r dirname \
+ | sort -u \
+ | xargs -r bash -c 'for d; do echo "Removing files under: $d"; rm -rf -- "$d"/*; done' _ \
+ || true
+ rm -rf build
+
+# ---------------------------- Release tooling ----------------------------
+
+# Bump version by level (major|minor|patch) or to explicit version
+[group('release')]
+[script("python3")]
+bump version_or_level:
+ import re
+ from pathlib import Path
+
+ arg = "{{version_or_level}}".strip()
+ if not arg:
+ raise SystemExit("Usage: just bump ")
+
+ # If it's a level keyword, calculate the new version
+ if arg.lower() in {"major", "minor", "patch"}:
+ level = arg.lower()
+ data = Path("typst.toml").read_text()
+ m = re.search(r'^version\s*=\s*"([^"]+)"', data, re.MULTILINE)
+ if not m:
+ raise SystemExit("Could not find current version in typst.toml")
+
+ major, minor, patch = map(int, m.group(1).split("."))
+ old_version = m.group(1)
+
+ if level == "major":
+ major, minor, patch = major + 1, 0, 0
+ elif level == "minor":
+ major, minor, patch = major, minor + 1, 0
+ else:
+ patch += 1
+
+ version = f"{major}.{minor}.{patch}"
+ print(f"Bumping {level} version: {old_version} β {version}")
+ else:
+ # It's an explicit version
+ version = arg
+ print(f"Setting version to {version}")
+
+ # Update files
+ def update(path: Path, pattern: re.Pattern):
+ text = path.read_text()
+ new_text, count = pattern.subn(lambda m: m.group(1) + version + m.group(3), text, count=1)
+ if count == 0:
+ raise SystemExit(f"Failed to update {path}")
+ path.write_text(new_text)
+
+ update(Path("typst.toml"), re.compile(r'^(version\s*=\s*")([^"]+)(")', re.MULTILINE))
+ update(Path("README.md"), re.compile(r'(#import "@preview/glossy:)([^"]+)(": \*)'))
+ print(f"Updated typst.toml and README.md")
+
+
+# Run full pre-submission checks
+[group('release')]
+pre-submit: clean images check
diff --git a/glossy/lib.typ b/glossy/lib.typ
index eeff265..c0f59b9 100644
--- a/glossy/lib.typ
+++ b/glossy/lib.typ
@@ -1,2 +1,2 @@
-#import "src/gloss.typ": init-glossary, glossary
+#import "src/gloss.typ": glossary, init-glossary
#import "src/themes.typ": *
diff --git a/glossy/src/gloss.typ b/glossy/src/gloss.typ
index 83d2a1f..bdd4aaa 100644
--- a/glossy/src/gloss.typ
+++ b/glossy/src/gloss.typ
@@ -59,7 +59,7 @@
longplural: entry.at("longplural", default: __pluralize(long)),
longarticle: entry.at("longarticle", default: __determine_article(long)),
description: entry.at("description", default: none),
- group: entry.at("group", default: "")
+ group: entry.at("group", default: ""),
)
}
@@ -135,7 +135,8 @@
label(__gloss_label_prefix + key + __gloss_entry_postfix)
}
-// Updates the term usage in the glossary state.
+// Updates the term usage (first use counter & wants to be referenced counter)
+// in the glossary state.
//
// Parameters:
// key (string): The glossary entry key
@@ -143,14 +144,18 @@
// Returns:
// none: Updates state as a side effect
//
-#let __mark_term_used(key, count-as-first-use) = {
- counter(__gloss_label_prefix + key).step()
+#let __mark_term_used(key, count-as-referenced, count-as-first-use) = {
+ if count-as-referenced {
+ counter(__gloss_label_prefix + key).step()
+ }
if count-as-first-use {
- counter(__gloss_label_prefix + key + __gloss_first_use_counter_postfix).step()
+ counter(
+ __gloss_label_prefix + key + __gloss_first_use_counter_postfix,
+ ).step()
}
}
-// Queries whether the term is used ANYWHERE
+// Queries whether the term wants to be referenced from ANYWHERE
//
// Parameters:
// key (string): The glossary entry key
@@ -159,9 +164,9 @@
// Returns:
// boolean: If the entry is used above the location in the document
//
-#let __is_term_ever_used(key, location: none) = {
+#let __is_term_ever_referenced(key, location: none) = {
let c = counter(__gloss_label_prefix + key)
- c = if location == none {c.final()} else {c.at(location)}
+ c = if location == none { c.final() } else { c.at(location) }
c.at(0) > 0
}
@@ -178,11 +183,27 @@
// boolean: If the entry is used above the location in the document
//
#let __is_term_first_used(key, location: none) = {
- let c = counter(__gloss_label_prefix + key + __gloss_first_use_counter_postfix)
- c = if location == none {c.final()} else {c.at(location)}
+ let c = counter(
+ __gloss_label_prefix + key + __gloss_first_use_counter_postfix,
+ )
+ c = if location == none { c.final() } else { c.at(location) }
c.at(0) > 0
}
+// Reset the first use counter to 0
+//
+// Parameters:
+// key (string): The glossary entry key
+//
+// Returns:
+// none: Updates state as a side effect
+//
+#let __reset_term_first_used(key, location: none) = {
+ counter(
+ __gloss_label_prefix + key + __gloss_first_use_counter_postfix,
+ ).update(0)
+}
+
// Determine if the glossary contains a visible entry
//
// Parameters:
@@ -207,8 +228,6 @@
// - "long": Show only the long form.
// - "def" or "desc": Show the term's description instead of its name.
// - "a" or "an": Prepend an article, chosen from the entry (short or long form).
-// - "hide" or "hidden": Use term (for the sake of the glossary/index),
-// but don't display it.
// show-term (function): A function that renders the chosen term.
// term-links (boolean): If terms should be clickable links leading to glossary
//
@@ -223,18 +242,88 @@
// content: The fully formatted term, including optional article, capitalization,
// usage tracking metadata, and the chosen form (short, long, or both).
//
-#let __gls(key, modifiers: array, format-term: function, show-term: function, term-links: true, display-text: none) = {
+#let __gls(
+ key,
+ modes-modifiers: array,
+ format-term: function,
+ show-term: function,
+ term-links: true,
+ display-text: none,
+) = {
+ let possible_modes = (
+ "auto",
+ "both",
+ "short",
+ "long",
+ "supplement",
+ "description",
+ "reset",
+ )
// ---------------------------------------------------------------------------
- // Check for illegal modifier combinations
+ // Normalize mode & modifier inputs AND check if the modifiers are valid
// ---------------------------------------------------------------------------
- if ("def" in modifiers or "desc" in modifiers) and modifiers.len() > 1 {
- panic("Cannot use 'def'/'desc' with other modifiers.")
+ let modes-modifiers = modes-modifiers.map(it => {
+ if it == "def" or it == "desc" {
+ return "description"
+ } else if it == "a" or it == "an" {
+ return "an"
+ } else if it == "use" or it == "spend" {
+ return "use"
+ } else if it == "nouse" or it == "nospend" {
+ return "no-use"
+ } else if it == "noref" or it == "noindex" {
+ return "noindex"
+ } else if it in ("both", "short", "long", "reset", "cap", "pl") {
+ return it
+ } else if it in ("auto", "description", "supplement") {
+ panic(
+ it,
+ "is a valid mode, but is not used by applying a modifier with this name. Read the documentation.",
+ )
+ } else {
+ panic(it, "is not a recognized mode or modifier.")
+ }
+ })
+ if display-text != none and display-text != auto {
+ // A supplement is provided, thus the mode is "supplement"
+ modes-modifiers.push("supplement")
}
- if ("a" in modifiers or "an" in modifiers) and ("pl" in modifiers) {
+
+ // ---------------------------------------------------------------------------
+ // Determine the requested modes (plural) and the modifier array
+ // ---------------------------------------------------------------------------
+ modes-modifiers.push("__MIDDLE_ITEM") // unused modifier
+ let (requested_modes, modifiers) = modes-modifiers
+ .sorted(key: it => {
+ if it in possible_modes {
+ // It is a 'mode'
+ return -1
+ } else if it == "__MIDDLE_ITEM" {
+ return 0
+ } else {
+ // It is a 'modifier'
+ return 1
+ }
+ })
+ .split("__MIDDLE_ITEM")
+
+ // ---------------------------------------------------------------------------
+ // Check for illegal mode and/or modifier combinations
+ // ---------------------------------------------------------------------------
+ if requested_modes.len() > 1 {
+ panic("Cannot mix modes ", requested_modes, ", pick one.")
+ }
+ if "description" in requested_modes and modifiers.len() > 0 {
+ panic("Cannot use mode 'def'/'desc' with other modifiers.")
+ }
+ if "reset" in requested_modes and modifiers.len() > 0 {
+ panic("Cannot use mode 'reset' with other modifiers.")
+ }
+ if "an" in modifiers and "pl" in modifiers {
panic("Cannot use 'a'/'an' and 'pl' together.")
}
- if ("hidden" in modifiers or "hide" in modifiers) and modifiers.len() > 1{
- panic("Cannot use 'hide'/'hidden' with other modifiers.")
+ if "use" in modifiers and "no-use" in modifiers {
+ panic("Cannot use 'use'/'spend' and 'nouse'/'nospend' together.")
}
// ---------------------------------------------------------------------------
@@ -243,24 +332,47 @@
let entry = __get_entry(key)
// ---------------------------------------------------------------------------
- // If "def" or "desc" modifier is present, show the entry's description immediately
+ // Determine the requested mode (singular)
// ---------------------------------------------------------------------------
- if "def" in modifiers or "desc" in modifiers {
+ let requested_mode = if requested_modes.len() == 0 {
+ "auto"
+ } else {
+ requested_modes.at(0)
+ }
+
+ // ---------------------------------------------------------------------------
+ // If mode is "description", show the entry's description immediately
+ // ---------------------------------------------------------------------------
+ if requested_mode == "description" {
if entry.description == none {
panic("Use of 'def'/'desc' requires a description be defined.")
}
return show-term([#entry.description])
}
+ // ---------------------------------------------------------------------------
+ // If mode is "reset", reset the (first) usage counter and return immediately
+ // ---------------------------------------------------------------------------
+ if requested_mode == "reset" {
+ __reset_term_first_used(key)
+ return
+ }
// ---------------------------------------------------------------------------
// Manage term usage counting and determine if it's the first reference
// ---------------------------------------------------------------------------
let is_first_use = not __is_term_first_used(key, location: here())
- let count-as-first-use = ("short" not in modifiers and "long" not in modifiers and "both" not in modifiers)
- let wants_reference = ("noref" not in modifiers and "noindex" not in modifiers)
- if wants_reference {
- __mark_term_used(key, count-as-first-use)
- }
+ let default-count-as-first-use = (
+ requested_mode == "auto" or requested_mode == "both"
+ )
+ let force-count-as-first-use = "use" in modifiers
+ let force-skip-as-first-use = "no-use" in modifiers
+ let wants_reference = "noindex" not in modifiers
+ __mark_term_used(
+ key,
+ wants_reference,
+ force-count-as-first-use
+ or (not force-skip-as-first-use and default-count-as-first-use),
+ )
// ---------------------------------------------------------------------------
// Helper Functions
@@ -282,7 +394,7 @@
let capitalize_term = (article, term) => {
if "cap" not in modifiers {
(article, term)
- } else if article == "" {
+ } else if article == none {
// No article present, so capitalize the term's first letter.
(article, upper(term.first()) + term.slice(1))
} else {
@@ -292,14 +404,14 @@
}
// get_article(mode): Returns the appropriate article string based on the mode.
- // - If wants_article is false, returns an empty string.
+ // - If wants_article is false, returns none
// - If mode is "short", return the short article.
// - If mode is "long" or "both", return the long article.
// The calling logic ensures that when mode = "long" or "both", a long form exists.
- let get_article = (mode) => {
- let wants_article = "a" in modifiers or "an" in modifiers
+ let get_article = mode => {
+ let wants_article = "an" in modifiers
if not wants_article {
- ""
+ none
} else if mode == "short" {
entry.article + " "
} else {
@@ -308,67 +420,41 @@
}
}
- // determine_mode(wants_both, wants_long, wants_short, is_first_use, long_available):
- // Decides which mode ("short", "long", or "both") to use.
- // Preference is given to explicit modifiers. If the requested mode can't be fulfilled due to no long form,
- // fall back to "short".
- // If no explicit mode is given, the default behavior is:
- // - On first use and if a long form exists, "both".
- // - Otherwise, "short".
- let determine_mode = (wants_both, wants_long, wants_short, is_first_use, long_available, wants_hidden) => {
- if wants_hidden {
- // If it's hidden, nothing else matters
- "hidden"
- } else if wants_both {
- // Explicit request for "both":
- // If a long form exists, use "both", otherwise fall back to "short".
- if long_available {
- "both"
- } else {
- "short"
- }
- } else if wants_long {
- // Explicit request for "long":
- // If a long form exists, use "long", otherwise fall back to "short".
- if long_available {
- "long"
- } else {
- "short"
- }
- } else if wants_short {
- // Explicit request for "short":
- // Always "short" regardless of availability.
- "short"
- } else {
- // No explicit mode given:
- // On first use with a long form available, default to "both".
- // Otherwise, use "short".
- if is_first_use and long_available {
- "both"
- } else {
- "short"
- }
- }
- }
-
// ---------------------------------------------------------------------------
// Determine desired options based on modifiers and entry.long availability
// ---------------------------------------------------------------------------
- let wants_both = "both" in modifiers
- let wants_long = "long" in modifiers
- let wants_short = "short" in modifiers
- let wants_hidden = ("hidden" in modifiers or "hide" in modifiers)
- let long_available = entry.long != none
+ // Decide which mode ("short", "long", or "both" or "supplement") to use.
+ // If the requested mode can't be fulfilled due to no long form, fall back to "short".
+ // If no explicit mode is given (i.e. we are in 'auto' mode), the default behavior is:
+ // - On first use and if a long form exists, "both".
+ // - Otherwise, "short".
+ if requested_mode == "auto" {
+ // Set requested_mode to automatically determined mode
+ requested_mode = if is_first_use {
+ "both"
+ } else {
+ "short"
+ }
+ }
- // Determine mode using the helper function
- let mode = determine_mode(wants_both, wants_long, wants_short, is_first_use, long_available, wants_hidden)
+ let long_available = entry.long != none
+ let mode = if (
+ (requested_mode == "both" or requested_mode == "long")
+ and not long_available
+ ) {
+ // The fall back case, because long form is not available, but it is requested
+ "short"
+ } else {
+ // No fall back needed, the requested mode can be fulfilled
+ requested_mode
+ }
// Pluralize (if requested)
let short-form = pluralize_term(entry.short, entry.plural)
let long-form = pluralize_term(entry.long, entry.longplural) // `none` safe here
// Apply format-term() to get the term
- let formatted-term = if display-text != none and display-text != auto {
+ let formatted-term = if mode == "supplement" {
// Display text was overriden by user, just accept it (string or content)
display-text
} else {
@@ -380,7 +466,7 @@
// that with content, thus requiring a string here.
// TODO: consider if we want to capitalize *before* this. First intuition is
// "no".
- panic("Your cutsom format-term() function must return a string.")
+ panic("Your custom format-term() function must return a string.")
}
// Get the article, then capitalize either the article or term (if requested)
@@ -390,7 +476,7 @@
// Construct and return the final output
// ---------------------------------------------------------------------------
context {
- let linked-term = if term-links and query(__entry_label(key)).len() > 0 {
+ let linked-term = if term-links and __has_glossary_entry(key) {
link(__entry_label(key), term)
} else {
term
@@ -403,57 +489,44 @@
}
// Create the output content
- if mode == "hidden" {
- // just put the metadata+label out there
- [#metadata("hidden term")#term-label]
- } else {
- // normal term display (ie not hidden)
-
- // create the forward link, if watned
- let linked-term = if term-links and __has_glossary_entry(key) {
- link(label(key), term)
- } else {
- term
- }
-
- // and the final content
- [#article#show-term(linked-term)#metadata(term)#term-label]
- // |^^^^^|^^^^^^^^^ |^^^^^^^^ |^^^^^^^^^^^^
- // \_art.| | |
- // \_ apply user formatting function to the term
- // | |
- // \_ metadata lets us label (ie makes it "labelable")
- // |
- // \_ i.e. <__gloss:key>, etc.
- // for backlink from glossary
- }
+ [#article#show-term(linked-term)#metadata(term)#term-label]
+ // |^^^^^|^^^^^^^^^ |^^^^^^^^ |^^^^^^^^^^
+ // | | | \_ the label for backlink from
+ // | | | glossary i.e. <__gloss:key>, etc.
+ // | | \_ metadata lets us label (ie makes it "labelable")
+ // | \_ apply user formatting function to the term
+ // \_art.
}
}
// Creates page number links back to each usage of a glossary term.
//
-// This function generates a comma-separated list of page numbers, where each
-// number links back to a usage of the term in the document. Duplicate page
-// numbers are removed to avoid redundancy.
+// This function generates an array of page numbers, where each number links
+// back to a usage of the term in the document. Duplicate page numers are
+// removed to avoid redundancy.
//
// Parameters:
// key (string): The glossary entry key
//
// Returns:
-// content: Comma-separated list of linked page numbers
+// array: Linked page numbers
//
-// Example output: "1, 3, 5" where each number links to the term usage on that page
+// Example output after a typical .join(", "):
+// "1, 3, 5" where each number links to the term usage on that page
//
#let __create_backlinks(key) = {
- return context query(__term_label(key)) // find all reference
- .map(meta => { // extract location and page number (or symbol)
+ return query(__term_label(key)) // find all reference
+ .map(meta => {
+ // extract location and page number (or symbol)
let loc = meta.location()
- let page = numbering(__default(loc.page-numbering(), "1"), ..counter(page).at(loc))
+ let page = numbering(
+ __default(loc.page-numbering(), "1"),
+ ..counter(page).at(loc),
+ )
(loc, page)
})
.dedup(key: ((loc, page)) => page) // deduplicate by page
.map(((loc, page)) => link(loc, page)) // create links
- .join(", ")
}
// Formats a term string based on the specified mode.
@@ -474,14 +547,14 @@
// string: The formatted term based on the specified mode.
//
#let __default-format-term(mode, short-form, long-form) = {
- if mode == "short" {
- short-form
- } else if mode == "long" {
- long-form
- } else {
- // mode assumed to be "both"
- long-form + " (" + short-form + ")"
- }
+ if mode == "short" {
+ short-form
+ } else if mode == "long" {
+ long-form
+ } else {
+ // mode assumed to be "both"
+ long-form + " (" + short-form + ")"
+ }
}
// Styles a term to control its display in a document.
@@ -525,17 +598,23 @@
format-term: __default-format-term,
show-term: __default-show-term,
term-links: false,
- body
+ body,
) = context {
// 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",))
+ let checked-entry = z.parse(entry, dict-schema, scope: (
+ "dictionary entry",
+ ))
checked-entries.insert(checked-key, checked-entry)
}
- let checked-format-term = z.parse(show-term, z.function(), scope: ("format-term",))
- let checked-show-term = z.parse(show-term, z.function(), scope: ("show-term",))
+ let checked-format-term = z.parse(show-term, z.function(), scope: (
+ "format-term",
+ ))
+ 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
@@ -556,7 +635,12 @@
// - That "key" does not correspond to an actual entry,
// - There is at least one modifier,
// - The first modifier corresponds to an existing entry key.
- let can_swap = (lower(raw_key) == "a" or lower(raw_key) == "an") and not __has_entry(raw_key) and raw_modifiers.len() > 0 and __has_entry(raw_modifiers.first())
+ let can_swap = (
+ (lower(raw_key) == "a" or lower(raw_key) == "an")
+ and not __has_entry(raw_key)
+ and raw_modifiers.len() > 0
+ and __has_entry(raw_modifiers.first())
+ )
// If we can swap, use the first modifier as the key and insert "a" as the first modifier.
let (key, modifiers) = if can_swap {
@@ -568,7 +652,14 @@
// Now see if this is an actual glossary term key
if __has_entry(key) {
// Found in dictionary, render via __gls()
- __gls(key, modifiers: modifiers.map(lower), format-term: format-term, show-term: show-term, term-links: term-links, display-text: supplement)
+ __gls(
+ key,
+ modes-modifiers: modifiers.map(lower),
+ format-term: format-term,
+ show-term: show-term,
+ term-links: term-links,
+ display-text: supplement,
+ )
} else {
// Not one of ours, so just pass it through
r
@@ -601,7 +692,7 @@
// - long: Long form of term (optional)
// - description: Term description (optional)
// - label: Term's dictionary label
-// - pages: Linked page numbers where term appears
+// - pages: Array of linked page numbers where term appears
// - index: Zero-based entry index within group
// - total: Total entries in group
// groups (array): Optional list of groups to include
@@ -624,14 +715,16 @@
// 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-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()
let all_used = if not show-all {
- all_entries.keys().filter(key => __is_term_ever_used(key))
+ all_entries.keys().filter(key => __is_term_ever_referenced(key))
} else {
all_entries.keys()
}
@@ -672,7 +765,7 @@
long: entry.at("long"),
description: entry.at("description"),
label: [#metadata(key)#__entry_label(key)],
- pages: __create_backlinks(key)
+ pages: __create_backlinks(key),
))
}
}
@@ -685,7 +778,9 @@
let sorted_entries = if sort {
current_entries
// 1. create array of tuples with (lower [if ignore-case], entry)
- .map(e => { if ignore-case { (lower(e.short), e) } else { (e.short, e) } })
+ .map(e => {
+ if ignore-case { (lower(e.short), e) } else { (e.short, e) }
+ })
// 2. sort the tuples (by first element then second)
.sorted() // NOTE: sorted() is NOT language-aware
// 3. strip away the tuple's first element, leaving an array of entries
@@ -713,10 +808,10 @@
output.len(),
for (i, entry) in entries.enumerate() {
(checked-theme.entry)(entry, i, entries.len())
- }
+ },
)
group_index += 1
- }
+ },
)
]
}
diff --git a/glossy/src/schemas.typ b/glossy/src/schemas.typ
index 989e3dd..366c29a 100644
--- a/glossy/src/schemas.typ
+++ b/glossy/src/schemas.typ
@@ -10,8 +10,8 @@
longplural: z.content(optional: true),
description: z.content(optional: true),
group: z.content(optional: true),
- )
- )
+ ),
+ ),
)
#let theme-schema = z.dictionary(
@@ -19,7 +19,7 @@
section: z.function(),
group: z.function(),
entry: z.function(),
- )
+ ),
)
#let groups-list-schema = z.array(pre-transform: z.coerce.array)
diff --git a/glossy/src/themes/academic.typ b/glossy/src/themes/academic.typ
index 975c8ad..4d97bda 100644
--- a/glossy/src/themes/academic.typ
+++ b/glossy/src/themes/academic.typ
@@ -5,7 +5,6 @@
v(1em)
body
},
-
group: (name, index, total, body) => {
if name != "" and total > 1 {
v(1.5em)
@@ -16,7 +15,6 @@
}
body
},
-
entry: (entry, index, total) => {
let short-display = text(weight: "bold", entry.short)
let long-display = if entry.long == none {
@@ -40,10 +38,10 @@
columns: (1fr, auto),
gutter: 0.75em,
[#short-display#long-display#description#entry.label],
- text(fill: rgb("#666666"), entry.pages)
+ text(fill: rgb("#666666"), entry.pages.join(", ")),
)
- }
- )
+ },
+ ),
)
},
)
diff --git a/glossy/src/themes/basic.typ b/glossy/src/themes/basic.typ
index b756c27..8c6bec2 100644
--- a/glossy/src/themes/basic.typ
+++ b/glossy/src/themes/basic.typ
@@ -15,7 +15,6 @@
heading(level: 1, title)
body
},
-
// Renders a group of related glossary terms
// Parameters:
// name: Group name (empty string for ungrouped terms)
@@ -28,7 +27,6 @@
}
body
},
-
// Renders a single glossary entry with term, definition, and page references
// Parameters:
// entry: Dictionary containing term data:
@@ -36,7 +34,7 @@
// - long: Long form of term (optional)
// - description: Term description (optional)
// - label: Term's dictionary label
- // - pages: Linked page numbers where term appears
+ // - pages: Array of linked page numbers where term appears
// index: Zero-based entry index within group
// total: Total entries in group
entry: (entry, index, total) => {
@@ -62,9 +60,9 @@
left: 1em,
bottom: 0.5em,
block(
- [#term#entry.label#long-form#description #h(1em) (pp. #entry.pages)]
- )
- )
+ [#term#entry.label#long-form#description #h(1em) (pp. #entry.pages.join(", "))],
+ ),
+ ),
)
},
)
diff --git a/glossy/src/themes/chicago-index.typ b/glossy/src/themes/chicago-index.typ
index 006c440..91bb498 100644
--- a/glossy/src/themes/chicago-index.typ
+++ b/glossy/src/themes/chicago-index.typ
@@ -5,7 +5,6 @@
heading(level: 1, smallcaps(title))
body
},
-
group: (name, index, total, body) => {
if name != "" and total > 1 {
v(1em)
@@ -14,13 +13,12 @@
}
body
},
-
entry: (entry, index, total) => {
let short-display = text(weight: "regular", entry.short)
let long-display = if entry.long == none {
[]
} else {
- [ β #entry.long] // Using em-dash for Chicago style
+ [ β #entry.long] // Using em-dash for Chicago style
}
let description = if entry.description == none {
@@ -38,10 +36,10 @@
columns: (1fr, auto),
gutter: 1em,
[#short-display#entry.label#long-display#description#entry.label],
- [#entry.pages]
+ [#entry.pages.join(", ")],
)
- }
- )
+ },
+ ),
)
},
)
diff --git a/glossy/src/themes/compact.typ b/glossy/src/themes/compact.typ
index 86a40e3..60c1850 100644
--- a/glossy/src/themes/compact.typ
+++ b/glossy/src/themes/compact.typ
@@ -17,7 +17,6 @@
heading(level: 1, outlined: false, text(weight: "bold", size: 1.1em, title))
body
},
-
// Renders a group of related glossary terms
// Parameters:
// name: Group name (empty string for ungrouped terms)
@@ -30,13 +29,12 @@
spacing: 0.5em,
pad(
top: 0.5em,
- text(weight: "bold", size: 0.9em, name)
- )
+ text(weight: "bold", size: 0.9em, name),
+ ),
)
}
body
},
-
// Renders a single glossary entry with term, definition, and page references
// Parameters:
// entry: Dictionary containing term data:
@@ -44,7 +42,7 @@
// - long: Long form of term (optional)
// - description: Term description (optional)
// - label: Term's dictionary label
- // - pages: Linked page numbers where term appears
+ // - pages: Array of linked page numbers where term appears
// index: Zero-based entry index within group
// total: Total entries in group
entry: (entry, index, total) => {
@@ -53,7 +51,7 @@
size: 0.65em,
weight: "medium",
fill: gray.darken(60%),
- entry.short
+ entry.short,
)
let long-form = if entry.long == none {
@@ -73,7 +71,7 @@
spacing: 0.4em,
grid(
columns: (auto, 1fr, auto),
- align: left+bottom,
+ align: left + bottom,
gutter: 0.5em,
// Term and description column
box[#term#entry.label#long-form #description],
@@ -83,9 +81,9 @@
text(
size: 0.6em,
fill: gray.darken(20%),
- entry.pages
- )
- )
+ entry.pages.join(", "),
+ ),
+ ),
)
},
)
diff --git a/glossy/src/themes/table.typ b/glossy/src/themes/table.typ
index 1dfe1f9..5b32acb 100644
--- a/glossy/src/themes/table.typ
+++ b/glossy/src/themes/table.typ
@@ -4,13 +4,13 @@
heading(level: 1, title)
body
},
-
group: (name, index, total, body) => {
if name != "" and total > 1 {
heading(level: 2, name)
}
- table(columns: 4,
+ table(
+ columns: 4,
stroke: none,
inset: (x, y) => {
if (x == 0) {
@@ -22,11 +22,15 @@
}
},
table.header([*Abbreviation*], [*Full Name*], [*Description*], [*Pages*]),
- ..body
+ ..body,
)
},
-
entry: (entry, index, total) => {
- (entry.short + entry.label, entry.long, entry.description, entry.pages)
- }
+ (
+ entry.short + entry.label,
+ entry.long,
+ entry.description,
+ entry.pages.join(", "),
+ )
+ },
)
diff --git a/glossy/src/themes/twocol.typ b/glossy/src/themes/twocol.typ
index 7183e6e..947fa2d 100644
--- a/glossy/src/themes/twocol.typ
+++ b/glossy/src/themes/twocol.typ
@@ -15,7 +15,6 @@
heading(level: 1, title)
columns(2, body)
},
-
// Renders a group of related glossary terms
// Parameters:
// name: Group name (empty string for ungrouped terms)
@@ -28,7 +27,6 @@
}
body
},
-
// Renders a single glossary entry with term, definition, and page references
// Parameters:
// entry: Dictionary containing term data:
@@ -36,7 +34,7 @@
// - long: Long form of term (optional)
// - description: Term description (optional)
// - label: Term's dictionary label
- // - pages: Linked page numbers where term appears
+ // - pages: Array of linked page numbers where term appears
// index: Zero-based entry index within group
// total: Total entries in group
entry: (entry, index, total) => {
@@ -60,13 +58,17 @@
size: 0.75em,
weight: "light",
grid(
- columns: (auto,1fr,1em,auto),
+ columns: (auto, 1fr, 1em, auto),
align: (left, center, center, right),
- [#short-display#entry.label#long-display#description], // Term with label
- [#repeat(h(0.25em) + "." + h(0.25em))], // Dotted leader line
- [ . ], // A 1em wide dot so we definitely get some break between term and pages
- [#entry.pages] // Page references
- )
+ [#short-display#entry.label#long-display#description],
+ // Term with label
+ [#repeat(h(0.25em) + "." + h(0.25em))],
+ // Dotted leader line
+ [ . ],
+ // A 1em wide dot so we definitely get some break between term and pages
+ [#entry.pages.join(", ")],
+ // Page references
+ ),
)
},
)
diff --git a/glossy/src/utils.typ b/glossy/src/utils.typ
index ea44e8d..9a6be1b 100644
--- a/glossy/src/utils.typ
+++ b/glossy/src/utils.typ
@@ -16,8 +16,8 @@
}
// Helper functions for checking endings
- let ends_with = (suffix) => lower(word).ends-with(suffix)
- let ends_with_any = (suffixes) => suffixes.any((suffix) => ends_with(suffix))
+ let ends_with = suffix => lower(word).ends-with(suffix)
+ let ends_with_any = suffixes => suffixes.any(suffix => ends_with(suffix))
// Map of irregular plurals for common words
let irregulars = (
@@ -80,7 +80,18 @@
// Irregular suffixes
let f_to_ves = ("leaf", "loaf", "calf", "half", "wolf", "thief")
let fe_to_ves = ("wife", "knife", "life")
- let o_to_os = ("photo", "piano", "halo", "radio", "video", "studio", "solo", "taco", "memo", "zero")
+ let o_to_os = (
+ "photo",
+ "piano",
+ "halo",
+ "radio",
+ "video",
+ "studio",
+ "solo",
+ "taco",
+ "memo",
+ "zero",
+ )
// Convenience
let w = lower(word)
@@ -123,7 +134,7 @@
} else if ends_with("is") {
word.slice(0, -2) + "es"
} else if ends_with("on") {
- word + "s"
+ word + "s"
} else if ends_with("o") {
if o_to_os.contains(w) {
word + "s"
@@ -203,7 +214,7 @@
if is_acronym {
// Use acronym rules
- let first_char = upper_word.codepoints().slice(0,1).first()
+ let first_char = upper_word.codepoints().slice(0, 1).first()
if acronym_vowels.contains(first_char) {
"an"
} else {
@@ -211,17 +222,17 @@
}
} else {
// Non-acronym rules
- let first_char = lower_word.codepoints().slice(0,1).first()
+ let first_char = lower_word.codepoints().slice(0, 1).first()
// Special cases for words matching a set of known 'silent h' prefixes
let silent_h_words = (
- "heir", // "air"
- "herb", // "erb" (in American English)
+ "heir", // "air"
+ "herb", // "erb" (in American English)
"homage", // "oh-mij" or "ah-mij"
"honest", // "on-est"
- "honor", // "on-or" (American English)
+ "honor", // "on-or" (American English)
"honour", // "on-our" (British English)
- "hour", // "our"
+ "hour", // "our"
)
if silent_h_words.any(w => lower_word.starts-with(w)) {
return "an"
@@ -235,15 +246,15 @@
// Words starting with 'u', that get the 'yoo' sound
if first_char == "u" {
let yoo_sounds = (
- "ubi", // ubiquitous
- "uni", // unicycle, uniform, universe, university, unilateral, unique, union, etc.
- "usa", // usage, usability
- "use", // use, useful, useless
- "usu", // usual, usually
+ "ubi", // ubiquitous
+ "uni", // unicycle, uniform, universe, university, unilateral, unique, union, etc.
+ "usa", // usage, usability
+ "use", // use, useful, useless
+ "usu", // usual, usually
"usur", // usurp
- "ute", // utensil, uterus
- "uti", // utility, utilize, utilization
- "uto", // utopia, utopian
+ "ute", // utensil, uterus
+ "uti", // utility, utilize, utilization
+ "uto", // utopia, utopian
)
if yoo_sounds.any(w => lower_word.starts-with(w)) {
return "a"
diff --git a/glossy/tests/abbreviated-syntax/ref/1.png b/glossy/tests/abbreviated-syntax/ref/1.png
index 7b6a7b4..d1279bd 100644
Binary files a/glossy/tests/abbreviated-syntax/ref/1.png and b/glossy/tests/abbreviated-syntax/ref/1.png differ
diff --git a/glossy/tests/abbreviated-syntax/test.typ b/glossy/tests/abbreviated-syntax/test.typ
index 369ec55..a38359b 100644
--- a/glossy/tests/abbreviated-syntax/test.typ
+++ b/glossy/tests/abbreviated-syntax/test.typ
@@ -6,10 +6,11 @@
tps: (
short: "TPS",
long: "test procedure specification",
- description: "A document on how to run all the test procedures"),
+ description: "A document on how to run all the test procedures",
+ ),
)
-#show: init-glossary.with(myGlossary, show-term: (body) => [#emph(body)])
+#show: init-glossary.with(myGlossary, show-term: body => [#emph(body)])
#set heading(numbering: "1.1")
#set page(numbering: "1")
@@ -40,18 +41,51 @@ Now make sure I get your @tps:short reports by 2pm!
== Using conflicting modifiers (short, long, both)
-These modifiers are semantically mutually exclusive, by they can be combined
-syntactically. When multiple are used, `glossy` tries to make a smart choice on
-which one to display.
+These modifiers are semantically mutually exclusive. When multiple are used,
+`glossy` throws an error to the compiler, explaining the problem.
+
+#import "/src/gloss.typ": __default-format-term, __gls
+#let manual-gls(key, mods) = __gls(
+ key,
+ modes-modifiers: mods,
+ format-term: __default-format-term,
+ show-term: body => [#strong(body)],
+ term-links: false,
+ display-text: none,
+)
+#assert-panic(manual-gls.with("tps", ("short", "long")))
+#let msg-short-long = "panicked with: \"Cannot mix modes \", (\"short\", \"long\"), \", pick one.\""
+#let msg-short-both = "panicked with: \"Cannot mix modes \", (\"short\", \"both\"), \", pick one.\""
+#let msg-long-both = "panicked with: \"Cannot mix modes \", (\"long\", \"both\"), \", pick one.\""
+#let msg-short-long-both = "panicked with: \"Cannot mix modes \", (\"short\", \"long\", \"both\"), \", pick one.\""
#table(
columns: 2,
- table.header([*Input*], [*Output*]),
+ table.header([*Input*], [*Error*]),
- [`@tps:short:long` ], [@tps:short:long],
- [`@tps:short:both` ], [@tps:short:both],
- [`@tps:long:both` ], [@tps:long:both],
- [`@tps:short:long:both`], [@tps:short:long:both],
+ [`@tps:short:long` ],
+ [#assert.eq(
+ catch(manual-gls.with("tps", ("short", "long"))),
+ msg-short-long,
+ )#msg-short-long],
+
+ [`@tps:short:both` ],
+ [#assert.eq(
+ catch(manual-gls.with("tps", ("short", "both"))),
+ msg-short-both,
+ )#msg-short-both],
+
+ [`@tps:long:both` ],
+ [#assert.eq(
+ catch(manual-gls.with("tps", ("long", "both"))),
+ msg-long-both,
+ )#msg-long-both],
+
+ [`@tps:short:long:both`],
+ [#assert.eq(
+ catch(manual-gls.with("tps", ("short", "long", "both"))),
+ msg-short-long-both,
+ )#msg-short-long-both],
)
#let my-theme = (
@@ -77,12 +111,10 @@ which one to display.
block(
grid(
columns: (auto, 1fr, auto),
- output,
- repeat([#h(0.25em) . #h(0.25em)]),
- entry.pages,
- )
+ output, repeat([#h(0.25em) . #h(0.25em)]), entry.pages.join(", "),
+ ),
)
- }
+ },
)
#glossary(theme: my-theme)
diff --git a/glossy/tests/demo/ref/1.png b/glossy/tests/demo/ref/1.png
index f5208fd..dfa7f93 100644
Binary files a/glossy/tests/demo/ref/1.png and b/glossy/tests/demo/ref/1.png differ
diff --git a/glossy/tests/demo/test.typ b/glossy/tests/demo/test.typ
index 0a422bb..f6ae004 100644
--- a/glossy/tests/demo/test.typ
+++ b/glossy/tests/demo/test.typ
@@ -7,20 +7,23 @@
short: "HTML",
long: "Hypertext Markup Language",
description: "A standard language for creating web pages",
- group: "Web"),
+ group: "Web",
+ ),
css: (
short: "CSS",
long: "Cascading Style Sheets",
description: "A language used for describing the presentation of a document",
- group: "Web"),
+ group: "Web",
+ ),
tps: (
short: "TPS",
long: "test procedure specification",
- description: "A document on how to run all the test procedures"),
- unused: "Unused term, which shouldn't print in the glossary."
+ description: "A document on how to run all the test procedures",
+ ),
+ unused: "Unused term, which shouldn't print in the glossary.",
)
-#show: init-glossary.with(myGlossary, show-term: (body) => [#emph(body)])
+#show: init-glossary.with(myGlossary, show-term: body => [#emph(body)])
#set heading(numbering: "1.1")
#set page(height: auto, width: 6.5in, margin: 1em, numbering: "1")
@@ -78,18 +81,51 @@ Articles are incompatible with the `pl` (plural) modifier.
== Using conflicting modifiers (short, long, both)
-These modifiers are semantically mutually exclusive, by they can be combined
-syntactically. When multiple are used, `glossy` tries to make a smart choice on
-which one to display.
+These modifiers are semantically mutually exclusive. When multiple are used,
+`glossy` throws an error to the compiler, explaining the problem.
+
+#import "/src/gloss.typ": __default-format-term, __gls
+#let manual-gls(key, mods) = __gls(
+ key,
+ modes-modifiers: mods,
+ format-term: __default-format-term,
+ show-term: body => [#strong(body)],
+ term-links: false,
+ display-text: none,
+)
+#assert-panic(manual-gls.with("tps", ("short", "long")))
+#let msg-short-long = "panicked with: \"Cannot mix modes \", (\"short\", \"long\"), \", pick one.\""
+#let msg-short-both = "panicked with: \"Cannot mix modes \", (\"short\", \"both\"), \", pick one.\""
+#let msg-long-both = "panicked with: \"Cannot mix modes \", (\"long\", \"both\"), \", pick one.\""
+#let msg-short-long-both = "panicked with: \"Cannot mix modes \", (\"short\", \"long\", \"both\"), \", pick one.\""
#table(
columns: 2,
- table.header([*Input*], [*Output*]),
+ table.header([*Input*], [*Error*]),
- [`@tps:short:long` ], [@tps:short:long],
- [`@tps:short:both` ], [@tps:short:both],
- [`@tps:long:both` ], [@tps:long:both],
- [`@tps:short:long:both`], [@tps:short:long:both],
+ [`@tps:short:long` ],
+ [#assert.eq(
+ catch(manual-gls.with("tps", ("short", "long"))),
+ msg-short-long,
+ )#msg-short-long],
+
+ [`@tps:short:both` ],
+ [#assert.eq(
+ catch(manual-gls.with("tps", ("short", "both"))),
+ msg-short-both,
+ )#msg-short-both],
+
+ [`@tps:long:both` ],
+ [#assert.eq(
+ catch(manual-gls.with("tps", ("long", "both"))),
+ msg-long-both,
+ )#msg-long-both],
+
+ [`@tps:short:long:both`],
+ [#assert.eq(
+ catch(manual-gls.with("tps", ("short", "long", "both"))),
+ msg-short-long-both,
+ )#msg-short-long-both],
)
#let my-theme = (
@@ -115,14 +151,20 @@ which one to display.
block(
grid(
columns: (auto, 1fr, auto),
- output,
- repeat([#h(0.25em) . #h(0.25em)]),
- entry.pages,
- )
+ output, repeat([#h(0.25em) . #h(0.25em)]), entry.pages.join(", "),
+ ),
)
- }
+ },
)
#glossary(theme: my-theme)
-#glossary(title: "Glossary with just empty group", groups: ("",), theme: theme-basic)
-#glossary(title: "Glossary with just Web group", groups: ("Web",), theme: theme-compact)
+#glossary(
+ title: "Glossary with just empty group",
+ groups: ("",),
+ theme: theme-basic,
+)
+#glossary(
+ title: "Glossary with just Web group",
+ groups: ("Web",),
+ theme: theme-compact,
+)
diff --git a/glossy/tests/determine-article/test.typ b/glossy/tests/determine-article/test.typ
index 6440e4c..40972b2 100644
--- a/glossy/tests/determine-article/test.typ
+++ b/glossy/tests/determine-article/test.typ
@@ -2,285 +2,274 @@
#let tests = (
// Main tests (covers most of English language)
- ("Europe","a"),
- ("European","a"),
- ("Hannah","a"),
- ("T-shirt","a"),
- ("Xerox","a"),
- ("Zebra","a"),
- ("aardvark","an"),
- ("apple","an"),
- ("boat","a"),
- ("car","a"),
- ("cat","a"),
- ("chair","a"),
- ("dog","a"),
- ("egg","an"),
- ("elephant","an"),
- ("emu","an"),
- ("eucalyptus","a"),
- ("eulogy","a"),
- ("euphemism","a"),
- ("exhausted","an"),
- ("ghost","a"),
- ("hat","a"),
- ("heir","an"),
- ("heiress","an"),
- ("herb","an"),
- ("herbal","an"),
- ("historic","a"),
- ("history","a"),
- ("homage","an"),
- ("honest","an"),
- ("honestly","an"),
- ("honor","an"),
- ("honorary","an"),
- ("honour","an"),
- ("horse","a"),
- ("hour","an"),
- ("hourglass","an"),
- ("house","a"),
- ("iris","an"),
- ("orange","an"),
- ("owl","an"),
- ("table","a"),
- ("ugly","an"),
- ("umbrella","an"),
- ("umpire","an"),
- ("unicorn","a"),
- ("unique","a"),
- ("university","a"),
- ("urn","an"),
- ("usage","a"),
- ("user","a"),
- ("utensil","a"),
-
+ ("Europe", "a"),
+ ("European", "a"),
+ ("Hannah", "a"),
+ ("T-shirt", "a"),
+ ("Xerox", "a"),
+ ("Zebra", "a"),
+ ("aardvark", "an"),
+ ("apple", "an"),
+ ("boat", "a"),
+ ("car", "a"),
+ ("cat", "a"),
+ ("chair", "a"),
+ ("dog", "a"),
+ ("egg", "an"),
+ ("elephant", "an"),
+ ("emu", "an"),
+ ("eucalyptus", "a"),
+ ("eulogy", "a"),
+ ("euphemism", "a"),
+ ("exhausted", "an"),
+ ("ghost", "a"),
+ ("hat", "a"),
+ ("heir", "an"),
+ ("heiress", "an"),
+ ("herb", "an"),
+ ("herbal", "an"),
+ ("historic", "a"),
+ ("history", "a"),
+ ("homage", "an"),
+ ("honest", "an"),
+ ("honestly", "an"),
+ ("honor", "an"),
+ ("honorary", "an"),
+ ("honour", "an"),
+ ("horse", "a"),
+ ("hour", "an"),
+ ("hourglass", "an"),
+ ("house", "a"),
+ ("iris", "an"),
+ ("orange", "an"),
+ ("owl", "an"),
+ ("table", "a"),
+ ("ugly", "an"),
+ ("umbrella", "an"),
+ ("umpire", "an"),
+ ("unicorn", "a"),
+ ("unique", "a"),
+ ("university", "a"),
+ ("urn", "an"),
+ ("usage", "a"),
+ ("user", "a"),
+ ("utensil", "a"),
// Acronym tests
- ("ASCII","an"),
- ("CFO","a"),
- ("F.A.Q.","an"),
- ("FBI","an"),
- ("GIF","a"),
- ("HIV","an"),
- ("JPEG","a"),
- ("LED","an"),
- ("MRI","an"),
- ("NATO","an"),
- ("PNG","a"),
- ("Q&A","a"),
- ("RF","an"),
- ("RNG","an"),
- ("SAS","an"),
- ("SMS","an"),
- ("SOS","an"),
- ("SQL","an"),
- ("UFO","a"),
- ("URL","a"),
- ("VCR","a"),
- ("WWW","a"),
- ("X.Y.Z.","an"),
- ("YAML","a"),
-
+ ("ASCII", "an"),
+ ("CFO", "a"),
+ ("F.A.Q.", "an"),
+ ("FBI", "an"),
+ ("GIF", "a"),
+ ("HIV", "an"),
+ ("JPEG", "a"),
+ ("LED", "an"),
+ ("MRI", "an"),
+ ("NATO", "an"),
+ ("PNG", "a"),
+ ("Q&A", "a"),
+ ("RF", "an"),
+ ("RNG", "an"),
+ ("SAS", "an"),
+ ("SMS", "an"),
+ ("SOS", "an"),
+ ("SQL", "an"),
+ ("UFO", "a"),
+ ("URL", "a"),
+ ("VCR", "a"),
+ ("WWW", "a"),
+ ("X.Y.Z.", "an"),
+ ("YAML", "a"),
// Extra tests (courtesy of LLM)
-
// Common English words starting with vowels
- ("idea","an"),
- ("island","an"),
- ("offer","an"),
- ("option","an"),
- ("operation","an"),
- ("appletree","an"),
- ("iguana","an"),
- ("octopus","an"),
- ("atom","an"),
- ("item","an"),
-
+ ("idea", "an"),
+ ("island", "an"),
+ ("offer", "an"),
+ ("option", "an"),
+ ("operation", "an"),
+ ("appletree", "an"),
+ ("iguana", "an"),
+ ("octopus", "an"),
+ ("atom", "an"),
+ ("item", "an"),
// Words starting with vowel but "yoo" sound (thus 'a')
- ("universe","a"),
- ("unicycle","a"),
- ("uniform","a"),
- ("union","a"),
- ("united","a"),
- ("unique","a"), // already tested, reaffirmed
- ("usual","a"),
- ("useful","a"),
- ("utility","a"),
- ("utopia","a"),
-
+ ("universe", "a"),
+ ("unicycle", "a"),
+ ("uniform", "a"),
+ ("union", "a"),
+ ("united", "a"),
+ ("unique", "a"), // already tested, reaffirmed
+ ("usual", "a"),
+ ("useful", "a"),
+ ("utility", "a"),
+ ("utopia", "a"),
// More common vowel words with a/an
- ("umbrella","an"), // repeated but reaffirming
- ("eggplant","an"),
- ("insect","an"),
- ("eleven","an"),
- ("olive","an"),
- ("impulse","an"),
- ("ox","an"),
- ("aroma","an"),
- ("ear","an"),
- ("ocean","an"),
-
+ ("umbrella", "an"), // repeated but reaffirming
+ ("eggplant", "an"),
+ ("insect", "an"),
+ ("eleven", "an"),
+ ("olive", "an"),
+ ("impulse", "an"),
+ ("ox", "an"),
+ ("aroma", "an"),
+ ("ear", "an"),
+ ("ocean", "an"),
// Words starting with 'h' but pronounced, so 'a'
- ("house","a"), // repeated for emphasis
- ("hammer","a"),
- ("helmet","a"),
- ("history","a"), // repeated
- ("hero","a"),
- ("hill","a"),
- ("hobby","a"),
- ("holiday","a"),
- ("harmony","a"),
- ("hover","a"),
-
+ ("house", "a"), // repeated for emphasis
+ ("hammer", "a"),
+ ("helmet", "a"),
+ ("history", "a"), // repeated
+ ("hero", "a"),
+ ("hill", "a"),
+ ("hobby", "a"),
+ ("holiday", "a"),
+ ("harmony", "a"),
+ ("hover", "a"),
// More silent 'h' words (already in set, but variations)
- ("honorific","an"),
- ("honorarium","an"),
- ("honesties","an"),
- ("hourly","an"),
- ("heirloom","an"),
-
+ ("honorific", "an"),
+ ("honorarium", "an"),
+ ("honesties", "an"),
+ ("hourly", "an"),
+ ("heirloom", "an"),
// Words starting with 'e' + 'u' combo with "yoo" sound
- ("Europe","a"), // repeated
- ("European","a"), // repeated
- ("euphoric","a"),
- ("eureka","a"),
- ("euphemistic","a"),
- ("euphonious","a"),
- ("eucalyptus","a"), // repeated
- ("euthanasia","a"),
- ("eugenics","a"),
- ("Eurasia","a"),
-
+ ("Europe", "a"), // repeated
+ ("European", "a"), // repeated
+ ("euphoric", "a"),
+ ("eureka", "a"),
+ ("euphemistic", "a"),
+ ("euphonious", "a"),
+ ("eucalyptus", "a"), // repeated
+ ("euthanasia", "a"),
+ ("eugenics", "a"),
+ ("Eurasia", "a"),
// Common consonant-start words
- ("book","a"),
- ("pen","a"),
- ("fork","a"),
- ("spoon","a"),
- ("knife","a"),
- ("ball","a"),
- ("tree","a"),
- ("river","a"),
- ("mountain","a"),
- ("cloud","a"),
-
+ ("book", "a"),
+ ("pen", "a"),
+ ("fork", "a"),
+ ("spoon", "a"),
+ ("knife", "a"),
+ ("ball", "a"),
+ ("tree", "a"),
+ ("river", "a"),
+ ("mountain", "a"),
+ ("cloud", "a"),
// More vowel-start words
- ("ostrich","an"),
- ("amphibian","an"),
- ("eleven","an"), // repeated
- ("issue","an"),
- ("incense","an"),
- ("antenna","an"),
- ("echo","an"),
- ("aisle","an"),
- ("oracle","an"),
- ("overcoat","an"),
-
+ ("ostrich", "an"),
+ ("amphibian", "an"),
+ ("eleven", "an"), // repeated
+ ("issue", "an"),
+ ("incense", "an"),
+ ("antenna", "an"),
+ ("echo", "an"),
+ ("aisle", "an"),
+ ("oracle", "an"),
+ ("overcoat", "an"),
// More acronym/initialism tests:
- ("ATM","an"), // A = 'ay'
- ("EPA","an"), // E = 'ee'
- ("FAQ","an"), // F = 'eff', repeated as F.A.Q.
- ("HTML","an"), // H = 'aitch'
- ("IBM","an"), // I = 'eye'
- ("LAN","an"), // L = 'el'
- ("NFL","an"), // N = 'en'
- ("OSHA","an"), // O = 'oh'
- ("RAM","an"), // R = 'ar'
- ("SMS","an"), // repeated, S = 'ess'
-
+ ("ATM", "an"), // A = 'ay'
+ ("EPA", "an"), // E = 'ee'
+ ("FAQ", "an"), // F = 'eff', repeated as F.A.Q.
+ ("HTML", "an"), // H = 'aitch'
+ ("IBM", "an"), // I = 'eye'
+ ("LAN", "an"), // L = 'el'
+ ("NFL", "an"), // N = 'en'
+ ("OSHA", "an"), // O = 'oh'
+ ("RAM", "an"), // R = 'ar'
+ ("SMS", "an"), // repeated, S = 'ess'
// Acronyms starting with consonant sound letters
- ("GIF","a"), // G = 'jee', repeated
- ("CFO","a"), // C = 'see', repeated (consonant sound 's')
- ("CEO","a"), // C = 'see'
- ("DNA","a"), // D = 'dee' starts with 'd' consonant sound
- ("PGA","a"), // P = 'pee' starts with 'p' consonant sound
- ("QVC","a"), // Q = 'kyoo' starts with 'k' consonant sound
- ("TNT","a"), // T = 'tee' starts with 't' consonant sound
- ("UPS","a"), // U = 'yoo' sound, hence 'a'
- ("VIP","a"), // V = 'vee' starts with 'v' consonant sound
- ("WIPO","a"), // W = 'double-u' starts with 'd' consonant sound
-
+ ("GIF", "a"), // G = 'jee', repeated
+ ("CFO", "a"), // C = 'see', repeated (consonant sound 's')
+ ("CEO", "a"), // C = 'see'
+ ("DNA", "a"), // D = 'dee' starts with 'd' consonant sound
+ ("PGA", "a"), // P = 'pee' starts with 'p' consonant sound
+ ("QVC", "a"), // Q = 'kyoo' starts with 'k' consonant sound
+ ("TNT", "a"), // T = 'tee' starts with 't' consonant sound
+ ("UPS", "a"), // U = 'yoo' sound, hence 'a'
+ ("VIP", "a"), // V = 'vee' starts with 'v' consonant sound
+ ("WIPO", "a"), // W = 'double-u' starts with 'd' consonant sound
// More tricky 'u' words with 'yoo' sound for 'a'
- ("unify","a"),
- ("unilateral","a"),
- ("ubiquitous","a"), // 'yoo-bik...'
- ("usurp","a"),
- ("usuary","a"), // 'yoo-zhoo-ary' (rare, but treat like usual)
- ("uterus","a"), // 'yoo-terus'
- ("usher","an"), // 'uh-sher' vowel sound
- ("ugly","an"), // repeated, 'uh-glee'
- ("upper","an"), // 'uh-pur' (vowel sound but actually 'uh' sound = 'an'? Actually "upper" starts with a simple vowel sound 'uh', so should it be 'an'? It's commonly "an upper hand".
- ("update","an"), // 'up-date' starts with 'uh' vowel sound β 'an update' normally. Actually we say "an update" commonly. Correcting to 'an':
-
+ ("unify", "a"),
+ ("unilateral", "a"),
+ ("ubiquitous", "a"), // 'yoo-bik...'
+ ("usurp", "a"),
+ ("usuary", "a"), // 'yoo-zhoo-ary' (rare, but treat like usual)
+ ("uterus", "a"), // 'yoo-terus'
+ ("usher", "an"), // 'uh-sher' vowel sound
+ ("ugly", "an"), // repeated, 'uh-glee'
+ ("upper", "an"), // 'uh-pur' (vowel sound but actually 'uh' sound = 'an'? Actually "upper" starts with a simple vowel sound 'uh', so should it be 'an'? It's commonly "an upper hand".
+ ("update", "an"), // 'up-date' starts with 'uh' vowel sound β 'an update' normally. Actually we say "an update" commonly. Correcting to 'an':
// Words starting with 'u' that actually take "an"
// (because they start with a vowel sound 'uh'):
- ("under","an"),
- ("understand","an"),
- ("unusual","an"),
- ("unreal","an"),
- ("unemployed","an"),
- ("unequal","an"),
- ("unopened","an"),
- ("unarmed","an"),
- ("uneasy","an"),
- ("united","a"), // 'yoo-nited' is 'a united front'
- ("universal","a"),
- ("umbrella","an"), // repeated
- ("upset","an"), // 'uh-pset' vowel start
-
+ ("under", "an"),
+ ("understand", "an"),
+ ("unusual", "an"),
+ ("unreal", "an"),
+ ("unemployed", "an"),
+ ("unequal", "an"),
+ ("unopened", "an"),
+ ("unarmed", "an"),
+ ("uneasy", "an"),
+ ("united", "a"), // 'yoo-nited' is 'a united front'
+ ("universal", "a"),
+ ("umbrella", "an"), // repeated
+ ("upset", "an"), // 'uh-pset' vowel start
// More vowel words to ensure coverage:
- ("animal","an"),
- ("image","an"),
- ("order","an"),
- ("arrow","an"),
- ("ace","an"),
- ("acre","an"),
- ("agent","an"),
- ("artist","an"),
- ("idea","an"), // repeated
- ("aim","an"),
- ("item","an"), // repeated
- ("isotope","an"),
- ("opera","an"),
-
+ ("animal", "an"),
+ ("image", "an"),
+ ("order", "an"),
+ ("arrow", "an"),
+ ("ace", "an"),
+ ("acre", "an"),
+ ("agent", "an"),
+ ("artist", "an"),
+ ("idea", "an"), // repeated
+ ("aim", "an"),
+ ("item", "an"), // repeated
+ ("isotope", "an"),
+ ("opera", "an"),
// Words starting with vowels but pronounced with consonant sound 'y' β 'a'
- ("euphemistic","a"), // repeated
- ("euphoric","a"),
- ("eulogy","a"), // repeated
- ("Europe","a"), // repeated
- ("European","a"), // repeated
- ("eugenics","a"), // repeated
- ("euphemism","a"), // repeated
- ("eureka","a"), // repeated
- ("euphonious","a"),
- ("Eurasia","a"),
-
+ ("euphemistic", "a"), // repeated
+ ("euphoric", "a"),
+ ("eulogy", "a"), // repeated
+ ("Europe", "a"), // repeated
+ ("European", "a"), // repeated
+ ("eugenics", "a"), // repeated
+ ("euphemism", "a"), // repeated
+ ("eureka", "a"), // repeated
+ ("euphonious", "a"),
+ ("Eurasia", "a"),
// Common consonant-start words:
- ("milk","a"),
- ("road","a"),
- ("stone","a"),
- ("book","a"), // repeated
- ("pen","a"), // repeated
- ("fork","a"), // repeated
- ("spoon","a"), // repeated
- ("knife","a"), // 'knife' actually starts with /n/ sound because 'k' is silent. "a knife" or "an knife"? It's "a knife" (starts with 'n' consonant sound?), actually 'kn' in 'knife' is silent, so 'knife' is pronounced 'nife' with a consonant sound 'n', so "a knife" is correct.
- ("glass","a"),
- ("window","a"),
-
+ ("milk", "a"),
+ ("road", "a"),
+ ("stone", "a"),
+ ("book", "a"), // repeated
+ ("pen", "a"), // repeated
+ ("fork", "a"), // repeated
+ ("spoon", "a"), // repeated
+ ("knife", "a"), // 'knife' actually starts with /n/ sound because 'k' is silent. "a knife" or "an knife"? It's "a knife" (starts with 'n' consonant sound?), actually 'kn' in 'knife' is silent, so 'knife' is pronounced 'nife' with a consonant sound 'n', so "a knife" is correct.
+ ("glass", "a"),
+ ("window", "a"),
// Final checks with tricky silent letters:
- ("gnome","a"), // 'g' silent, pronounced 'nome' with 'n' consonant sound β 'a gnome'
- ("gnat","a"), // 'nat' consonant sound β 'a gnat'
- ("xylophone","a"), // 'zylophone' β 'z' consonant sound β 'a xylophone'
- ("xenon","a"), // 'zee-non' consonant sound 'z' β 'a xenon'
- ("honorific","an"), // repeated but reaffirming
- ("hourly","an"), // repeated but reaffirming
- ("honorably","an"),
- ("honorifics","an"),
- ("honors","an"),
+ ("gnome", "a"), // 'g' silent, pronounced 'nome' with 'n' consonant sound β 'a gnome'
+ ("gnat", "a"), // 'nat' consonant sound β 'a gnat'
+ ("xylophone", "a"), // 'zylophone' β 'z' consonant sound β 'a xylophone'
+ ("xenon", "a"), // 'zee-non' consonant sound 'z' β 'a xenon'
+ ("honorific", "an"), // repeated but reaffirming
+ ("hourly", "an"), // repeated but reaffirming
+ ("honorably", "an"),
+ ("honorifics", "an"),
+ ("honors", "an"),
)
#for (word, article) in tests {
let chosen = __determine_article(word)
if chosen != article {
- panic("bad choice! word: " + word + ", article: " + article + ", chosen: " + chosen)
+ panic(
+ "bad choice! word: "
+ + word
+ + ", article: "
+ + article
+ + ", chosen: "
+ + chosen,
+ )
}
}
diff --git a/glossy/tests/format-term/test.typ b/glossy/tests/format-term/test.typ
index c38ed49..064ff73 100644
--- a/glossy/tests/format-term/test.typ
+++ b/glossy/tests/format-term/test.typ
@@ -5,20 +5,24 @@
short: "HTML",
long: "Hypertext Markup Language",
description: "A standard language for creating web pages",
- group: "Web"),
+ group: "Web",
+ ),
css: (
short: "CSS",
long: "Cascading Style Sheets",
description: "A language used for describing the presentation of a document",
- group: "Web"),
+ group: "Web",
+ ),
tps: (
short: "TPS",
long: "test procedure specification",
- description: "A document on how to run all the test procedures"),
+ description: "A document on how to run all the test procedures",
+ ),
concise: "Concise syntax!",
shortonly: (
- short: "shortonly!!!"),
- unused: "Unused term, which shouldn't print in the glossary."
+ short: "shortonly!!!",
+ ),
+ unused: "Unused term, which shouldn't print in the glossary.",
)
#set page(width: 6.5in, height: auto, margin: 1em)
@@ -26,23 +30,21 @@
#let test-content = {
table(
columns: 3,
- table.header(
- [`short`], [`long`], [`both`],
- ),
+ table.header([`short`], [`long`], [`both`]),
- [@html:short], [@html:long], [@html:both],
- [@css:short], [@css:long], [@css:both],
- [@tps:short], [@tps:long], [@tps:both],
- [@concise:short], [@concise:long], [@concise:both],
+ [@html:short], [@html:long], [@html:both],
+ [@css:short], [@css:long], [@css:both],
+ [@tps:short], [@tps:long], [@tps:both:nouse],
+ [@concise:short], [@concise:long], [@concise:both],
[@shortonly:short], [@shortonly:long], [@shortonly:both],
table.hline(stroke: 2pt),
- [@html:short:cap], [@html:long:cap], [@html:both:cap],
- [@a:css:short], [@a:css:long], [@a:css:both],
- [@tps:short:pl], [@tps:long:pl], [@tps:both:pl],
- [@concise:a:cap:short], [@concise:a:cap:long], [@concise:a:cap:both],
- [@an:shortonly:short], [@an:shortonly:long], [@an:shortonly:both],
+ [@html:short:cap], [@html:long:cap], [@html:both:cap],
+ [@a:css:short], [@a:css:long], [@a:css:both],
+ [@tps:short:pl], [@tps:long:pl], [@tps:both:nouse:pl],
+ [@concise:a:cap:short], [@concise:a:cap:long], [@concise:a:cap:both],
+ [@an:shortonly:short], [@an:shortonly:long], [@an:shortonly:both],
)
[@a:tps:cap is @tps:def.]
@@ -54,7 +56,7 @@
if mode == "short" {
short-form
} else if mode == "long" {
- long-form
+ long-form
} else {
long-form + " (" + short-form + ")"
}
@@ -79,7 +81,7 @@
// ---------------------------------------------------------------------------------
#let format-uppercase-short(mode, short-form, long-form) = {
- let short-up = upper(short-form);
+ let short-up = upper(short-form)
if mode == "short" {
short-up
} else if mode == "long" {
@@ -108,8 +110,8 @@
// ---------------------------------------------------------------------------------
#let format-conditional-separator(mode, short-form, long-form) = {
- let separator = if short-form.len() > 4 { " / " } else { ", " };
- let has_long = long-form != none and long-form != "";
+ let separator = if short-form.len() > 4 { " / " } else { ", " }
+ let has_long = long-form != none and long-form != ""
if mode == "short" {
short-form
@@ -124,7 +126,10 @@
}
}
-#init-glossary(myGlossary, format-term: format-conditional-separator)[#test-content]
+#init-glossary(
+ myGlossary,
+ format-term: format-conditional-separator,
+)[#test-content]
// ---------------------------------------------------------------------------------
// 1. Braces and Labels
@@ -145,7 +150,9 @@
// 2. Mode-Based Prefix
// Idea: Add a prefix indicating the mode, and then show the term(s).
#let format-mode-prefix(mode, short-form, long-form) = {
- let prefix = if mode == "short" { "S:" } else if mode == "long" { "L:" } else { "B:" };
+ let prefix = if mode == "short" { "S:" } else if mode == "long" {
+ "L:"
+ } else { "B:" }
if mode == "short" {
prefix + short-form
} else if mode == "long" {
@@ -161,7 +168,7 @@
// 3. Conditional Fallback for Missing Long
// Idea: If no long-form is provided, use the short-form in all cases.
#let format-fallback-long(mode, short-form, long-form) = {
- let has_long = long-form != none and long-form != "";
+ let has_long = long-form != none and long-form != ""
if mode == "short" {
short-form
} else if mode == "long" {
@@ -193,7 +200,9 @@
// Idea: In both mode, append the length of each string.
#let format-length-info(mode, short-form, long-form) = {
let s_len = str(short-form.len())
- let l_len = if long-form != none and long-form != "" { str(long-form.len()) } else { "0" }
+ let l_len = if long-form != none and long-form != "" {
+ str(long-form.len())
+ } else { "0" }
if mode == "short" {
short-form + " [len:" + s_len + "]"
diff --git a/glossy/tests/forward-links/ref/1.png b/glossy/tests/forward-links/ref/1.png
index 66ddcde..012c7b4 100644
Binary files a/glossy/tests/forward-links/ref/1.png and b/glossy/tests/forward-links/ref/1.png differ
diff --git a/glossy/tests/forward-links/test.typ b/glossy/tests/forward-links/test.typ
index 85c2406..8b1e093 100644
--- a/glossy/tests/forward-links/test.typ
+++ b/glossy/tests/forward-links/test.typ
@@ -1,5 +1,5 @@
#import "/lib.typ": *
-#import "@preview/glossarium:0.5.3": *
+#import "@preview/glossarium:0.5.9": *
#set page(height: auto, width: 4.5in)
#show link: set text(fill: red)
@@ -19,7 +19,7 @@
This should be a link, too: @WWW
#glossary()
- ]
+ ],
)
// -----------------------------------------------------------------------------
@@ -41,5 +41,5 @@
This should be a link, too: @ML
#print-glossary(entry-list)
- ]
+ ],
)
diff --git a/glossy/tests/group-specified/test.typ b/glossy/tests/group-specified/test.typ
index 58720ae..e0bab26 100644
--- a/glossy/tests/group-specified/test.typ
+++ b/glossy/tests/group-specified/test.typ
@@ -12,22 +12,22 @@ Reference: @pbr, @zbuffer
]
#t("abbreviations") // "string" : str
-#t(("abbreviations")) // ("string") : str
+#t("abbreviations") // ("string") : str
#t(("abbreviations",)) // ("string",) : array(str)
-#t(("abbreviations","abbreviations")) // ("string","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
-#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
+#t(none) // none should be all groups
#pagebreak(weak: true)
-#t(("abbreviations",none)) // try to get both groups
+#t(("abbreviations", none)) // try to get both groups
diff --git a/glossy/tests/hidden-terms/test.typ b/glossy/tests/hidden-terms/test.typ
index ffbaf3a..0211dc7 100644
--- a/glossy/tests/hidden-terms/test.typ
+++ b/glossy/tests/hidden-terms/test.typ
@@ -5,17 +5,20 @@
short: "HTML",
long: "Hypertext Markup Language",
description: "A standard language for creating web pages",
- group: "Web"),
+ group: "Web",
+ ),
css: (
short: "CSS",
long: "Cascading Style Sheets",
description: "A language used for describing the presentation of a document",
- group: "Web"),
+ group: "Web",
+ ),
tps: (
short: "TPS",
long: "test procedure specification",
- description: "A document on how to run all the test procedures"),
- unused: "Unused term, which shouldn't print in the glossary."
+ description: "A document on how to run all the test procedures",
+ ),
+ unused: "Unused term, which shouldn't print in the glossary.",
)
#show: init-glossary.with(myGlossary)
@@ -24,9 +27,9 @@
= Hiding terms
-Here's a hidden term: @html:hide
+Here's a hidden term: @html[]
-Here's another hidden term: @css:hidden
+Here's another hidden term: @css[]
And here's a shown term: @tps
diff --git a/glossy/tests/no-sort/test.typ b/glossy/tests/no-sort/test.typ
index 554f927..ec71ff6 100644
--- a/glossy/tests/no-sort/test.typ
+++ b/glossy/tests/no-sort/test.typ
@@ -1,4 +1,4 @@
-#import "/lib.typ":*
+#import "/lib.typ": *
#show: init-glossary.with(yaml("glossary.yml"))
diff --git a/glossy/tests/noref/test.typ b/glossy/tests/noref/test.typ
index ba62835..334c81c 100644
--- a/glossy/tests/noref/test.typ
+++ b/glossy/tests/noref/test.typ
@@ -2,10 +2,10 @@
// Our test glossary
#show: init-glossary.with((
- Normal: "this is a normal term",
- NoRef: "this term is noref'd",
- NoIndex: "this term is noindex'd",
- NoRefNoIndex: "this term is noref'd and noindex'd",
+ Normal: "this is a normal term",
+ NoRef: "this term is noref'd",
+ NoIndex: "this term is noindex'd",
+ NoRefNoIndex: "this term is noref'd and noindex'd",
))
// Configure styling
diff --git a/glossy/tests/override-display/ref/1.png b/glossy/tests/override-display/ref/1.png
index d077037..144db79 100644
Binary files a/glossy/tests/override-display/ref/1.png and b/glossy/tests/override-display/ref/1.png differ
diff --git a/glossy/tests/override-display/test.typ b/glossy/tests/override-display/test.typ
index e5a01b3..8403c70 100644
--- a/glossy/tests/override-display/test.typ
+++ b/glossy/tests/override-display/test.typ
@@ -5,17 +5,20 @@
short: "HTML",
long: "Hypertext Markup Language",
description: "A standard language for creating web pages",
- group: "Web"),
+ group: "Web",
+ ),
css: (
short: "CSS",
long: "Cascading Style Sheets",
description: "A language used for describing the presentation of a document",
- group: "Web"),
+ group: "Web",
+ ),
tps: (
short: "TPS",
long: "test procedure specification",
- description: "A document on how to run all the test procedures"),
- unused: "Unused term, which shouldn't print in the glossary."
+ description: "A document on how to run all the test procedures",
+ ),
+ unused: "Unused term, which shouldn't print in the glossary.",
)
#show: init-glossary.with(myGlossary)
diff --git a/glossy/tests/page-numbers/test.typ b/glossy/tests/page-numbers/test.typ
index 706d873..53ac5e0 100644
--- a/glossy/tests/page-numbers/test.typ
+++ b/glossy/tests/page-numbers/test.typ
@@ -20,7 +20,7 @@
tps: (
short: "TPS",
long: "test procedure specification",
- description: "A document on how to run all the test procedures"
+ description: "A document on how to run all the test procedures",
),
)
diff --git a/glossy/tests/pluralize/test.typ b/glossy/tests/pluralize/test.typ
index d9af75f..634e8de 100644
--- a/glossy/tests/pluralize/test.typ
+++ b/glossy/tests/pluralize/test.typ
@@ -294,11 +294,11 @@
if result != expected {
panic(
"Pluralization failed for: "
- + (if singular == none { "none" } else { str(singular) })
- + ". Expected: "
- + (if expected == none { "none" } else { str(expected) })
- + ", got: "
- + (if result == none { "none" } else { str(result) })
+ + (if singular == none { "none" } else { str(singular) })
+ + ". Expected: "
+ + (if expected == none { "none" } else { str(expected) })
+ + ", got: "
+ + (if result == none { "none" } else { str(result) }),
)
}
}
diff --git a/glossy/tests/refs-exhaustive/ref/1.png b/glossy/tests/refs-exhaustive/ref/1.png
index d7e6746..23cd59a 100644
Binary files a/glossy/tests/refs-exhaustive/ref/1.png and b/glossy/tests/refs-exhaustive/ref/1.png differ
diff --git a/glossy/tests/refs-exhaustive/ref/2.png b/glossy/tests/refs-exhaustive/ref/2.png
index 7898d3b..299fe65 100644
Binary files a/glossy/tests/refs-exhaustive/ref/2.png and b/glossy/tests/refs-exhaustive/ref/2.png differ
diff --git a/glossy/tests/refs-exhaustive/ref/3.png b/glossy/tests/refs-exhaustive/ref/3.png
index d7dbaf7..fb83da5 100644
Binary files a/glossy/tests/refs-exhaustive/ref/3.png and b/glossy/tests/refs-exhaustive/ref/3.png differ
diff --git a/glossy/tests/refs-exhaustive/ref/4.png b/glossy/tests/refs-exhaustive/ref/4.png
index 13d9c6e..e4831bb 100644
Binary files a/glossy/tests/refs-exhaustive/ref/4.png and b/glossy/tests/refs-exhaustive/ref/4.png differ
diff --git a/glossy/tests/refs-exhaustive/ref/5.png b/glossy/tests/refs-exhaustive/ref/5.png
index 160a403..03be655 100644
Binary files a/glossy/tests/refs-exhaustive/ref/5.png and b/glossy/tests/refs-exhaustive/ref/5.png differ
diff --git a/glossy/tests/refs-exhaustive/ref/6.png b/glossy/tests/refs-exhaustive/ref/6.png
deleted file mode 100644
index fcbc89b..0000000
Binary files a/glossy/tests/refs-exhaustive/ref/6.png and /dev/null differ
diff --git a/glossy/tests/refs-exhaustive/test.typ b/glossy/tests/refs-exhaustive/test.typ
index ca19418..26eeeeb 100644
--- a/glossy/tests/refs-exhaustive/test.typ
+++ b/glossy/tests/refs-exhaustive/test.typ
@@ -37,79 +37,68 @@
short: "HTML",
long: "Hypertext Markup Language",
description: "A standard language for creating web pages",
- group: "Web"
+ group: "Web",
),
-
css: (
short: "CSS",
long: "Cascading Style Sheets",
description: "A language used for describing the presentation of documents",
- group: "Web"
+ group: "Web",
),
-
// Term with no description
js: (
short: "JS",
long: "JavaScript",
- group: "Web"
+ group: "Web",
),
-
// Term with only a short field
tcp: (
short: "TCP",
- group: "Networking"
+ group: "Networking",
),
-
// Term with only a long field
// should panic!
//udp: (
// long: "User Datagram Protocol",
// group: "Networking"
//),
-
// Term with short and description, but no long
ip: (
short: "IP",
description: "A unique identifier for a host or network interface",
- group: "Networking"
+ group: "Networking",
),
-
// Term with custom articles and everything defined
api: (
short: "API",
long: "Application Programming Interface",
description: "A set of protocols and tools for building software",
- article: "an", // custom article for short form
- longarticle: "an", // custom article for long form
- group: "Software"
+ article: "an", // custom article for short form
+ longarticle: "an", // custom article for long form
+ group: "Software",
),
-
// Term starting with a vowel, no custom article, to test default a/an logic
xml: (
short: "XML",
long: "Extensible Markup Language",
description: "A markup language defining rules for encoding documents",
- group: "Data"
+ group: "Data",
),
-
// Term starting with a consonant, no custom article
cpu: (
short: "CPU",
long: "Central Processing Unit",
description: "The primary component of a computer that performs calculations",
- group: "Hardware"
+ group: "Hardware",
),
-
// Term without any fields (just a string), should be handled gracefully
bare: "A bare term with no fields",
-
// Term with only description
// should panic!
//desconly: (
// description: "Just a description, no short or long",
// group: "Misc"
//),
-
// Term with article fields but missing short and long (should test fallback)
// should panic!
//articonly: (
@@ -118,51 +107,46 @@
// description: "Has only articles and a description",
// group: "Misc"
//),
-
// Term with uppercase key
SSL: (
short: "SSL",
long: "Secure Sockets Layer",
description: "A protocol for encrypting information over the internet",
- group: "Security"
+ group: "Security",
),
-
// Term that will not be referenced
unusedterm: (
short: "UNUSED",
long: "Unused Term",
- description: "Should not appear since it's never referenced"
+ description: "Should not appear since it's never referenced",
),
-
// Term that tests pluralization with custom fields maybe
doc: (
short: "doc",
long: "document",
description: "A single piece of written matter",
- group: "Misc"
+ group: "Misc",
),
-
// Terms that might require checking conflicting modifiers
tps: (
short: "TPS",
long: "test procedure specification",
description: "A document describing test procedures",
- group: "Testing"
+ group: "Testing",
),
-
// Term that might appear multiple times
http: (
short: "HTTP",
long: "Hypertext Transfer Protocol",
description: "A protocol for distributed, collaborative, hypermedia information systems",
- group: "Web"
- )
+ group: "Web",
+ ),
)
// Initialize the glossary with a custom show-term callback
#show: init-glossary.with(
exhaustiveGlossary,
- show-term: (body) => [#strong(body)]
+ show-term: body => [#strong(body)],
)
#set heading(numbering: "1.1")
@@ -293,14 +277,32 @@ This document tries all reference forms and modifiers on a large set of terms.
== Conflicting multiple modifiers combined (short, long, both together)
-- @tps:short:long
-- @tps:short:both
-- @tps:long:both
-- @tps:short:long:both
-- @html:both:long:short
-- @doc:long:short
-- @cpu:both:long:short
-- @api:short:long:both
+Assert that a panic occurs.
+#import "/src/gloss.typ": __default-format-term, __gls
+#let manual-gls(key, mods) = __gls(
+ key,
+ modes-modifiers: mods,
+ format-term: __default-format-term,
+ show-term: body => [#strong(body)],
+ term-links: false,
+ display-text: none,
+)
+//- @tps:short:long
+#assert-panic(manual-gls.with("tps", ("short", "long")))
+//- @tps:short:both
+#assert-panic(manual-gls.with("tps", ("short", "both")))
+//- @tps:long:both
+#assert-panic(manual-gls.with("tps", ("long", "both")))
+//- @tps:short:long:both
+#assert-panic(manual-gls.with("tps", ("short", "long", "both")))
+//- @html:both:long:short
+#assert-panic(manual-gls.with("html", ("both", "long", "short")))
+//- @doc:long:short
+#assert-panic(manual-gls.with("doc", ("long", "short")))
+//- @cpu:both:long:short
+#assert-panic(manual-gls.with("cpu", ("both", "long", "short")))
+//- @api:short:long:both
+#assert-panic(manual-gls.with("api", ("short", "long", "both")))
== Combining capitalization and plural with short/long/both
@@ -337,19 +339,19 @@ This document tries all reference forms and modifiers on a large set of terms.
#table(
columns: 3,
- table.header([*Input*],[*Output*],[*Comment*]),
- [`@api` ], [@api], ["default"],
- [`@api:short` ], [@api:short], ["short only"],
- [`@api:long` ], [@api:long], ["long only"],
- [`@api:both` ], [@api:both], ["both"],
- [`@api:def` ], [@api:def], ["definition (long)"],
- [`@api:desc` ], [@api:desc], ["description"],
- [`@a:api` ], [@a:api], ["article before key"],
- [`@api:a` ], [@api:a], ["article after key"],
- [`@api:cap` ], [@api:cap], ["capitalize"],
- [`@api:pl` ], [@api:pl], ["plural"],
- [`@api:long:cap`], [@api:long:cap],["long + cap"],
- [`@api:both:pl` ], [@api:both:pl], ["both + pl"]
+ table.header([*Input*], [*Output*], [*Comment*]),
+ [`@api` ], [@api], ["default"],
+ [`@api:short` ], [@api:short], ["short only"],
+ [`@api:long` ], [@api:long], ["long only"],
+ [`@api:both` ], [@api:both], ["both"],
+ [`@api:def` ], [@api:def], ["definition (long)"],
+ [`@api:desc` ], [@api:desc], ["description"],
+ [`@a:api` ], [@a:api], ["article before key"],
+ [`@api:a` ], [@api:a], ["article after key"],
+ [`@api:cap` ], [@api:cap], ["capitalize"],
+ [`@api:pl` ], [@api:pl], ["plural"],
+ [`@api:long:cap`], [@api:long:cap], ["long + cap"],
+ [`@api:both:pl` ], [@api:both:pl], ["both + pl"],
)
== Multiple glossaries with themes and group filtering
@@ -366,25 +368,41 @@ This document tries all reference forms and modifiers on a large set of terms.
== Networking Only
-#glossary(title: "Networking Terms", groups: ("Networking",), theme: theme-basic)
+#glossary(
+ title: "Networking Terms",
+ groups: ("Networking",),
+ theme: theme-basic,
+)
== Misc and Data
-#glossary(title: "Misc & Data", groups: ("Misc","Data"), theme: theme-basic)
+#glossary(title: "Misc & Data", groups: ("Misc", "Data"), theme: theme-basic)
== Just Testing terms
-#glossary(title: "Testing Terms", groups: ("Testing",), theme: theme-chicago-index)
+#glossary(
+ title: "Testing Terms",
+ groups: ("Testing",),
+ theme: theme-chicago-index,
+)
== Hardware group
-#glossary(title: "Hardware Terms", groups: ("Hardware",), theme: theme-chicago-index)
+#glossary(
+ title: "Hardware Terms",
+ groups: ("Hardware",),
+ theme: theme-chicago-index,
+)
== Unreferenced entries
-#glossary(title: "Unreferenced (Should Contain Unused?)", groups: ("Security",), theme: theme-chicago-index)
+#glossary(
+ title: "Unreferenced (Should Contain Unused?)",
+ groups: ("Security",),
+ theme: theme-chicago-index,
+)
== Empty group glossary
-#glossary(title: "Empty Group Glossary", groups: (""), theme: theme-basic)
+#glossary(title: "Empty Group Glossary", groups: "", theme: theme-basic)
= End of Brutal Test
diff --git a/glossy/tests/refs-in-captions/ref/1.png b/glossy/tests/refs-in-captions/ref/1.png
index 8b819b6..06290d9 100644
Binary files a/glossy/tests/refs-in-captions/ref/1.png and b/glossy/tests/refs-in-captions/ref/1.png differ
diff --git a/glossy/tests/refs-in-captions/test.typ b/glossy/tests/refs-in-captions/test.typ
index 7f2cc5e..bcf3ee0 100644
--- a/glossy/tests/refs-in-captions/test.typ
+++ b/glossy/tests/refs-in-captions/test.typ
@@ -2,14 +2,14 @@
// Our test glossary
#show: init-glossary.with((
- ShortInHeader: "short used in header",
- ShortInCaption: "short used in caption",
- LongInHeader: "long used in header",
- LongInCaption: "long used in caption",
- BothInHeader: "both used in header",
- BothInCaption: "both used in caption",
- NormalInHeader: "unmodified use in header",
- NormalInCaption: "unmodified use in caption",
+ ShortInHeader: "short used in header",
+ ShortInCaption: "short used in caption",
+ LongInHeader: "long used in header",
+ LongInCaption: "long used in caption",
+ BothInHeader: "both used in header",
+ BothInCaption: "both used in caption",
+ NormalInHeader: "unmodified use in header",
+ NormalInCaption: "unmodified use in caption",
))
// Configure styling
@@ -21,11 +21,11 @@
// Outlines
-#outline(title:"Table of Contents", indent: auto)
+#outline(title: "Table of Contents", indent: auto)
#outline(title: "List of Figures", target: figure.where(kind: image))
#block(
- height:7em,
- glossary(title: "List of Abbreviations", theme: theme-twocol)
+ height: 7em,
+ glossary(title: "List of Abbreviations", theme: theme-twocol),
)
#line(length: 100%)
@@ -37,7 +37,7 @@
=== `@ShortInHeader:short` = "@ShortInHeader:short"
=== `@LongInHeader:long` = "@LongInHeader:long"
-=== `@BothInHeader:both` = "@BothInHeader:both"
+=== `@BothInHeader:both:nouse` = "@BothInHeader:both:nouse"
=== `@NormalInHeader` = "@NormalInHeader"
#line(length: 100%)
@@ -47,7 +47,10 @@
#figure([], caption: [`@ShortInCaption:short` = "@ShortInCaption:short"])
#figure([], caption: [`@LongInCaption:long` = "@LongInCaption:long"])
-#figure([], caption: [`@BothInCaption:both` = "@BothInCaption:both"])
+#figure(
+ [],
+ caption: [`@BothInCaption:both:nospend` = "@BothInCaption:both:nospend"],
+)
#figure([], caption: [`@NormalInCaption` = "@NormalInCaption"])
#line(length: 100%)
diff --git a/glossy/tests/show-all/test.typ b/glossy/tests/show-all/test.typ
index 7dcc234..e7154f2 100644
--- a/glossy/tests/show-all/test.typ
+++ b/glossy/tests/show-all/test.typ
@@ -2,7 +2,7 @@
#show: init-glossary.with((
one: "this is term one",
- two: "term two also"
+ two: "term two also",
))
#set page(
@@ -19,15 +19,15 @@ shown anyway.
#glossary(
theme: theme-chicago-index,
- show-all: true
+ show-all: true,
)
#glossary(
theme: theme-compact,
- show-all: true
+ show-all: true,
)
#glossary(
theme: theme-table,
- show-all: true
+ show-all: true,
)
diff --git a/glossy/tests/sorting/test.typ b/glossy/tests/sorting/test.typ
index 6754610..b790284 100644
--- a/glossy/tests/sorting/test.typ
+++ b/glossy/tests/sorting/test.typ
@@ -22,11 +22,11 @@
tps: (
short: "TPS",
long: "test procedure specification",
- description: "A document on how to run all the test procedures"
+ description: "A document on how to run all the test procedures",
),
)
-#show: init-glossary.with(myGlossary, show-term: (body) => [#emph(body)])
+#show: init-glossary.with(myGlossary, show-term: body => [#emph(body)])
#set page(numbering: "1")
diff --git a/glossy/tests/theme-gallery/test.typ b/glossy/tests/theme-gallery/test.typ
index ce447b7..23f7155 100644
--- a/glossy/tests/theme-gallery/test.typ
+++ b/glossy/tests/theme-gallery/test.typ
@@ -8,7 +8,7 @@
),
iphone: (
short: "iPhone",
- description: "Revolutionized phones."
+ description: "Revolutionized phones.",
),
css: (
short: "CSS",
@@ -21,11 +21,11 @@
tps: (
short: "TPS",
long: "test procedure specification",
- description: "A document on how to run all the test procedures"
+ description: "A document on how to run all the test procedures",
),
)
-#show: init-glossary.with(myGlossary, show-term: (body) => [#emph(body)])
+#show: init-glossary.with(myGlossary, show-term: body => [#emph(body)])
#set page(
margin: 1cm,
@@ -35,7 +35,7 @@
#text(size: 24pt, weight: "bold")[`glossy`: theme gallery]
-#text(size: 1pt, fill: rgb(0,0,0,0))[
+#text(size: 1pt, fill: rgb(0, 0, 0, 0))[
First, we refer to each term at least once so they'll actually show up in the
glossaries. Our terms include: @atom, @iphone, @html:cap, @css, and @tps.
]
@@ -48,8 +48,8 @@
width: 100%,
spacing: 2em,
inset: 1em,
- stroke: 1pt+gray,
+ stroke: 1pt + gray,
height: if theme.first() == "theme-twocol" { 1.5in } else { auto },
- glossary(title: raw(theme.first()), theme: theme.last(), ignore-case: true)
+ glossary(title: raw(theme.first()), theme: theme.last(), ignore-case: true),
)
}
diff --git a/glossy/tests/utf-handling/test.typ b/glossy/tests/utf-handling/test.typ
index 1d0f9ef..f01b1c6 100644
--- a/glossy/tests/utf-handling/test.typ
+++ b/glossy/tests/utf-handling/test.typ
@@ -1,4 +1,4 @@
-#import "/lib.typ":*
+#import "/lib.typ": *
#set text(lang: "cs", region: "CZ")
diff --git a/glossy/themeshots.png b/glossy/themeshots.png
index 49b0f8b..9bf9497 100644
Binary files a/glossy/themeshots.png and b/glossy/themeshots.png differ
diff --git a/glossy/thumbnail.png b/glossy/thumbnail.png
index 5f43827..70c32c8 100644
Binary files a/glossy/thumbnail.png and b/glossy/thumbnail.png differ
diff --git a/glossy/typst.toml b/glossy/typst.toml
index a890c1d..e1e490e 100644
--- a/glossy/typst.toml
+++ b/glossy/typst.toml
@@ -1,7 +1,7 @@
[package]
name = "glossy"
-version = "0.8.0"
-compiler = "0.13.0"
+version = "0.9.0"
+compiler = "0.14.0"
entrypoint = "lib.typ"
authors = ["Stephen Waits "]
license = "MIT"
@@ -9,4 +9,4 @@ description = "A very simple glossary system with easily customizable output."
categories = ["model"]
keywords = ["glossary", "index", "dictionary", "gloss"]
repository = "https://github.com/swaits/typst-collection"
-exclude = ["thumbnail.png", "themeshots.png", "tests", "bin"]
+exclude = ["justfile", "thumbnail.png", "themeshots.png", "tests", "bin"]