Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38d33d3c8a
|
||
|
|
b84900ffc1
|
||
|
|
0e6d002839
|
||
|
|
7b7fd2e53f | ||
|
|
1d83997ec3
|
||
|
|
f856f34421
|
||
|
|
435136303f | ||
|
|
c1f3a757c1
|
||
|
|
b7bcb8a185
|
||
|
|
934afca4c3 | ||
|
|
5a30a0eb62
|
||
|
|
dfaf8cee93 | ||
|
|
45112b434f
|
||
|
|
8a2a2956bc
|
No files matched your search
@@ -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.
|
||||
@@ -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
|
||||
@@ -1,3 +1,54 @@
|
||||
# 🚨 REPOSITORY MOVING - DO NOT CREATE NEW ISSUES OR PRS HERE 🚨
|
||||
|
||||
<div align="center">
|
||||
|
||||
## ⛔ 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
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## 📦 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]**
|
||||
|
||||
---
|
||||
|
||||
|
||||
<details>
|
||||
<summary>📜 Original README (click to expand)</summary>
|
||||
|
||||
# `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).
|
||||
|
||||
</details>
|
||||
@@ -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).
|
||||
@@ -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: '<dir>-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"
|
||||
@@ -10,10 +10,10 @@ Pretty simple. Import `codly`. Initialize it. Import `codly-languages`.
|
||||
Configure `codly` with the languages. Like this:
|
||||
|
||||
```typst
|
||||
#import "@preview/codly:1.2.0": *
|
||||
#import "@preview/codly:1.3.0": *
|
||||
#show: codly-init
|
||||
|
||||
#import "@preview/codly-languages:0.1.8": *
|
||||
#import "@preview/codly-languages:0.1.10": *
|
||||
#codly(languages: codly-languages)
|
||||
```
|
||||
|
||||
|
||||
@@ -4,21 +4,20 @@
|
||||
// To use:
|
||||
//
|
||||
// ```typst
|
||||
// #import "@preview/codly:1.2.0": *
|
||||
// #import "@preview/codly:1.3.0": *
|
||||
// #show: codly-init
|
||||
//
|
||||
// #import "codly-languages.typ:0.1.8": *
|
||||
// #import "codly-languages.typ:0.1.10": *
|
||||
// #codly(languages: codly-languages)
|
||||
// ```
|
||||
#let codly-languages = {
|
||||
// helper function which takes an image filename and creates an icon
|
||||
let __icon(image-filename) = {
|
||||
box(
|
||||
image("icons/" + image-filename, height: 0.9em),
|
||||
baseline: 0.05em,
|
||||
image("icons/" + image-filename, height: 130%, fit: "contain"),
|
||||
inset: 0pt,
|
||||
outset: 0pt,
|
||||
) + h(0.3em)
|
||||
)
|
||||
}
|
||||
|
||||
let __emoji(emoji) = {
|
||||
@@ -26,7 +25,7 @@
|
||||
emoji,
|
||||
inset: 0pt,
|
||||
outset: 0pt,
|
||||
) + h(0.3em)
|
||||
)
|
||||
}
|
||||
|
||||
// configurations for languages
|
||||
@@ -643,9 +642,9 @@
|
||||
tsx: (name: "TSX", color: rgb("#007acc"), icon: __icon("typescript.svg")), //Devicons
|
||||
typescriptreact: (name: "React", color: rgb("#61dafb"), icon: __icon("react.svg")), //Devicons
|
||||
//Typst
|
||||
typst: (name: "Typst", color: rgb("#8b70c3"), icon: __icon("typst.svg")), //Typst
|
||||
typst: (name: "Typst", color: rgb("#458fa0"), icon: __icon("typst.svg")), //Typst
|
||||
typ: (name: "Typst", color: rgb("#458fa0"), icon: __icon("typst.svg")), //Typst
|
||||
typc: (name: "Typst", color: rgb("#8b70c3"), icon: __icon("typst.svg")), //Typst
|
||||
typc: (name: "Typst", color: rgb("#458fa0"), icon: __icon("typst.svg")), //Typst
|
||||
typm: (name: "Typst", color: rgb("#458fa0"), icon: __icon("typst.svg")), //Typst
|
||||
//UML
|
||||
uml: (name: "UML", color: rgb("#452e7f"), icon: __icon("unifiedmodelinglanguage.svg")), //Devicons
|
||||
|
||||
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 72 KiB |
@@ -1,4 +1,4 @@
|
||||
#import "@preview/codly:1.2.0": *
|
||||
#import "@preview/codly:1.3.0": *
|
||||
#import "/lib.typ": *
|
||||
#show: codly-init
|
||||
#codly(languages: codly-languages)
|
||||
|
Before Width: | Height: | Size: 254 KiB After Width: | Height: | Size: 102 KiB |
@@ -1,5 +1,5 @@
|
||||
#import "/lib.typ": *
|
||||
#import "@preview/codly:1.2.0": *
|
||||
#import "@preview/codly:1.3.0": *
|
||||
#show: codly-init
|
||||
#codly(languages: codly-languages)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "codly-languages"
|
||||
version = "0.1.8"
|
||||
version = "0.1.10"
|
||||
entrypoint = "lib.typ"
|
||||
authors = ["Stephen Waits <steve@waits.net>"]
|
||||
license = "MIT"
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
tests/**/out/
|
||||
build/
|
||||
tests/**/diff/
|
||||
tests/**/out/
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Stephen Waits <steve@waits.net>
|
||||
Copyright (c) 2025 Stephen Waits <steve@waits.net>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -41,7 +41,7 @@ different goals:
|
||||
### Import the package
|
||||
|
||||
```typst
|
||||
#import "@preview/glossy:0.7.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` <br> `: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` <br> `: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`<br>`a:`<br>`:an`<br>`an:` | Include the article (`an` is just an alias of `a`, they're equivalent) |
|
||||
| `:use` <br> `: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` <br> `: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.
|
||||
@@ -1,6 +0,0 @@
|
||||
watchexec \
|
||||
--watch . \
|
||||
--clear \
|
||||
--ignore 'tests/**/diff/**' \
|
||||
--ignore 'tests/**/out/**' \
|
||||
"typst-test r"
|
||||
@@ -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 <major|minor|patch|x.y.z>")
|
||||
|
||||
# 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
|
||||
@@ -1,2 +1,2 @@
|
||||
#import "src/gloss.typ": init-glossary, glossary
|
||||
#import "src/gloss.typ": glossary, init-glossary
|
||||
#import "src/themes.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
|
||||
}
|
||||
},
|
||||
)
|
||||
]
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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(", ")),
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -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(", "))],
|
||||
),
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -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(", ")],
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -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(", "),
|
||||
),
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -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(", "),
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -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
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -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"
|
||||
|
||||
|
Before Width: | Height: | Size: 490 KiB After Width: | Height: | Size: 104 KiB |
@@ -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)
|
||||
|
Before Width: | Height: | Size: 882 KiB After Width: | Height: | Size: 187 KiB |
@@ -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,
|
||||
)
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 + "]"
|
||||
|
||||
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 99 KiB |
@@ -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)
|
||||
]
|
||||
],
|
||||
)
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#import "/lib.typ":*
|
||||
#import "/lib.typ": *
|
||||
|
||||
#show: init-glossary.with(yaml("glossary.yml"))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 27 KiB |
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -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) }),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 275 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 502 KiB After Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 534 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 376 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 407 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 78 KiB |
@@ -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
|
||||
|
Before Width: | Height: | Size: 652 KiB After Width: | Height: | Size: 135 KiB |
@@ -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%)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#import "/lib.typ":*
|
||||
#import "/lib.typ": *
|
||||
|
||||
#set text(lang: "cs", region: "CZ")
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 650 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 906 KiB |
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "glossy"
|
||||
version = "0.7.0"
|
||||
compiler = "0.13.0"
|
||||
version = "0.9.0"
|
||||
compiler = "0.14.0"
|
||||
entrypoint = "lib.typ"
|
||||
authors = ["Stephen Waits <steve@waits.net>"]
|
||||
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"]
|
||||
@@ -4,7 +4,7 @@
|
||||
RSYNC_OPTS="--archive --delete --itemize-changes --human-readable"
|
||||
|
||||
# Set the destination base directory
|
||||
DEST_DIR="$HOME/Code/forks/typst-packages-fork/packages/preview"
|
||||
DEST_DIR="$HOME/Code/typst-packages-fork/packages/preview"
|
||||
|
||||
# Ensure the destination base directory exists
|
||||
mkdir -p "$DEST_DIR"
|
||||
|
||||