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"]