Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e4e93e096
|
||
|
|
5b0bdf333f
|
||
|
|
a903bf0fc8
|
||
|
|
ee570f7487
|
||
|
|
ef03fdfbc4
|
||
|
|
07c8fa50f9
|
||
|
|
8da80916df
|
||
|
|
588eca1c7d | ||
|
|
7f3183bd92 | ||
|
|
3e70585ffa | ||
|
|
1230057477 | ||
|
|
60a54cccf5 | ||
|
|
7ad3c5ad65
|
||
|
|
079e80edb2
|
||
|
|
4761b49867
|
||
|
|
e4c1350ebc
|
||
|
|
b0dac5f91a | ||
|
|
d0e7fe4371
|
||
|
|
0cd345a123
|
||
|
|
d296f3a3f1
|
||
|
|
338fee564f
|
||
|
|
a2f2b6e59c
|
||
|
|
a76b261348
|
||
|
|
093fcf88fd
|
||
|
|
9bb814f108
|
||
|
|
c306e56ec6 | ||
|
|
7ed699d2f7
|
||
|
|
257926d7a5
|
||
|
|
647fddbf18
|
||
|
|
93a7794c2e
|
||
|
|
40cc652aeb
|
||
|
|
600925157a
|
||
|
|
ed552faef2
|
||
|
|
5964bc082a
|
||
|
|
41e1c184e8
|
||
|
|
1e095a8b26
|
||
|
|
5d8eb4763e
|
||
|
|
5ad6c10b65
|
||
|
|
05a66f4956
|
||
|
|
df889d8d72 | ||
|
|
c008b5bd86
|
||
|
|
842166c211
|
No files matched your search
@@ -11,12 +11,19 @@ links below to their main page.
|
||||
- [**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
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
# remove-diff-out.sh
|
||||
#
|
||||
# Removes all files (including hidden) in any <pkg>/tests/<test>/diff or out directories.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# 1) Make the shell match hidden files (dotfiles) in globs.
|
||||
# 2) Let an empty glob expand to zero arguments rather than itself.
|
||||
shopt -s dotglob nullglob
|
||||
|
||||
# 2) Loop over any matching directories: <pkg>/tests/<test>/{diff,out}
|
||||
for dir in */tests/*/{diff,out}; do
|
||||
# Only proceed if it's actually a directory
|
||||
if [[ -d "$dir" ]]; then
|
||||
echo "Removing files under: $dir"
|
||||
# Remove everything inside (including hidden files)
|
||||
rm -rf -- "$dir"/*
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Done!"
|
||||
@@ -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
|
||||
|
||||
@@ -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.1.0": *
|
||||
#import "@preview/codly:1.1.1": *
|
||||
#show: codly-init
|
||||
|
||||
#import "@preview/codly-languages:0.1.3": *
|
||||
#import "@preview/codly-languages:0.1.6": *
|
||||
#codly(languages: codly-languages)
|
||||
```
|
||||
|
||||
@@ -24,78 +24,38 @@ languages, should look like this:
|
||||
|
||||
## Contributing
|
||||
|
||||
The following languages are still missing. All contributions welcome.
|
||||
|
||||
- ASP
|
||||
- ActionScript
|
||||
- Ada
|
||||
- AppleScript
|
||||
- AsciiDoc
|
||||
- Batch File
|
||||
- CFML
|
||||
- CSV
|
||||
- Cabal
|
||||
- Crontab
|
||||
- D
|
||||
- Diff
|
||||
- DotENV
|
||||
- Email
|
||||
- Fish
|
||||
- Fstab
|
||||
- GLSL
|
||||
- Graphviz
|
||||
- Groff
|
||||
- Group
|
||||
- INI
|
||||
- Jinja2
|
||||
- Jsonnet
|
||||
- Lean
|
||||
- Lisp
|
||||
- LiveScript
|
||||
- Makefile
|
||||
- MediaWiki
|
||||
- NSIS
|
||||
- Ninja
|
||||
- Org mode
|
||||
- Pascal
|
||||
- Passwd
|
||||
- Protobuf
|
||||
- Puppet
|
||||
- QML
|
||||
- Racket
|
||||
- Rego
|
||||
- Regular Expressions
|
||||
- Resolv
|
||||
- RestructuredText
|
||||
- Robot
|
||||
- SLS
|
||||
- SML
|
||||
- Slim
|
||||
- Strace
|
||||
- SublimeEthereum
|
||||
- SublimeJQ
|
||||
- SystemVerilo
|
||||
- TCL
|
||||
- TOML
|
||||
- Textile
|
||||
- TodoTxt
|
||||
- Verilog
|
||||
- WGSL
|
||||
- cmd-help
|
||||
- gnuplot
|
||||
- hosts
|
||||
- http-request-response
|
||||
- varlink
|
||||
- vscode-wgsl
|
||||
Some languages are still missing. All contributions welcome.
|
||||
|
||||
## Icon Attribution
|
||||
|
||||
The `typst-small.png` icon included in this package came from the MIT-licensed
|
||||
[codly](https://github.com/Dherse/codly) project.
|
||||
| **Icon** | **Source** | **License** |
|
||||
| ----------------- | --------------------------------------------- | -------------------------------- |
|
||||
| `css3.svg` | [CSS-Next/logo.css][css3-source] | [CC0][css3-license] |
|
||||
| `cuda.svg` | [vscode-icons/vscode-icons][cuda-source] | [MIT][cuda-license] |
|
||||
| `lisp.svg` | [Wikipedia (User:Jooja)][lisp-source] | [CC BY-SA 4.0][lisp-license] |
|
||||
| `nextflow.svg` | [nextflow-io/trademark][nextflow-source] | [Limited Use][nextflow-license] |
|
||||
| `splunk.svg` | [denali-design/denali-icons][splunk-source] | [MIT][splunk-license] |
|
||||
| `typst-small.png` | [Dherse/codly][typst-source] | [MIT][typst-license] |
|
||||
|
||||
All other icons included here came from the MIT-licensed
|
||||
[devicon](https://github.com/devicons/devicon/) project.
|
||||
[css3-source]: https://github.com/CSS-Next/logo.css/blob/main/css.svg?short_path=c59d4da
|
||||
[css3-license]: https://github.com/CSS-Next/logo.css/blob/main/LICENSE
|
||||
[cuda-source]: https://github.com/vscode-icons/vscode-icons/tree/master
|
||||
[cuda-license]: https://github.com/vscode-icons/vscode-icons/blob/master/LICENSE
|
||||
[lisp-source]: https://commons.wikimedia.org/wiki/File:Lisp_logo.svg
|
||||
[lisp-license]: https://commons.wikimedia.org/wiki/File:Lisp_logo.svg#Licensing
|
||||
[nextflow-source]: https://github.com/nextflow-io/trademark
|
||||
[nextflow-license]: https://github.com/nextflow-io/trademark/blob/master/README.md
|
||||
[splunk-source]: https://github.com/denali-design/denali-icons/blob/master/svg/splunk.svg
|
||||
[splunk-license]: https://github.com/denali-design/denali-icons/blob/master/LICENSE.md
|
||||
[typst-source]: https://github.com/Dherse/codly
|
||||
[typst-license]: https://github.com/Dherse/codly/blob/main/LICENSE
|
||||
|
||||
All icons not listed in this table come from the
|
||||
[devicons/devicon][default-source] project, [MIT licensed][default-license].
|
||||
|
||||
[default-source]: https://github.com/devicons/devicon/
|
||||
[default-license]: https://github.com/devicons/devicon/blob/master/LICENSE
|
||||
|
||||
## License
|
||||
|
||||
This package is released under the MIT License.
|
||||
This package is released under the [MIT License](LICENSE).
|
||||
@@ -1 +1,2 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><g fill="#0a094d"><path d="M114.33 75.056c.136-.547-.375-1.063-.715-.723-.418.422-.703.25-.582-.347.07-.36.035-.563-.102-.563-.36 0-.23-.527.207-.836.23-.16.801-.293 1.27-.297.469 0 .98-.09 1.133-.203.218-.152.168-.176-.22-.09-.276.063-.734.024-1.01-.082-.38-.144-.645-.12-1.075.094-.715.355-.703.36-.703-.078 0-.25-.153-.383-.485-.422l-.48-.063.41-.437c.438-.469.914-.48 2.2-.066.84.27.769.004-.133-.504-.852-.477-1.434-1.137-3.598-4.07-2.305-3.118-2.469-3.52-2.57-6.153l-.086-2.203-1.196-1.402c-.656-.77-1.28-1.454-1.386-1.52-.106-.062-.618-.168-1.137-.23-1.067-.125-1.133-.278-.547-1.27.46-.789 1.07-.879 1.953-.293.313.207.692.367.848.363.176-.007.12-.09-.14-.218-.235-.11-.423-.262-.423-.336 0-.211 2.477-.375 3.2-.207 1.5.343 1.98.87 2.234 2.445.172 1.066.285 1.281 1.058 2.008.473.449 1.344 1.047 1.934 1.328s1.414.789 1.836 1.125c.992.789 2.547 3.062 3.078 4.492.23.621.512 1.238.625 1.379.309.371-.187.625-.988.5a13.79 13.79 0 0 0-1.598-.117c-.52-.008-1.055-.106-1.191-.215-.348-.281-1.266-2.363-1.434-3.242-.293-1.563-.855-2.14-2.832-2.91-1.418-.551-1.523-.637-2.285-1.825-.7-1.09-.832-1.91-.3-1.87.546.042.398-.688-.192-.97-.403-.195-.668-.203-1.153-.042-.418.136-.886.148-1.406.03-.426-.097-.777-.132-.777-.077 0 .05.437.57.973 1.152 1.562 1.711 1.687 1.988 1.546 3.461-.082.852-.05 1.352.098 1.531.121.145.203.336.184.422-.02.09.105.477.273.863.172.383.313.828.313.985 0 .16.132.289.296.289.22 0 .258.11.16.422-.113.351-.09.386.133.199.22-.18.313-.11.512.379.133.328.324.797.422 1.043.098.242.34.484.54.535.202.05.41.324.476.613.062.285.27.688.457.89.187.204.402.552.472.774.176.551 1.024 1.117 1.805 1.207.492.059.652.164.652.442 0 .199.098.343.215.32.121-.023.32.086.45.234.124.153.316.278.425.278.11 0 0-.211-.242-.469s-.39-.523-.324-.59c.066-.062.344.149.617.477.547.648 1.176 1.054 1.36.87.066-.062-.262-.44-.723-.843-.461-.398-.774-.789-.7-.867.079-.078.352.062.61.312 1.242 1.203 2.25 1.864 2.855 1.864.285 0 .282-.035-.02-.368-.179-.199-.277-.445-.214-.55a.217.217 0 0 0-.07-.301c-.102-.063-.578-.875-1.059-1.805-.48-.93-1.031-1.773-1.227-1.879-.699-.375-.324-.492 1.458-.457l1.816.04 1.562 1.663c.86.918 1.532 1.696 1.493 1.735-.036.039-.239-.02-.45-.133-.52-.281-.57-.262-.457.172.11.418-.129.496-.468.152-.125-.12-.29-.156-.368-.078-.078.082.36.606.977 1.164.66.602 1.047 1.082.938 1.176-.247.21-4.247-.055-4.739-.32-.219-.118-.742-.211-1.164-.211-.637 0-.765.062-.765.37 0 .755-.614 1.872-1.434 2.622-.465.422-.887.77-.934.77s-.035-.2.028-.438zm.902-1.223c-.082-.25-.062-.261.082-.054.152.207.242.171.477-.192.156-.246.312-.617.347-.82.051-.32-.027-.367-.504-.313-.671.078-1.199.336-1.644.797-.403.422-.414.547-.043.547.156 0 .426.168.598.371.367.426.855.188.687-.336zm-.656-.605c.469-.39.777-.473.777-.211 0 .152-.828.601-1.09.59-.07-.004.067-.176.313-.38zm6.515-2.625c-.066-.106-.203-.188-.304-.188-.106 0-.137.082-.07.188.062.101.199.187.3.187.106 0 .137-.086.074-.187zm-.582-2.371c.512-.196.329-.45-.242-.332-.308.058-.597.015-.668-.102-.176-.281-.535-.262-.437.023.043.13.281.29.531.36.254.07.473.137.488.144.02.012.168-.03.328-.093zm-1.77-.996c0-.09-.132-.22-.296-.282-.461-.175-.523-.136-.266.168.258.313.563.375.563.114zm-2.41-2.317c-.136-.137-.222-.148-.222-.027 0 .25.223.472.348.347.054-.054-.004-.199-.125-.32zm.508-.61c-.324-.32-1.546-1.042-1.628-.956-.059.054-.07.129-.028.16.043.031.324.246.621.473.446.335 1.325.613 1.035.324zm1.34-.476c0-.226-.691-.672-1.32-.847-.422-.122-.402-.079.191.441.66.582 1.13.75 1.13.406zm-1.847-3.05c-.137-.137-.223-.149-.223-.032 0 .254.223.473.348.348.054-.05-.004-.195-.125-.317zm-1.352-.985c0-.047-.086-.137-.187-.2-.106-.062-.188-.026-.188.083 0 .11.082.2.188.2.101 0 .187-.036.187-.083zm-2.527-.77c-.387-.289-.602-.242-.395.086.067.114.266.2.442.196.277-.004.273-.04-.047-.281zm-4.242-4.976a.196.196 0 0 0-.2-.191c-.109 0-.148.085-.086.191.067.102.157.187.2.187.047 0 .086-.085.086-.187zm-3.575-.191c0-.102-.191-.184-.425-.184-.34.004-.368.039-.141.184.367.238.566.238.566 0zm10.657 15.3c-.067-.07-.125-.25-.125-.402 0-.219.054-.227.28-.04.157.13.286.31.286.4 0 .195-.262.218-.441.042zm-2.579-2.867c-.355-.3-.578-.617-.496-.703.086-.086.243-.008.348.18.102.187.39.414.64.511.25.094.458.258.458.364 0 .32-.262.222-.95-.352zm-10.66-11.93-.605-.218.476-.614c.352-.449.633-.609 1.047-.609.313 0 .532.063.493.14-.04.079-.215.458-.395.844-.176.391-.34.7-.367.692a84.463 84.463 0 0 1-.649-.235zM20.498 34.126h.922c1.03 0 1.355.164 1.675.84.422.918.422.918.68.918h.371v-2.691c-.422.16-.758.207-1.277.207h-6.29c-.695 0-.968-.047-1.324-.207v2.691h.5c.16 0 .258-.129.34-.465.242-.984.676-1.293 1.805-1.293h1.016v8.762c0 .469-.11.613-.5.68l-.16.015c-.192.031-.29.13-.29.305v.277h3.485v-.277c0-.176-.098-.274-.258-.305l-.18-.015c-.386-.051-.515-.211-.515-.68zm6.281 4.133c.39-.535 1.164-.906 1.89-.906.45 0 .872.148 1.16.437.29.274.387.563.387 1.211v3.758c0 .582-.03.645-.468.758l-.078.035c-.165.047-.227.129-.227.32v.293h3.016v-.293c0-.191-.063-.304-.207-.32l-.13-.035c-.40Line truncated
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><title>file_type_awk</title><path d="M26.925,27.737C23.431,26.1,24.606,14.588,13.81,8.319,14.089,5.792,14.758-.5,7.961,3,6.845,3.128,4.907,2.331,4,4.831v.114C16.918,3.9.088,10.53,16.75,25.844c-.373.176-.674-.325-1.97.1l-.014.016c-1.722,1.135,1.933.768,4.154,1.274-1.611.417-5.594-1.137-6.3,1.645.877-.37,1,.329,1.076,1.077A26.277,26.277,0,0,1,22.379,27.5c1.1.285,4.118,2.049,5.122.551C27.519,27.93,27.221,27.876,26.925,27.737Z"/><path d="M10.446,2.97l-.121.088a.266.266,0,0,0-.011.377.211.211,0,0,0,.045.039.416.416,0,0,0,.521-.063.263.263,0,0,0,.078-.364l-.01-.014c-.076-.143-.163-.177-.34-.127C10.553,2.925,10.5,2.946,10.446,2.97Z" style="fill:#d2d2d2"/><path d="M18,26.368c.151-.041.318-.828.174-.949A6.29,6.29,0,0,0,19.4,26.485c1.023,1.007,2.665-.032,3.482.759a10.736,10.736,0,0,0,1.957,1.027c-.139-.151-.029-.144.179-.011-.13-.338-4.421-5.156-5.226-7.18.095.293-1.608-.824-2.076-1.419-.028.056-.092-.251-.228-.434-.041.05-.2-.433-.3-.728.037.187-.462-.5-.65-.818-.056.09-.719.372-.809.286-.729-.4,2.529,4.066.122,2.559.676.683.614.4-1.095-.852.364.452-.317.312-1.553-1.523.186.2-.218-.576-.218-.576a2.692,2.692,0,0,0-.133-.483c-.056-.32-.241-.723-.12-.65-1.444-1.556,1.314-3.3.719-3.671-.111,0-.027.017-.151-.106-.09,0-.468.285-.587-.234.006.132-.034.406-.153-.1-.023.052.015.1-.03.145-.225-.576-.772-1.6-1.217-2.539-.158.155-.138-.076-.193-1.092.053.144-.225,1.921-.2.13-.128.007.108,1.258-.343.21-.141.05-.305-.363-.341-1.178-.048.623-.29.187-.5-.923-.269.508-1.6,1.743-.333,7.622-.053-.313.186.341.755,2.427.021-.039-.022-.083.038-.131a6.324,6.324,0,0,0,.677,1.365c.544.658.995,2.074.8,1.277a11.867,11.867,0,0,0,2.554,3.249A34.423,34.423,0,0,0,18,26.368Z" style="fill:#d2d2d2"/><path d="M10.823,2.557a.291.291,0,0,0-.051-.022c-.221-.04-.429.153-.654.032-.145.085-.257-.036-.375-.073a.224.224,0,0,0-.2.014,5.823,5.823,0,0,0-.814.582,1.037,1.037,0,0,0-.273.449c-.021.048-.037.126.05.137a2.3,2.3,0,0,0,.682.045c.177-.028.277-.152.418-.221a1.2,1.2,0,0,0,.592-.68c.064-.175.161-.167.28-.2S10.7,2.62,10.823,2.557Z" style="fill:#d2d2d2"/><path d="M10.325,3.058l.121-.088a.117.117,0,0,1,.12.064c.044.1.106.112.193.047.033-.025.071-.058.118-.027a.119.119,0,0,1,.041.128.276.276,0,0,1-.187.248.266.266,0,0,1-.3-.03C10.341,3.308,10.26,3.2,10.325,3.058Z"/></svg>
|
||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 2.4 KiB |
@@ -1 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><path fill="#1572B6" d="M18.814 114.123L8.76 1.352h110.48l-10.064 112.754-45.243 12.543-45.119-12.526z"/><path fill="#33A9DC" d="M64.001 117.062l36.559-10.136 8.601-96.354h-45.16v106.49z"/><path fill="#fff" d="M64.001 51.429h18.302l1.264-14.163H64.001V23.435h34.682l-.332 3.711-3.4 38.114h-30.95V51.429z"/><path fill="#EBEBEB" d="M64.083 87.349l-.061.018-15.403-4.159-.985-11.031H33.752l1.937 21.717 28.331 7.863.063-.018v-14.39z"/><path fill="#fff" d="M81.127 64.675l-1.666 18.522-15.426 4.164v14.39l28.354-7.858.208-2.337 2.406-26.881H81.127z"/><path fill="#EBEBEB" d="M64.048 23.435v13.831H30.64l-.277-3.108-.63-7.012-.331-3.711h34.646zm-.047 27.996v13.831H48.792l-.277-3.108-.631-7.012-.33-3.711h16.447z"/></svg>
|
||||
<!--from https://github.com/CSS-Next/logo.css/blob/main/css.svg?short_path=c59d4da cc0-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000" role="img" aria-labelledby="css-logo-title css-logo-description">
|
||||
<path id="bg" fill="#639" d="M0 0H840A160 160 0 0 1 1000 160V840A160 160 0 0 1 840 1000H160A160 160 0 0 1 0 840V0Z" />
|
||||
<path id="fg" fill="#fff" d="m358.1,920c-64.23-.06-103.86-36.23-103.1-102.79,0,0,0-168.39,0-168.39,0-33.74,9.88-59.4,29.64-76.96,35.49-34.19,117.83-36.27,152.59.52,21.42,18.89,29.5,57.48,27.58,93.49h-73.72c.56-14.15-.19-35.58-8.51-43.65-10.81-14.63-39.36-12.91-46.91,2.32-4.64,8.26-6.96,20.49-6.96,36.67v146.18c0,30.65,10.65,46.15,31.96,46.49,9.96,0,17.53-3.62,22.68-10.85,7.19-8.58,8.31-27.58,7.73-41.32h73.72c5.04,70.07-36.32,119.16-106.71,118.29Zm234.04,0c-71.17.98-103.01-49.66-101.04-118.29h69.59c-1.93,29.92,8.35,57.17,32.99,55.27,10.99,0,18.73-3.44,23.2-10.33,8.5-12.59,10.09-48.95-2.06-63.02-8.49-13.55-39.03-25.51-55.16-33.57-23.03-11.02-39.61-24.1-49.75-39.26-22.87-33.64-20.75-107.48,11.34-137.4,31.18-36.92,112.61-38.62,143.82-.77,19.25,19.51,27.66,57.9,26.03,93.23h-67.02c.57-14.52-.8-37.95-6.44-46.49-3.95-7.23-11.43-10.85-22.42-10.85-19.59,0-29.38,11.71-29.38,35.12.21,24.86,9.9,35.06,32.48,45.45,29.24,11.36,66.42,30.76,79.9,54.24,40.2,71.54,12.62,180.82-86.09,176.65Zm224.76,0c-71.17.98-103.01-49.66-101.04-118.29h69.59c-1.93,29.92,8.35,57.17,32.99,55.27,10.99,0,18.73-3.44,23.2-10.33,8.5-12.59,10.09-48.95-2.06-63.02-8.49-13.55-39.03-25.51-55.16-33.57-23.03-11.02-39.61-24.1-49.75-39.26-22.87-33.64-20.75-107.48,11.34-137.4,31.18-36.92,112.61-38.62,143.82-.77,19.25,19.51,27.66,57.9,26.03,93.23h-67.02c.57-14.52-.8-37.95-6.44-46.49-3.95-7.23-11.43-10.85-22.42-10.85-19.59,0-29.38,11.71-29.38,35.12.21,24.86,9.9,35.06,32.48,45.45,29.24,11.36,66.42,30.76,79.9,54.24,40.2,71.54,12.62,180.82-86.09,176.65Z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 778 B After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><title>file_type_cuda</title><path d="M12.447,12.265V10.591c.163-.012.327-.02.494-.026,4.577-.143,7.581,3.934,7.581,3.934S17.278,19,13.8,19a4.2,4.2,0,0,1-1.353-.217V13.712c1.782.215,2.14,1,3.212,2.788l2.383-2.009A6.312,6.312,0,0,0,13.37,12.21a8.606,8.606,0,0,0-.923.055m0-5.529v2.5c.164-.013.329-.024.494-.03,6.366-.214,10.513,5.221,10.513,5.221s-4.764,5.792-9.726,5.792a7.4,7.4,0,0,1-1.281-.112v1.545a8.528,8.528,0,0,0,1.067.069c4.618,0,7.958-2.358,11.192-5.15.535.43,2.731,1.474,3.182,1.932-3.075,2.574-10.241,4.649-14.3,4.649-.392,0-.769-.024-1.138-.06v2.172H30V6.736Zm0,12.051v1.32c-4.271-.762-5.457-5.2-5.457-5.2a9.234,9.234,0,0,1,5.457-2.64v1.447h-.006a4.1,4.1,0,0,0-3.184,1.456s.782,2.811,3.19,3.62M4.861,14.713a10.576,10.576,0,0,1,7.586-4.122V9.236C6.848,9.685,2,14.427,2,14.427s2.746,7.939,10.447,8.665v-1.44C6.8,20.941,4.861,14.713,4.861,14.713Z" style="fill:#80bc00"/></svg>
|
||||
|
After Width: | Height: | Size: 945 B |
@@ -1 +1,3 @@
|
||||
<svg viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"><path d="M103.555 95.851L64 80.52 24.446 95.847l15.618-24.436L0 56.447l49.208.23L63.999 32.1l14.794 24.578L128 56.453l-40.065 14.96 15.62 24.438"/><path d="M98.204 91.48l-34.17-13.244-34.168 13.242 13.491-21.11-34.61-12.926 42.506.198L64.03 36.41l12.78 21.23 42.509-.194L84.71 70.37l13.493 21.11" fill="#619cbc"/><path d="M37.804 44.66c3.413 0 1.424 8.528.21 11.1-1.04 2.201-3.38 5.377-6.153 5.377-3.327 0-3.228-3.727-1.904-6.532.717-1.52 1.82-3.222 3.338-4.474-.39 1.307.925 2.2.393 3.325-.363.769-1.114 1.609-1.504 2.436-.631 1.337-.39 3.71 1.135 3.71 1.365 0 2.578-1.692 3.075-2.745 1.019-2.158 3.566-11.366.719-11.366-3.28 0-8.93 7.99-10.113 10.497-2.112 4.474-.58 9.984 4.231 9.984 3.252 0 5.926-3.126 7.218-5.862a14.931 14.931 0 001.353-4.781l.632-.116c.139 4.21 4.592 11.18 2.697 15.196-2.427 5.14-9.681 5.094-13.824 6.918-.87-2.037-2.05-3.93-3.711-5.376 3.695-1.243 12.775-3.33 14.75-7.512.83-1.758.264-4.671-.694-5.659a10.916 10.916 0 01-.689 1.89c-1.69 3.58-5.31 6.357-9.041 6.357-5.196 0-7.398-3.733-4.953-8.913 1.467-3.109 8.96-13.455 12.835-13.455"/><path d="M37.804 44.66c3.413 0 1.424 8.528.21 11.1-1.04 2.201-3.38 5.377-6.153 5.377-3.327 0-3.228-3.727-1.904-6.532.717-1.52 1.82-3.222 3.338-4.474-.39 1.307.925 2.2.393 3.325-.363.769-1.114 1.609-1.504 2.436-.631 1.337-.39 3.71 1.135 3.71 1.365 0 2.578-1.692 3.075-2.745 1.019-2.158 3.566-11.366.719-11.366-3.28 0-8.93 7.99-10.113 10.497-2.112 4.474-.58 9.984 4.231 9.984 3.252 0 5.926-3.126 7.218-5.862a14.931 14.931 0 001.353-4.781l.632-.116c.139 4.21 4.592 11.18 2.697 15.196-2.427 5.14-9.681 5.094-13.824 6.918-.87-2.037-2.05-3.93-3.711-5.376 3.695-1.243 12.775-3.33 14.75-7.512.83-1.758.264-4.671-.694-5.659a10.916 10.916 0 01-.689 1.89c-1.69 3.58-5.31 6.357-9.041 6.357-5.196 0-7.398-3.733-4.953-8.913 1.467-3.109 8.96-13.455 12.835-13.455z" fill="none" stroke="#000" stroke-linejoin="round" stroke-miterlimit="3.864" stroke-width="5.7179996"/><path d="M46.681 57.002c.206.508.803 3.38 1.256 3.38.979 0 2.748-2.663 3.222-3.355.87.57.388 1.767 2 1.767.73 0 1.098-1.573 1.858-1.599.026.636.067 1.211-.28 1.946-.534 1.132-1.886 2.666-3.215 2.666-.953 0-2.279-1.146-2.54-1.146-.282 0-.802.132-.967.483-.693 1.467 1.158 6.363 3.014 6.363.992 0 2.175-.728 3.213-1.176-.27 1.764-.308 3.251.05 4.77a5.674 5.674 0 01-2.942.85c-4.56 0-2.045-10.605-6.25-12.865l1.58-2.084"/><path d="M46.681 57.002c.206.508.803 3.38 1.256 3.38.979 0 2.748-2.663 3.222-3.355.87.57.388 1.767 2 1.767.73 0 1.098-1.573 1.858-1.599.026.636.067 1.211-.28 1.946-.534 1.132-1.886 2.666-3.215 2.666-.953 0-2.279-1.146-2.54-1.146-.282 0-.802.132-.967.483-.693 1.467 1.158 6.363 3.014 6.363.992 0 2.175-.728 3.213-1.176-.27 1.764-.308 3.251.05 4.77a5.674 5.674 0 01-2.942.85c-4.56 0-2.045-10.605-6.25-12.865z" fill="none" stroke="#000" stroke-linejoin="round" stroke-miterlimit="3.864" stroke-width="5.7179996"/><path d="M64.209 56.154c3.447 0 4.808 6.2 3.261 9.476-1.2 2.542-3.327 4.384-6.052 4.384-4.812 0-4.21-6.56-2.332-10.538.518-1.096 2.287-3.484 3.67-3.484.51 0 .93.162 1.453.162zm-.107.579c-.542 0-1.02.268-1.27.802-.53 1.118 2.105 2.25 1.727 3.051-.238.504-1.144.976-1.601.976-2.284 0-2.265-2.972-.903-4.908-.847.539-1.402 1.363-1.762 2.127-1.338 2.835-.276 6.734 2.778 6.734 1.688 0 3.631-1.516 4.387-3.117.93-1.968-1.448-5.665-3.356-5.665" fill-rule="evenodd"/><path d="M64.209 56.154c3.447 0 4.808 6.2 3.261 9.476-1.2 2.542-3.327 4.384-6.052 4.384-4.812 0-4.21-6.56-2.332-10.538.518-1.096 2.287-3.484 3.67-3.484.51 0 .93.162 1.453.162z" fill="none" stroke="#000" stroke-linejoin="round" stroke-miterlimit="3.864" stroke-width="5.7179996"/><path d="M64.101 56.733c-.542 0-1.02.268-1.271.802-.528 1.119 2.106 2.25 1.728 3.051-.238.504-1.144.976-1.601.976-2.284 0-2.265-2.972-.903-4.908-.847.54-1.402 1.363-1.762 2.127-1.339 2.835-.277 6.735 2.778 6.735 1.687 0 3.631-1.517 4.387-3.117.93-1.968-1.448-5.666-3.356-5.666z" fill="none" stroke="#000" stroke-linejoin="round" stroke-miterlimit="3.864" stroke-width="5.7179996"/><path d="M79.875 66.36c-.901 1.908-2.58 2.955-4.47 2.955-5.997 0-7.187-5.469-4.587-10.975.613-1.3 1.62-2.737 3.159-2.737 4.818 0 8.174 5.933 5.897 10.757zM75.09 56.293c-.443 0-.83.16-1.043.61-.466.989 2.072 1.87 2.075 2.892-.265.314-1.007.665-1.33.665-1.828 0-3.208-2.478-1.647-4.32-.634.403-1.01 1.005-1.277 1.57-1.582 3.352.673 6.74 3.96 6.74 1.368 0 3.13-.76 3.841-2.266 1.006-2.13-2.576-5.89-4.58-5.89" fill-rule="evenodd"/><path d="M79.875 66.36c-.901 1.908-2.58 2.955-4.47 2.955-5.997 0-7.187-5.469-4.587-10.975.613-1.3 1.62-2.737 3.159-2.737 4.818 0 8.174 5.933 5.897 10.757z" fill="none" stroke="#000" stroke-linejoin="round" stroke-miterlimit="3.864" stroke-width="5.7179996"/><path d="M75.089 56.294c-.442 0-.83.16-1.043.61-.466.988 2.072 1.87 2.076 2.892-.265.313-1.008.665-1.331.665-1.828 0-3.208-2.478-1.647-4.32-.633.402-1.01 1.004-1.277 1.57-1.582 3.352.674 6.74 3.96 6.74 1.368 0 3.131-.76 3.842-2.266 1.005-2.13-2.576-5.89-4.58-5.89z" fill="none" stroke="#Line truncated
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-star" viewBox="0 0 16 16">
|
||||
<path d="M2.866 14.85c-.078.444.36.791.746.593l4.39-2.256 4.389 2.256c.386.198.824-.149.746-.592l-.83-4.73 3.522-3.356c.33-.314.16-.888-.282-.95l-4.898-.696L8.465.792a.513.513 0 0 0-.927 0L5.354 5.12l-4.898.696c-.441.062-.612.636-.283.95l3.523 3.356-.83 4.73zm4.905-2.767-3.686 1.894.694-3.957a.56.56 0 0 0-.163-.505L1.71 6.745l4.052-.576a.53.53 0 0 0 .393-.288L8 2.223l1.847 3.658a.53.53 0 0 0 .393.288l4.052.575-2.906 2.77a.56.56 0 0 0-.163.506l.694 3.957-3.686-1.894a.5.5 0 0 0-.461 0z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 623 B |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg version="1.1" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="256" cy="256" r="235" fill="#fff"/>
|
||||
<path stroke="#000" stroke-width="5" d="m255.56 20.008c-62.374 0.1169-122.17 24.922-166.3 68.992-92.236 92.091-92.353 241.52-0.2617 333.75 92.09 92.236 241.52 92.353 333.75 0.262 92.236-92.091 92.353-241.52 0.262-333.75-44.377-44.447-104.64-69.371-167.45-69.254zm2.281 1.0059c59.934 0.4846 119.39 23.809 164.46 68.953 91.701 91.845 91.585 240.64-0.259 332.34-45.922 45.851-120.32 45.793-166.17-0.129-45.851-45.922-45.793-120.32 0.129-166.17 46.412-46.339 46.471-121.53 0.13-167.94-37.084-37.141-94.457-46.553-140.66-21.658 42.416-31.541 92.711-45.798 142.37-45.396zm-190.84 130.26h40c9.943 42.147 25.204 79.418 40.75 116.43 15.9-41.326 33.203-81.249 55.25-116.43h40c-48.928 97.364-102.19 164.06-24 250h-40c-47.567-77.243-82.439-147.67-112-250z"/>
|
||||
<path d="m293 110.72c78.194 85.936 24.928 152.64-24 250h40c22.047-35.179 39.35-75.102 55.25-116.43 15.546 37.01 30.807 74.282 40.75 116.43h40c-29.561-102.33-64.433-172.76-112-250z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,6 @@
|
||||
<svg width="251" height="251" viewBox="0 0 251 251" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 47.0195C39.45 49.6394 71.06 81.3272 73.54 120.815H119.61C117.05 55.8589 64.93 3.64245 0 0.942627V47.0195Z" fill="#0DC09D"/>
|
||||
<path d="M73.8 131.324C71.18 170.771 39.49 202.379 0 204.859V250.926C64.96 248.366 117.18 196.249 119.88 131.324H73.8Z" fill="#0DC09D"/>
|
||||
<path d="M176.201 120.545C178.821 81.0972 210.511 49.4894 250.001 47.0095V0.942627C185.041 3.50245 132.821 55.619 130.121 120.545H176.201Z" fill="#0DC09D"/>
|
||||
<path d="M250.001 204.849C210.551 202.229 178.941 170.542 176.461 131.054H130.391C132.951 196.01 185.071 248.226 250.001 250.926V204.849Z" fill="#0DC09D"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 693 B |
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- License: MIT. Made by Denali Design: https://github.com/denali-design/denali-icons -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>splunk</title>
|
||||
<g id="Layer_2" data-name="Layer 2">
|
||||
<g id="invisible_box" data-name="invisible box">
|
||||
<rect width="48" height="48" fill="none"/>
|
||||
</g>
|
||||
<g id="Q3_icons" data-name="Q3 icons">
|
||||
<path d="M37.5,4h-27A6.5,6.5,0,0,0,4,10.5v27A6.5,6.5,0,0,0,10.5,44h27A6.5,6.5,0,0,0,44,37.5v-27A6.5,6.5,0,0,0,37.5,4ZM33.6,26.1c0,.1,0,.2-.2.3L14.7,35.8c-.1.1-.3-.1-.3-.2V30.8c0-.1,0-.2.1-.2l13.6-6.8L14.5,16.9c-.1,0-.1-.1-.1-.2V11.9c0-.1.2-.3.3-.2l18.7,9.4a.5.5,0,0,1,.2.4Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 743 B |
@@ -4,7 +4,7 @@
|
||||
// To use:
|
||||
//
|
||||
// ```typst
|
||||
// #import "@preview/codly:1.1.0": *
|
||||
// #import "@preview/codly:1.1.1": *
|
||||
// #show: codly-init
|
||||
//
|
||||
// #import "codly-languages.typ": *
|
||||
@@ -42,6 +42,8 @@
|
||||
cplusplus: (name: "C++", color: rgb("#00599c"), icon: __icon("cplusplus.svg")),
|
||||
cpp: (name: "C++", color: rgb("#00599c"), icon: __icon("cplusplus.svg")),
|
||||
cxx: (name: "C++", color: rgb("#00599c"), icon: __icon("cplusplus.svg")),
|
||||
cuda: (name: "CUDA", color: rgb("#80bc00"), icon: __icon("cuda.svg")),
|
||||
cu: (name: "CUDA", color: rgb("#80bc00"), icon: __icon("cuda.svg")),
|
||||
crystal: (name: "Crystal", color: rgb("#000000"), icon: __icon("crystal.svg")),
|
||||
csharp: (name: "C#", color: rgb("#9b4f96"), icon: __icon("csharp.svg")),
|
||||
cs: (name: "C#", color: rgb("#9b4f96"), icon: __icon("csharp.svg")),
|
||||
@@ -80,10 +82,12 @@
|
||||
kt: (name: "Kotlin", color: rgb("#5e3cc2"), icon: __icon("kotlin.svg")),
|
||||
latex: (name: "LaTeX", color: rgb("#000000"), icon: __icon("latex.svg")),
|
||||
less: (name: "Less", color: rgb("#2a4d80"), icon: __icon("less.svg")),
|
||||
lisp: (name: "Lisp", color: rgb("#3FBF3F"), icon: __icon("lisp.svg")),
|
||||
lua: (name: "Lua", color: rgb("#000080"), icon: __icon("lua.svg")),
|
||||
markdown: (name: "Markdown", color: rgb("#000000"), icon: __icon("markdown.svg")),
|
||||
matlab: (name: "Matlab", color: rgb("#4499dd"), icon: __icon("matlab.svg")),
|
||||
mysql: (name: "MySQL", color: rgb("#00618a"), icon: __icon("mysql.svg")),
|
||||
nextflow: (name: "Nextflow", color: rgb("#0dc09d"), icon: __icon("nextflow.svg")),
|
||||
neovim: (name: "Neovim", color: rgb("#517d37"), icon: __icon("neovim.svg")),
|
||||
nvim: (name: "Neovim", color: rgb("#517d37"), icon: __icon("neovim.svg")),
|
||||
nginx: (name: "Nginx", color: rgb("#009900"), icon: __icon("nginx.svg")),
|
||||
@@ -122,6 +126,8 @@
|
||||
shell: (name: "Shell", color: rgb("#293138"), icon: __icon("bash.svg")),
|
||||
solidity: (name: "Solidity", color: rgb("#000000"), icon: __icon("solidity.svg")),
|
||||
sol: (name: "Solidity", color: rgb("#000000"), icon: __icon("solidity.svg")),
|
||||
splunk: (name: "Splunk", color: rgb("#76a445"), icon: __icon("splunk.svg")),
|
||||
spl: (name: "Splunk", color: rgb("#76a445"), icon: __icon("splunk.svg")),
|
||||
sql: (name: "SQL", color: rgb("#f2f2f2"), icon: __icon("sql.svg")),
|
||||
sqlite: (name: "SQLite", color: rgb("#0b7fcc"), icon: __icon("sqlite.svg")),
|
||||
ssh-config: (name: "SSH", color: rgb("#231f20"), icon: __icon("ssh.svg")),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#import "/lib.typ": *
|
||||
#import "@preview/codly:1.1.0": *
|
||||
#import "@preview/codly:1.1.1": *
|
||||
#show: codly-init
|
||||
#codly(languages: codly-languages)
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
@@ -18,6 +18,7 @@
|
||||
"crystal",
|
||||
"csharp",
|
||||
"css",
|
||||
"cuda",
|
||||
"dart",
|
||||
"docker",
|
||||
"elixir",
|
||||
@@ -42,11 +43,13 @@
|
||||
"kotlin",
|
||||
"latex",
|
||||
"less",
|
||||
"lisp",
|
||||
"lua",
|
||||
"markdown",
|
||||
"matlab",
|
||||
"mysql",
|
||||
"neovim",
|
||||
"nextflow",
|
||||
"nginx",
|
||||
"nim",
|
||||
"nix",
|
||||
@@ -67,6 +70,7 @@
|
||||
"sass",
|
||||
"scala",
|
||||
"solidity",
|
||||
"splunk",
|
||||
"sql",
|
||||
"sqlite",
|
||||
"ssh-config",
|
||||
@@ -107,6 +111,7 @@ Found all base languages!
|
||||
"cpp",
|
||||
"cs",
|
||||
"cxx",
|
||||
"cu",
|
||||
"dockerfile",
|
||||
"erl",
|
||||
"ex",
|
||||
@@ -132,6 +137,7 @@ Found all base languages!
|
||||
"sh",
|
||||
"shell",
|
||||
"sol",
|
||||
"spl",
|
||||
"ssh",
|
||||
"styl",
|
||||
"tf",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "codly-languages"
|
||||
version = "0.1.3"
|
||||
version = "0.1.6"
|
||||
entrypoint = "lib.typ"
|
||||
authors = ["Stephen Waits <steve@waits.net>"]
|
||||
license = "MIT"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
tests/**/out/
|
||||
tests/**/diff/
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
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
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,65 @@
|
||||
# Easy Typography for Typst
|
||||
|
||||
A Typst package that simplifies professional typography by providing sensible
|
||||
defaults and easy customization options. Focus on your content while ensuring
|
||||
beautiful, readable documents.
|
||||
|
||||
## Features
|
||||
|
||||
- 🎨 Precise heading scale with clear hierarchy
|
||||
- 📏 Optimal line height and paragraph spacing
|
||||
- 📖 Professional text justification and hyphenation
|
||||
- ⚖️ Balanced vertical rhythm throughout
|
||||
- ⚡ Simple configuration with reasonable defaults
|
||||
|
||||
## Usage
|
||||
|
||||
Basic usage with default settings:
|
||||
|
||||
```typst
|
||||
#import "@preview/easy-typography:0.1.0": *
|
||||
#show: easy-typography
|
||||
|
||||
= Your Document Title
|
||||
Your content here...
|
||||
```
|
||||
|
||||
Customized usage with specific fonts:
|
||||
|
||||
```typst
|
||||
#show: easy-typography.with(
|
||||
fonts: (
|
||||
heading: "Source Sans Pro",
|
||||
body: "Source Serif Pro"
|
||||
),
|
||||
body-size: 11pt,
|
||||
paper: "a4",
|
||||
margin: 2cm
|
||||
)
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
- `body-size`: Base size for body text (default: 10pt)
|
||||
- `fonts`: Dictionary specifying heading and body fonts
|
||||
- `heading`: Font for headings (default: "Libertinus Sans")
|
||||
- `body`: Font for body text (default: "Libertinus Serif")
|
||||
- `paper`: Paper size setting (optional)
|
||||
- `margin`: Page margin setting (optional)
|
||||
|
||||
## Example Output
|
||||
|
||||
The package automatically handles:
|
||||
|
||||
- Heading sizes with natural visual hierarchy (H1-H5)
|
||||
- Optimal spacing between elements
|
||||
- Professional text justification
|
||||
- Smart hyphenation
|
||||
- Consistent vertical rhythm
|
||||
|
||||
See the [example output](thumbnail.png) for more information and a complete
|
||||
example.
|
||||
|
||||
## License
|
||||
|
||||
MIT License - See [LICENSE](LICENSE) for details.
|
||||
@@ -0,0 +1 @@
|
||||
#import "src/main.typ": easy-typography
|
||||
@@ -0,0 +1,29 @@
|
||||
// Constants
|
||||
|
||||
// space above H1
|
||||
#let heading-above-max = 1.25em
|
||||
|
||||
// space above H5
|
||||
#let heading-above-min = 0.80em
|
||||
|
||||
// space below H1
|
||||
#let heading-below-max = 0.65em
|
||||
|
||||
// space below H5
|
||||
#let heading-below-min = 0.55em
|
||||
|
||||
// font size for H1
|
||||
#let heading-size-max = 1.10em
|
||||
|
||||
// font size for H5
|
||||
#let heading-size-min = 1.00em
|
||||
|
||||
// default text weight -- light is best for reading, and printers are fine with
|
||||
// it these days
|
||||
#let body-weight = "light"
|
||||
|
||||
// line spacing -- tight; efficient but still readable with good fonts
|
||||
#let line-spacing = 1.30
|
||||
|
||||
// paragraph spacing -- defaults to a double-space
|
||||
#let paragraph-spacing = 1.70
|
||||
@@ -0,0 +1,102 @@
|
||||
#import "constants.typ": *
|
||||
|
||||
/// The main function for easy typography setup.
|
||||
///
|
||||
/// - body-size (): The size of body text (default 10pt).
|
||||
/// - fonts (): A dictionary specifying heading/body fonts.
|
||||
/// - paper (str): The paper size to use (none to skip).
|
||||
/// - margin (): Margin for the page (none to skip).
|
||||
/// -> content
|
||||
#let easy-typography(
|
||||
body-size: 10pt,
|
||||
fonts: (heading: "Libertinus Sans", body: "Libertinus Serif"),
|
||||
paper: none,
|
||||
margin: none,
|
||||
body
|
||||
) = {
|
||||
// Optional page setup
|
||||
if paper != none {
|
||||
set page(paper: paper)
|
||||
}
|
||||
if margin != none {
|
||||
set page(margin: margin)
|
||||
}
|
||||
|
||||
// Paragraphs
|
||||
set par(
|
||||
leading: line-spacing * 0.5em,
|
||||
spacing: paragraph-spacing * 0.5em,
|
||||
justify: true,
|
||||
linebreaks: "optimized",
|
||||
)
|
||||
|
||||
// Body text
|
||||
set text(
|
||||
font: fonts.body,
|
||||
fallback: false,
|
||||
style: "normal",
|
||||
weight: body-weight,
|
||||
stretch: 100%,
|
||||
size: body-size,
|
||||
tracking: 0pt,
|
||||
spacing: 100% + 0pt,
|
||||
baseline: 0pt,
|
||||
overhang: true,
|
||||
hyphenate: true,
|
||||
kerning: true,
|
||||
ligatures: true,
|
||||
number-width: "proportional",
|
||||
// number-type: "lining", // commented: intentionally left up to the font to choose
|
||||
)
|
||||
|
||||
show table: set text(number-width: "tabular")
|
||||
|
||||
/// Top-heavy easing function for heading sizes/spacing.
|
||||
///
|
||||
/// `sqrt(t)` gives biggest decrease at top, gentlest at bottom.
|
||||
///
|
||||
/// - max (length): Biggest size (H1)
|
||||
/// - min (length): Smallest size (H5)
|
||||
/// - level (length): From 1 to 5
|
||||
/// -> length
|
||||
let compute-size(max, min, level) = {
|
||||
if level <= 1 {
|
||||
max
|
||||
} else if level >= 5 {
|
||||
min
|
||||
} else {
|
||||
let t = (level - 1) / 4
|
||||
max - (max - min) * calc.sqrt(t)
|
||||
}
|
||||
}
|
||||
|
||||
// Heading weight logic
|
||||
let compute-weight(level) = {
|
||||
if level <= 1 {
|
||||
"bold"
|
||||
} else if level == 2 {
|
||||
"semibold"
|
||||
} else if level == 3 {
|
||||
"medium"
|
||||
} else {
|
||||
"regular"
|
||||
}
|
||||
}
|
||||
|
||||
// Show headings using computed size/spacing values
|
||||
show heading: it => block(
|
||||
breakable: false,
|
||||
sticky: true,
|
||||
above: compute-size(heading-above-max, heading-above-min, it.level),
|
||||
below: compute-size(heading-below-max, heading-below-min, it.level),
|
||||
text(
|
||||
font: fonts.heading,
|
||||
size: compute-size(heading-size-max, heading-size-min, it.level),
|
||||
weight: compute-weight(it.level),
|
||||
it
|
||||
)
|
||||
)
|
||||
|
||||
// Finally, render the body
|
||||
body
|
||||
}
|
||||
|
After Width: | Height: | Size: 769 KiB |
@@ -0,0 +1,125 @@
|
||||
#import "/lib.typ": *
|
||||
|
||||
#import "@preview/codly:1.2.0": *
|
||||
#import "@preview/codly-languages:0.1.1": *
|
||||
#show: codly-init.with()
|
||||
#codly(languages: codly-languages)
|
||||
|
||||
#show: easy-typography.with(
|
||||
fonts: (heading: "Source Sans 3", body: "Source Serif 4"),
|
||||
)
|
||||
|
||||
= Introducing Easy Typography
|
||||
|
||||
#set heading(numbering: (..nums) => {
|
||||
numbering("1.1.", ..nums.pos().slice(1))
|
||||
})
|
||||
|
||||
The `easy-typography` package transforms complex typographic decisions into
|
||||
simple choices, letting you focus on your content while ensuring professional
|
||||
results. By adjusting the settings to match your specific needs, you can refine
|
||||
the aesthetic or adapt your layout for everything from casual reading to formal
|
||||
publication.
|
||||
|
||||
== Core Typography Features
|
||||
|
||||
The package manages:
|
||||
|
||||
#columns(2)[
|
||||
- Precise heading scale with a clear hierarchy
|
||||
- Optimal line height and paragraph spacing
|
||||
#colbreak()
|
||||
- Professional text justification and hyphenation
|
||||
- Balanced vertical rhythm throughout
|
||||
]
|
||||
|
||||
These features ensure that your document is both visually appealing and easy to
|
||||
read.
|
||||
|
||||
=== Type Formatting
|
||||
|
||||
This package automatically adjusts line spacing, paragraph spacing, and
|
||||
justification to maintain a clean layout. Headings are also carefully weighted
|
||||
to balance them against the body text, so you can focus on content rather than
|
||||
tweaking spacing and sizing. Standard formatting like *bold* and _italic_
|
||||
integrates seamlessly with `easy-typography`'s approach.
|
||||
|
||||
=== Heading Levels
|
||||
|
||||
The heading scale gracefully steps down, ensuring that each level remains
|
||||
distinct yet consistent. Behind the scenes, `easy-typography` calculates the
|
||||
ideal size for each heading, preserving a cohesive visual hierarchy as your
|
||||
document gets deeper. This approach supports manuals, academic papers, and any
|
||||
long-form text where structure matters. It also helps in shorter documents,
|
||||
guaranteeing a crisp layout with minimal effort.
|
||||
|
||||
== Why Typography Matters
|
||||
|
||||
Good typography isn't just about aesthetics. It's about effective communication.
|
||||
Well-designed text:
|
||||
|
||||
#columns(2)[
|
||||
- Improves reading comprehension
|
||||
- Reduces eye strain
|
||||
- Maintains reader engagement
|
||||
#colbreak()
|
||||
- Establishes visual hierarchy
|
||||
- Conveys professionalism
|
||||
]
|
||||
|
||||
Notice how this document's typography enhances readability. The justified text,
|
||||
proper hyphenation, and optimized line breaks create a clean, professional
|
||||
appearance. With each heading level, the user can quickly scan and digest
|
||||
important information.
|
||||
|
||||
== Example Usage and Output
|
||||
|
||||
#set heading(numbering: none)
|
||||
#show raw.where(block: true): set text(size: 7pt)
|
||||
|
||||
#grid(
|
||||
columns: (55%, auto),
|
||||
gutter: 1.0em,
|
||||
[
|
||||
// code
|
||||
```typst
|
||||
#import "@preview/easy-typography:0.1.0": *
|
||||
#show: easy-typography.with(
|
||||
fonts: (
|
||||
heading: "Source Sans Pro",
|
||||
body: "Source Serif Pro"
|
||||
),
|
||||
)
|
||||
|
||||
#lorem(6)
|
||||
= Level One
|
||||
#lorem(6)
|
||||
== Level Two
|
||||
#lorem(6)
|
||||
=== Level Three
|
||||
#lorem(6)
|
||||
==== Level Four
|
||||
#lorem(6)
|
||||
===== Level Five
|
||||
#lorem(6)
|
||||
```
|
||||
],
|
||||
box(
|
||||
stroke: 0.5pt + silver,
|
||||
inset: 0.5em,
|
||||
radius: 0.2em,
|
||||
[
|
||||
#lorem(6)
|
||||
= Level One
|
||||
#lorem(6)
|
||||
== Level Two
|
||||
#lorem(6)
|
||||
=== Level Three
|
||||
#lorem(6)
|
||||
==== Level Four
|
||||
#lorem(6)
|
||||
===== Level Five
|
||||
#lorem(6)
|
||||
]
|
||||
) // box
|
||||
)
|
||||
|
After Width: | Height: | Size: 306 KiB |
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "easy-typography"
|
||||
version = "0.1.0"
|
||||
entrypoint = "lib.typ"
|
||||
authors = ["Stephen Waits <steve@waits.net>"]
|
||||
license = "MIT"
|
||||
description = "Sets up sensible typography defaults."
|
||||
keywords = ["easy", "typography", "defaults"]
|
||||
repository = "https://github.com/swaits/typst-collection"
|
||||
exclude = ["thumbnail.png", "tests"]
|
||||
@@ -41,7 +41,7 @@ different goals:
|
||||
### Import the package
|
||||
|
||||
```typst
|
||||
#import "@preview/glossy:0.5.0": *
|
||||
#import "@preview/glossy:0.6.0": *
|
||||
```
|
||||
|
||||
### Defining Glossary Terms
|
||||
@@ -143,6 +143,7 @@ Available modifiers:
|
||||
- **short**: Shows only short form
|
||||
- **long**: Shows only long form
|
||||
- **def** or **desc**: Shows the description
|
||||
- **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)
|
||||
|
||||
@@ -160,6 +161,9 @@ Modifiers can be combined with colons:
|
||||
| `@tps:short:pl` | "TPSes" |
|
||||
| `@tps:both:pl:cap` | "Technical procedure specifications (TPSes)" |
|
||||
| `@tps:def` | "A formal document describing test steps and expected results" |
|
||||
| `@tps:desc` | _same as above, `desc` is an alias for `def`_ |
|
||||
| `@tps:noref` | _works as normal, just won't show up in glossary_ |
|
||||
| `@tps:noindex` | _same as above, `noindex` is an alias for `noref`_ |
|
||||
|
||||
The `a`/`an` modifier is special because it can either precede or follow the
|
||||
term's key.
|
||||
@@ -180,14 +184,27 @@ For example:
|
||||
Note that the `a`/`an` (article) modifier cannot be combined with the `pl`
|
||||
(plural) modifier.
|
||||
|
||||
### First use logic
|
||||
|
||||
Any use of the `short`, `long`, or `both` modifier will not count against the
|
||||
term's first use.
|
||||
|
||||
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
|
||||
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".
|
||||
|
||||
### Generating the Glossary
|
||||
|
||||
Display the glossary using the `glossary()` function:
|
||||
|
||||
```typst
|
||||
#glossary(
|
||||
title: "Web Development Glossary", // Optional: defaults to Glossary
|
||||
theme: my-theme, // Optionaal: defaults to theme-twocol
|
||||
title: "Web Development Glossary", // Optional: defaults to Glossary theme:
|
||||
my-theme, // Optional: defaults to theme-academic
|
||||
sort: true, // Optional: whether or not to sort the glossary
|
||||
ignore-case: false, // Optional: ignore case when sorting terms
|
||||
groups: ("Web") // Optional: Filter to specific groups
|
||||
)
|
||||
@@ -252,7 +269,7 @@ Customize glossary appearance by defining a theme with three functions:
|
||||
// Individual glossary entry
|
||||
entry: (entry, index, total) => {
|
||||
// index = entry index, total = total entries in group
|
||||
let output = [#entry.short]
|
||||
let output = [#entry.short#entry.label] // **NOTE:** Label here!
|
||||
if entry.long != none {
|
||||
output = [#output -- #entry.long]
|
||||
}
|
||||
@@ -279,6 +296,9 @@ Entry fields available to themes:
|
||||
- `label`: Term's dictionary label
|
||||
- `pages`: Linked page numbers where term appears
|
||||
|
||||
**NOTE:** If the theme does not emit `entry.label`, linking form terms to their
|
||||
glossary entry will not work.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License.
|
||||
@@ -0,0 +1,6 @@
|
||||
watchexec \
|
||||
--watch . \
|
||||
--clear \
|
||||
--ignore 'tests/**/diff/**' \
|
||||
--ignore 'tests/**/out/**' \
|
||||
"typst-test r"
|
||||
@@ -7,6 +7,7 @@
|
||||
#let __gloss_entries = state("__gloss_entries", (:))
|
||||
|
||||
#let __gloss_label_prefix = "__gloss:"
|
||||
#let __gloss_first_use_counter_postfix = ":first-use-count"
|
||||
|
||||
// Normalizes a dictionary entry by ensuring all required and optional keys exist
|
||||
// with appropriate default values.
|
||||
@@ -129,11 +130,14 @@
|
||||
// Returns:
|
||||
// none: Updates state as a side effect
|
||||
//
|
||||
#let __mark_term_used(key) = {
|
||||
#let __mark_term_used(key, count-as-first-use) = {
|
||||
counter(__gloss_label_prefix + key).step()
|
||||
if count-as-first-use {
|
||||
counter(__gloss_label_prefix + key + __gloss_first_use_counter_postfix).step()
|
||||
}
|
||||
}
|
||||
|
||||
// Queries the term usage
|
||||
// Queries whether the term is used ANYWHERE
|
||||
//
|
||||
// Parameters:
|
||||
// key (string): The glossary entry key
|
||||
@@ -142,12 +146,29 @@
|
||||
// Returns:
|
||||
// boolean: If the entry is used above the location in the document
|
||||
//
|
||||
#let __is_term_used(key, location: none) = {
|
||||
#let __is_term_ever_used(key, location: none) = {
|
||||
let c = counter(__gloss_label_prefix + key)
|
||||
c = if location == none {c.final()} else {c.at(location)}
|
||||
c.at(0) > 0
|
||||
}
|
||||
|
||||
// Queries whether the term has been "first used"
|
||||
//
|
||||
// "First used" is used to determine how to display the term, either "long
|
||||
// (short)" or just "(short)"
|
||||
//
|
||||
// Parameters:
|
||||
// key (string): The glossary entry key
|
||||
// location (location): The location in the document. Use none for end of document
|
||||
//
|
||||
// Returns:
|
||||
// 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)}
|
||||
c.at(0) > 0
|
||||
}
|
||||
|
||||
// Determine if the glossary contains a visible entry
|
||||
//
|
||||
@@ -216,8 +237,12 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
// Manage term usage counting and determine if it's the first reference
|
||||
// ---------------------------------------------------------------------------
|
||||
let is_first_use = not __is_term_used(key, location: here())
|
||||
__mark_term_used(key)
|
||||
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)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helper Functions
|
||||
@@ -342,15 +367,20 @@
|
||||
} else {
|
||||
term
|
||||
}
|
||||
[#article#show-term(linked-term)#metadata(term)#__term_label(key)]
|
||||
// |^^^^^^^|^^^^^^^^^ |^^^^^^^^ |^^^^^^^^^^^^
|
||||
// \_art. | | |
|
||||
let term-label = if wants_reference {
|
||||
__term_label(key)
|
||||
} else {
|
||||
[]
|
||||
}
|
||||
[#article#show-term(linked-term)#metadata(term)#term-label]
|
||||
// |^^^^^^^|^^^^^^^^^ |^^^^^^^^ |^^^^^^^^^^^^
|
||||
// \_art. | | |
|
||||
// \_ apply user formatting function to the term
|
||||
// | |
|
||||
// \_ metadata lets us label (ie it's "labelable")
|
||||
// |
|
||||
// \_ i.e. <__gloss:key>, etc.
|
||||
// for backlink from glossary
|
||||
// | |
|
||||
// \_ metadata lets us label (ie makes it "labelable")
|
||||
// |
|
||||
// \_ i.e. <__gloss:key>, etc.
|
||||
// for backlink from glossary
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,6 +571,7 @@
|
||||
#let glossary(
|
||||
title: "Glossary",
|
||||
theme: theme-academic,
|
||||
sort: true,
|
||||
ignore-case: false,
|
||||
groups: (),
|
||||
) = context {
|
||||
@@ -553,7 +584,7 @@
|
||||
// Collect and organize entries by group
|
||||
let output = (:)
|
||||
let all_entries = __gloss_entries.final()
|
||||
let all_used = all_entries.keys().filter(key => __is_term_used(key))
|
||||
let all_used = all_entries.keys().filter(key => __is_term_ever_used(key))
|
||||
|
||||
// Determine which groups to process
|
||||
let all_groups = all_entries
|
||||
@@ -601,13 +632,17 @@
|
||||
group = if group == none { "" } else { group }
|
||||
|
||||
// sort entries by case insensitivity if requested
|
||||
let sorted_entries = 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) } })
|
||||
// 2. sort the tuples (by first element then second)
|
||||
.sorted(key: t => t.first())
|
||||
// 3. strip away the tuple's first element, leaving an array of entries
|
||||
.map(t => t.last())
|
||||
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) } })
|
||||
// 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
|
||||
.map(t => t.last())
|
||||
} else {
|
||||
current_entries
|
||||
}
|
||||
|
||||
// add entries to this group's output map
|
||||
output.insert(group, sorted_entries)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Inspired by academic textbook glossaries
|
||||
#let theme-academic = (
|
||||
section: (title, body) => {
|
||||
set text(font: "New Computer Modern")
|
||||
heading(level: 1, title)
|
||||
v(1em)
|
||||
body
|
||||
@@ -40,7 +39,7 @@
|
||||
grid(
|
||||
columns: (1fr, auto),
|
||||
gutter: 0.75em,
|
||||
[#short-display#long-display#description],
|
||||
[#short-display#long-display#description#entry.label],
|
||||
text(fill: rgb("#666666"), entry.pages)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
grid(
|
||||
columns: (1fr, auto),
|
||||
gutter: 1em,
|
||||
[#short-display#entry.label#long-display#description],
|
||||
[#short-display#entry.label#long-display#description#entry.label],
|
||||
[#entry.pages]
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,6 +27,6 @@
|
||||
},
|
||||
|
||||
entry: (entry, index, total) => {
|
||||
(entry.short, entry.long, entry.description, entry.pages)
|
||||
(entry.short + entry.label, entry.long, entry.description, entry.pages)
|
||||
}
|
||||
)
|
||||
@@ -203,7 +203,7 @@
|
||||
|
||||
if is_acronym {
|
||||
// Use acronym rules
|
||||
let first_char = upper_word.slice(0,1)
|
||||
let first_char = upper_word.codepoints().slice(0,1).first()
|
||||
if acronym_vowels.contains(first_char) {
|
||||
"an"
|
||||
} else {
|
||||
@@ -211,7 +211,7 @@
|
||||
}
|
||||
} else {
|
||||
// Non-acronym rules
|
||||
let first_char = lower_word.slice(0,1)
|
||||
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 = (
|
||||
|
||||
|
Before Width: | Height: | Size: 481 KiB After Width: | Height: | Size: 489 KiB |
|
Before Width: | Height: | Size: 843 KiB After Width: | Height: | Size: 884 KiB |
@@ -47,6 +47,8 @@ Now make sure I get @tps:a:SHORT report by 2pm! @an:tps:cap is very important!!!
|
||||
[`@tps:both:pl:cap`], [@tps:both:pl:cap],
|
||||
[`@tps:def` ], [@tps:def],
|
||||
[`@tps:desc` ], [@tps:desc],
|
||||
[`@tps:noref` ], [@tps:noref *(not listed in glossary)*],
|
||||
[`@tps:noindex` ], [@tps:noindex *(not listed in glossary)*],
|
||||
)
|
||||
|
||||
== Adding articles via `a`/`an` modifiers
|
||||
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 2.5 MiB After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 98 KiB |
@@ -0,0 +1,45 @@
|
||||
#import "/lib.typ": *
|
||||
#import "@preview/glossarium:0.5.1": *
|
||||
|
||||
#set page(height: auto, width: 4.5in)
|
||||
#show link: set text(fill: red)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
= `glossy`:
|
||||
|
||||
#box(
|
||||
stroke: 1pt,
|
||||
inset: 1em,
|
||||
[
|
||||
#show: init-glossary.with((WWW: "World Wide Web"))
|
||||
|
||||
This should be a link: @WWW
|
||||
|
||||
This should be a link, too: @WWW
|
||||
|
||||
#glossary()
|
||||
]
|
||||
)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
= `glossarium`:
|
||||
|
||||
#box(
|
||||
stroke: 1pt,
|
||||
inset: 1em,
|
||||
[
|
||||
#show: make-glossary
|
||||
#let entry-list = (
|
||||
(key: "ML", short: "ML", long: "Machine Learning"),
|
||||
)
|
||||
#register-glossary(entry-list)
|
||||
|
||||
This should be a link: @ML
|
||||
|
||||
This should be a link, too: @ML
|
||||
|
||||
#print-glossary(entry-list)
|
||||
]
|
||||
)
|
||||
|
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 195 KiB |
|
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 139 KiB |
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 78 KiB |
@@ -0,0 +1,23 @@
|
||||
first:
|
||||
short: "DAL"
|
||||
long: "first"
|
||||
|
||||
second:
|
||||
short: "cab"
|
||||
long: "second"
|
||||
|
||||
third:
|
||||
short: "delta"
|
||||
long: "third"
|
||||
|
||||
fourth:
|
||||
short: "COO"
|
||||
long: "fourth"
|
||||
|
||||
fifth:
|
||||
short: "cuckoo"
|
||||
long: "fifth"
|
||||
|
||||
sixth:
|
||||
short: "ČR"
|
||||
long: "sixth"
|
||||
|
After Width: | Height: | Size: 179 KiB |
@@ -0,0 +1,13 @@
|
||||
#import "/lib.typ":*
|
||||
|
||||
#show: init-glossary.with(yaml("glossary.yml"))
|
||||
|
||||
@first, @second, @third, @fourth, @fifth, @sixth
|
||||
|
||||
#glossary(ignore-case: false, sort: true)
|
||||
#line(length: 20em)
|
||||
#glossary(ignore-case: true, sort: true)
|
||||
#line(length: 20em)
|
||||
#glossary(ignore-case: false, sort: false)
|
||||
#line(length: 20em)
|
||||
#glossary(ignore-case: true, sort: false)
|
||||
|
After Width: | Height: | Size: 55 KiB |
@@ -0,0 +1,26 @@
|
||||
#import "/lib.typ": *
|
||||
|
||||
// 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",
|
||||
))
|
||||
|
||||
// Configure styling
|
||||
|
||||
#set page(margin: 1em)
|
||||
#set page(width: 3.5in)
|
||||
#set page(height: auto)
|
||||
#set text(size: 10pt)
|
||||
|
||||
@Normal
|
||||
|
||||
@NoRef:noref
|
||||
|
||||
@NoIndex:noindex
|
||||
|
||||
@NoRefNoIndex:noref:noindex
|
||||
|
||||
#glossary()
|
||||
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 133 KiB After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 674 KiB |
@@ -0,0 +1,82 @@
|
||||
#import "/lib.typ": *
|
||||
|
||||
// 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",
|
||||
))
|
||||
|
||||
// Configure styling
|
||||
|
||||
#set page(numbering: "1")
|
||||
#set page(margin: 0.5in)
|
||||
#set page(height: auto)
|
||||
#set text(size: 10pt)
|
||||
|
||||
// Outlines
|
||||
|
||||
#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)
|
||||
)
|
||||
|
||||
#line(length: 100%)
|
||||
|
||||
// Doc Body
|
||||
|
||||
// Use all the terms in headings
|
||||
#heading(level: 1, outlined: false, [Use terms in HEADERS])
|
||||
|
||||
=== `@ShortInHeader:short` = "@ShortInHeader:short"
|
||||
=== `@LongInHeader:long` = "@LongInHeader:long"
|
||||
=== `@BothInHeader:both` = "@BothInHeader:both"
|
||||
=== `@NormalInHeader` = "@NormalInHeader"
|
||||
|
||||
#line(length: 100%)
|
||||
|
||||
// Use all the terms in captions
|
||||
#heading(level: 1, outlined: false, [Use terms in CAPTIONS])
|
||||
|
||||
#figure([], caption: [`@ShortInCaption:short` = "@ShortInCaption:short"])
|
||||
#figure([], caption: [`@LongInCaption:long` = "@LongInCaption:long"])
|
||||
#figure([], caption: [`@BothInCaption:both` = "@BothInCaption:both"])
|
||||
#figure([], caption: [`@NormalInCaption` = "@NormalInCaption"])
|
||||
|
||||
#line(length: 100%)
|
||||
|
||||
// Now use the terms in the body to see if they handle "first use" correctly
|
||||
#heading(level: 1, outlined: false, [Use terms in BODY])
|
||||
|
||||
First `@ShortInHeader` = "@ShortInHeader".
|
||||
Second `@ShortInHeader` = "@ShortInHeader"
|
||||
|
||||
First `@LongInHeader` = "@LongInHeader".
|
||||
Second `@LongInHeader` = "@LongInHeader".
|
||||
|
||||
First `@BothInHeader` = "@BothInHeader".
|
||||
Second `@BothInHeader` = "@BothInHeader".
|
||||
|
||||
First `@NormalInHeader` = "@NormalInHeader".
|
||||
Second `@NormalInHeader` = "@NormalInHeader".
|
||||
|
||||
#v(0.5em)
|
||||
|
||||
First `@ShortInCaption` = "@ShortInCaption".
|
||||
Second `@ShortInCaption` = "@ShortInCaption"
|
||||
|
||||
First `@LongInCaption` = "@LongInCaption".
|
||||
Second `@LongInCaption` = "@LongInCaption".
|
||||
|
||||
First `@BothInCaption` = "@BothInCaption".
|
||||
Second `@BothInCaption` = "@BothInCaption".
|
||||
|
||||
First `@NormalInCaption` = "@NormalInCaption".
|
||||
Second `@NormalInCaption` = "@NormalInCaption".
|
||||
|
Before Width: | Height: | Size: 259 KiB After Width: | Height: | Size: 259 KiB |
|
Before Width: | Height: | Size: 651 KiB After Width: | Height: | Size: 651 KiB |
@@ -0,0 +1,23 @@
|
||||
cab:
|
||||
short: "cab"
|
||||
long: "taxi cab"
|
||||
|
||||
coo:
|
||||
short: "COO"
|
||||
long: "Chief Operations Officer"
|
||||
|
||||
cuckoo:
|
||||
short: "cuckoo"
|
||||
long: "really crazy"
|
||||
|
||||
delta:
|
||||
short: "delta"
|
||||
long: "difference between two values"
|
||||
|
||||
dal:
|
||||
short: "DAL"
|
||||
long: "Delta Airlines"
|
||||
|
||||
čr:
|
||||
short: "ČR"
|
||||
long: "Česká Republika"
|
||||
|
After Width: | Height: | Size: 133 KiB |
@@ -0,0 +1,20 @@
|
||||
#import "/lib.typ":*
|
||||
|
||||
#set text(lang: "cs", region: "CZ")
|
||||
|
||||
#show: init-glossary.with(yaml("glossary.yml"))
|
||||
#glossary(ignore-case: true, theme: theme-twocol)
|
||||
|
||||
#line(length: 20em)
|
||||
|
||||
@čr
|
||||
|
||||
@cab
|
||||
|
||||
@coo
|
||||
|
||||
@cuckoo
|
||||
|
||||
@delta
|
||||
|
||||
@dal
|
||||
|
Before Width: | Height: | Size: 651 KiB After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 332 KiB After Width: | Height: | Size: 117 KiB |
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "glossy"
|
||||
version = "0.5.0"
|
||||
version = "0.6.0"
|
||||
entrypoint = "lib.typ"
|
||||
authors = ["Stephen Waits <steve@waits.net>"]
|
||||
license = "MIT"
|
||||
@@ -8,4 +8,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.pjng", "tests"]
|
||||
exclude = ["thumbnail.png", "themeshots.pjng", "tests", "bin"]
|
||||
@@ -0,0 +1,2 @@
|
||||
tests/**/out/
|
||||
tests/**/diff/
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
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
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,62 @@
|
||||
# run-liners
|
||||
|
||||
A Typst package for creating run-in lists, enumerations, and more following Chicago Manual of Style guidelines.
|
||||
|
||||
## Features
|
||||
|
||||
- **Run-in Enumerations**: Create numbered lists like "(1) apple, (2) banana, and (3) cherry"
|
||||
- **Run-in Bullet Lists**: Make bullet-point lists flow in a single line
|
||||
- **Run-in Term Definitions**: Format term-definition pairs inline
|
||||
- **Run-in Verse**: Join poetry lines with custom separators
|
||||
- **Smart Separator Detection**: Automatically switches between commas and semicolons based on content
|
||||
- **Flexible Coordination**: Use "and", "or", "and/or", or no coordinator between the last two items
|
||||
|
||||
## Usage
|
||||
|
||||
```typst
|
||||
#import "@preview/run-liners:0.1.0": *
|
||||
|
||||
// Basic enumeration
|
||||
#run-in-enum([Apple], [Banana], [Cherry])
|
||||
// Output: (1) Apple, (2) Banana, and (3) Cherry
|
||||
|
||||
// Bullet list with custom marker
|
||||
#run-in-list(
|
||||
marker: [#sym.ballot.check],
|
||||
[First],
|
||||
[Second],
|
||||
[Third]
|
||||
)
|
||||
// Output: ✓ First, ✓ Second, and ✓ Third
|
||||
|
||||
// Term definitions
|
||||
#run-in-terms(
|
||||
([Term 1], [Definition 1]),
|
||||
([Term 2], [Definition 2])
|
||||
)
|
||||
// Output: Term 1: Definition 1, and Term 2: Definition 2
|
||||
|
||||
// Poetry lines
|
||||
#run-in-verse(
|
||||
[Line 1],
|
||||
[Line 2],
|
||||
[Line 3]
|
||||
)
|
||||
// Output: Line 1 / Line 2 / Line 3
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
- `separator`: Use "auto" for smart detection or specify like ", " or "; "
|
||||
- `coordinator`: "and", "or", "and/or", or none
|
||||
- `numbering-pattern`: "(1)", "(A)", etc. for enumerations
|
||||
- `marker`: Customize bullet points
|
||||
- `term-formatter`: Style your terms (bold by default)
|
||||
|
||||
## Documentation
|
||||
|
||||
See the [manual](docs/manual.pdf) for detailed examples and usage guidelines.
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](LICENSE)
|
||||
@@ -0,0 +1,6 @@
|
||||
watchexec \
|
||||
--watch . \
|
||||
--clear \
|
||||
--ignore 'tests/**/diff/**' \
|
||||
--ignore 'tests/**/out/**' \
|
||||
"typst-test r"
|
||||
@@ -0,0 +1,472 @@
|
||||
#import "/lib.typ": *
|
||||
|
||||
#import "@preview/codly:1.1.1": *
|
||||
#import "@preview/codly-languages:0.1.1": *
|
||||
#show: codly-init.with()
|
||||
#codly(languages: codly-languages)
|
||||
|
||||
#set page(width: 8.5in, height: 11in, margin: 1in, numbering: "1",
|
||||
header: [#h(1fr) Version: `0.1.0`])
|
||||
#set par(justify: true)
|
||||
#show raw.where(block: true): set text(size:7pt)
|
||||
|
||||
#let easy-typography(
|
||||
body-size: 10pt,
|
||||
body-font: "Source Serif Pro",
|
||||
heading-font: "Source Sans Pro",
|
||||
paper: none,
|
||||
margin: none,
|
||||
body
|
||||
) = {
|
||||
// Constants
|
||||
let heading-above-max = 1.25em
|
||||
let heading-above-min = 0.75em
|
||||
let heading-below-max = 0.65em
|
||||
let heading-below-min = 0.52em
|
||||
let heading-size-max = 1.10em
|
||||
let heading-size-min = 1.00em
|
||||
let body-weight = "light"
|
||||
let line-spacing = 1.25
|
||||
let paragraph-spacing = 2.00
|
||||
|
||||
// Optional page setup
|
||||
if paper != none {
|
||||
set page(paper: paper)
|
||||
}
|
||||
if margin != none {
|
||||
set page(margin: margin)
|
||||
}
|
||||
|
||||
// Paragraphs
|
||||
set par(
|
||||
leading: line-spacing * 0.5em,
|
||||
spacing: paragraph-spacing * 0.5em,
|
||||
justify: true,
|
||||
linebreaks: "optimized",
|
||||
)
|
||||
|
||||
// Body text
|
||||
set text(
|
||||
font: body-font,
|
||||
fallback: false,
|
||||
style: "normal",
|
||||
weight: body-weight,
|
||||
stretch: 100%,
|
||||
size: body-size,
|
||||
tracking: 0pt,
|
||||
spacing: 100% + 0pt,
|
||||
baseline: 0pt,
|
||||
overhang: true,
|
||||
hyphenate: true,
|
||||
kerning: true,
|
||||
ligatures: true,
|
||||
number-type: "lining",
|
||||
)
|
||||
|
||||
// Top-heavy easing function for heading sizes/spacing:
|
||||
// - max = biggest size (H1), min = smallest size (H5), level in [1..5]
|
||||
// - sqrt(t) => gives biggest decrease at top, gentlest at bottom
|
||||
let compute-size(max, min, level) = {
|
||||
if level <= 1 {
|
||||
max
|
||||
} else if level >= 5 {
|
||||
min
|
||||
} else {
|
||||
let t = (level - 1) / 4
|
||||
max - (max - min) * calc.sqrt(t)
|
||||
}
|
||||
}
|
||||
|
||||
// Heading weight logic
|
||||
let compute-weight(level) = {
|
||||
if level <= 1 {
|
||||
"bold"
|
||||
} else if level == 2 {
|
||||
"semibold"
|
||||
} else if level == 3 {
|
||||
"medium"
|
||||
} else {
|
||||
"regular"
|
||||
}
|
||||
}
|
||||
|
||||
// Show headings using computed size/spacing values
|
||||
show heading: it => block(
|
||||
breakable: false,
|
||||
sticky: true,
|
||||
above: compute-size(heading-above-max, heading-above-min, it.level),
|
||||
below: compute-size(heading-below-max, heading-below-min, it.level),
|
||||
text(
|
||||
font: heading-font,
|
||||
size: compute-size(heading-size-max, heading-size-min, it.level),
|
||||
weight: compute-weight(it.level),
|
||||
it
|
||||
)
|
||||
)
|
||||
|
||||
// Finally, render the body
|
||||
body
|
||||
}
|
||||
|
||||
#show: easy-typography
|
||||
|
||||
#text(
|
||||
size: 3em,
|
||||
weight: "black",
|
||||
font: "Source Sans Pro",
|
||||
[`run-liners`: User Manual]
|
||||
)
|
||||
|
||||
#v(1fr)
|
||||
|
||||
#outline(depth: 1)
|
||||
|
||||
#pagebreak()
|
||||
|
||||
|
||||
#set heading(numbering: "1.1.")
|
||||
|
||||
= Introduction
|
||||
|
||||
This package provides a set of functions that create “run-in” lists and enumerations, following guidelines similar to the *Chicago Manual of Style*. You can produce run-in enumerations, bullet lists, terms/definitions, or verses, all joined in a single line with flexible separators and optional words like “and,” “or,” or _none_ (i.e. omit a coordinator).
|
||||
|
||||
We’ll illustrate each function using
|
||||
#run-in-terms(
|
||||
coordinator: "and",
|
||||
([the left column], [a `typst` block containing the Typst code you’d write]),
|
||||
([the right column], [the rendered result]),
|
||||
).
|
||||
|
||||
= `run-in-enum`: Run-in numbered lists
|
||||
`run-in-enum` is typically used for run-in enumerations like “(1) apple, (2) banana, and (3) cherry.” It offers these parameters:
|
||||
|
||||
- *`separator`*: Defaults to `"auto"` (which tries to detect commas and switch to semicolons).
|
||||
- *`coordinator`*: The word or phrase before the last item—defaults to `"and"`, can be `"or"`, `"and/or"`, or `none`.
|
||||
- *`numbering-pattern`*: A pattern like `"(1)"`, `"(A)"`, or any format the `numbering()` call supports.
|
||||
- *`numbering-formatter`*: A function that can style or transform the generated number.
|
||||
|
||||
|
||||
|
||||
== Example: Basic Three-Item Enumeration
|
||||
|
||||
#columns(2)[
|
||||
```typst
|
||||
#run-in-enum(
|
||||
[Apple],
|
||||
[Banana],
|
||||
[Cherry]
|
||||
)
|
||||
```
|
||||
#colbreak()
|
||||
|
||||
#run-in-enum(
|
||||
[Apple],
|
||||
[Banana],
|
||||
[Cherry]
|
||||
)
|
||||
]
|
||||
|
||||
This example uses *all defaults*:
|
||||
- `separator: "auto"` → because there’s no comma in the content, it uses commas.
|
||||
- `coordinator: "and"` → puts “and” before the last item.
|
||||
- `numbering-pattern: "(1)"` → “(1) (2) (3)”
|
||||
- `numbering-formatter: (it) => [#it]` → no special styling.
|
||||
|
||||
|
||||
|
||||
== Example: Coordinator = none, 4 Items, Comma in content
|
||||
|
||||
If one of your items contains `[text, with comma]`, the `auto` separator chooses `"; "`.
|
||||
|
||||
#columns(2)[
|
||||
```typst
|
||||
#run-in-enum(
|
||||
coordinator: none,
|
||||
[Item One],
|
||||
[Item Two, comma here],
|
||||
[Item Three],
|
||||
[Item Four]
|
||||
)
|
||||
```
|
||||
#colbreak()
|
||||
|
||||
#run-in-enum(
|
||||
coordinator: none,
|
||||
[Item One],
|
||||
[Item Two, comma here],
|
||||
[Item Three],
|
||||
[Item Four]
|
||||
)
|
||||
]
|
||||
|
||||
Notice it used semicolons because of comma detection, *and* no coordinator word (because `coordinator: none`).
|
||||
|
||||
== Example: Custom Numbering Pattern & Styling
|
||||
|
||||
#block(breakable: false)[
|
||||
You can change `numbering-pattern` to `"(A)"` or `"(i)"` and style the numbers with `numbering-formatter`.
|
||||
|
||||
#columns(2)[
|
||||
```typst
|
||||
#run-in-enum(
|
||||
numbering-pattern: "(A)",
|
||||
numbering-formatter: (txt) => [#strong(txt)],
|
||||
[Alpha],
|
||||
[Beta],
|
||||
[Gamma]
|
||||
)
|
||||
```
|
||||
#colbreak()
|
||||
|
||||
#run-in-enum(
|
||||
numbering-pattern: "(A)",
|
||||
numbering-formatter: (txt) => [#strong(txt)],
|
||||
[Alpha],
|
||||
[Beta],
|
||||
[Gamma]
|
||||
)
|
||||
]
|
||||
Here, `(A)`, `(B)`, `(C)` appear in *bold*.
|
||||
]
|
||||
|
||||
== Example: Single Item & Two Items Edge Cases
|
||||
|
||||
When only one item is present, no separator or coordinator is used. With two items, you’ll see just one separator plus “and/or/or” (depending on coordinator).
|
||||
|
||||
#columns(2)[
|
||||
```typst
|
||||
// Single item:
|
||||
#run-in-enum([LoneItem])
|
||||
```
|
||||
#colbreak()
|
||||
#run-in-enum([LoneItem])
|
||||
]
|
||||
#columns(2)[
|
||||
```typst
|
||||
// Two items:
|
||||
#run-in-enum([First], [Second])
|
||||
```
|
||||
#colbreak()
|
||||
#run-in-enum([First], [Second])
|
||||
]
|
||||
#columns(2)[
|
||||
|
||||
```typst
|
||||
// Two items, no coordinator:
|
||||
#run-in-enum(coordinator: none, [First], [Second])
|
||||
```
|
||||
#colbreak()
|
||||
#run-in-enum(coordinator: none, [First], [Second])
|
||||
]
|
||||
#columns(2)[
|
||||
|
||||
```typst
|
||||
// Three items:
|
||||
#run-in-enum([First], [Second], [Third])
|
||||
```
|
||||
#colbreak()
|
||||
#run-in-enum([First], [Second], [Third])
|
||||
]
|
||||
#columns(2)[
|
||||
|
||||
```typst
|
||||
// Three items, no coordinator:
|
||||
#run-in-enum(coordinator: none, [First], [Second], [Third])
|
||||
```
|
||||
#colbreak()
|
||||
#run-in-enum(coordinator: none, [First], [Second], [Third])
|
||||
]
|
||||
|
||||
|
||||
|
||||
= `run-in-list`: Run-in bullet points
|
||||
`run-in-list` behaves like `run-in-enum` but uses a *bullet (or any marker)* before each item. The rest of the logic is the same—`separator`, `coordinator`, etc.
|
||||
See the “run-in-enum” section for *how `auto` detection* and *`coordinator`* work.
|
||||
|
||||
|
||||
|
||||
== Example1: Default Bullets
|
||||
#columns(2)[
|
||||
```typst
|
||||
#run-in-list(
|
||||
[Apple],
|
||||
[Banana],
|
||||
[Cherry]
|
||||
)
|
||||
```
|
||||
#colbreak()
|
||||
|
||||
#run-in-list(
|
||||
[Apple],
|
||||
[Banana],
|
||||
[Cherry]
|
||||
)
|
||||
]
|
||||
|
||||
You get bullets `[•]` for each item by default.
|
||||
|
||||
== Example: Custom Marker, Coordinator = 'or'
|
||||
|
||||
#block(breakable: false)[
|
||||
#columns(2)[
|
||||
```typst
|
||||
#run-in-list(
|
||||
coordinator: "or",
|
||||
marker: [#sym.ballot.check],
|
||||
[First],
|
||||
[Second],
|
||||
[Third, comma item]
|
||||
)
|
||||
```
|
||||
#colbreak()
|
||||
|
||||
#run-in-list(
|
||||
coordinator: "or",
|
||||
marker: [#sym.ballot.check],
|
||||
[First],
|
||||
[Second],
|
||||
[Third, comma item]
|
||||
)
|
||||
]
|
||||
Because of the comma, it uses semicolons. The coordinator is now `"or"`.
|
||||
]
|
||||
|
||||
= `run-in-terms`: Run-in term definitions
|
||||
|
||||
`run-in-terms` is for run-in *terms and definitions*. By default, each term is *bold* (`[#strong(term)]`) followed by the definition, and you still get the same *separator* and *coordinator* logic as in `run-in-enum`.
|
||||
|
||||
== Example: Three Terms, No Coordinator
|
||||
|
||||
#columns(2)[
|
||||
```typst
|
||||
#run-in-terms(
|
||||
coordinator: none,
|
||||
(
|
||||
([Goal], [Summarize the prior research]),
|
||||
([Methods], [Outline the approach]),
|
||||
([Outcome], [Analyze the results])
|
||||
)
|
||||
)
|
||||
```
|
||||
#colbreak()
|
||||
#run-in-terms(
|
||||
coordinator: none,
|
||||
([Goal], [Summarize the prior research]),
|
||||
([Methods], [Outline the approach]),
|
||||
([Outcome], [Analyze the results])
|
||||
)
|
||||
]
|
||||
|
||||
See how no “and” or “or” appears. It detects commas if they exist.
|
||||
|
||||
|
||||
|
||||
== Example: Custom Term Formatter
|
||||
#columns(2)[
|
||||
```typst
|
||||
#run-in-terms(
|
||||
term-formatter: (txt) => [#underline(txt)],
|
||||
([Key], [Value 1]),
|
||||
([Another Key], [Value 2])
|
||||
)
|
||||
```
|
||||
#colbreak()
|
||||
#run-in-terms(
|
||||
term-formatter: (txt) => [#underline(txt)],
|
||||
([Key], [Value 1]),
|
||||
([Another Key], [Value 2])
|
||||
)
|
||||
]
|
||||
|
||||
Each term is underlined, with a colon after the term.
|
||||
|
||||
|
||||
|
||||
= `run-in-verse`: Run-in poetry lines
|
||||
`run-in-verse` simply joins lines (verses) with a given *separator* (default: `[ /~]`), and no coordinator. It’s much simpler since you typically don’t want “and” in between lines of poetry.
|
||||
|
||||
== Example: Default Verse Joining
|
||||
#columns(2)[
|
||||
```typst
|
||||
#run-in-verse(
|
||||
[Line 1],
|
||||
[Line 2],
|
||||
[Line 3]
|
||||
)
|
||||
```
|
||||
#colbreak()
|
||||
#run-in-verse(
|
||||
[Line 1],
|
||||
[Line 2],
|
||||
[Line 3]
|
||||
)
|
||||
]
|
||||
|
||||
== Example: Custom Separator
|
||||
|
||||
#block(breakable: false)[
|
||||
#columns(2)[
|
||||
```typst
|
||||
// Overriding the default with a comma + space
|
||||
#run-in-verse(
|
||||
separator: ", ",
|
||||
[Line A],
|
||||
[Line B],
|
||||
[Line C]
|
||||
)
|
||||
```
|
||||
#colbreak()
|
||||
#run-in-verse(
|
||||
separator: ", ",
|
||||
[Line A],
|
||||
[Line B],
|
||||
[Line C]
|
||||
)
|
||||
]
|
||||
]
|
||||
|
||||
= Direct `run-in-join`
|
||||
All these functions ultimately call *`run-in-join`*, which you can use yourself if you want to create custom transformations. You supply:
|
||||
|
||||
1. *`separator`* (or `"auto"` for comma detection).
|
||||
2. *`coordinator`* or `none`.
|
||||
3. A *spread* of content items (`..content`).
|
||||
|
||||
|
||||
|
||||
== Example: Using `run-in-join` Directly
|
||||
#columns(2)[
|
||||
```typst
|
||||
#run-in-join(
|
||||
coordinator: "and/or",
|
||||
[First item],
|
||||
[Second item],
|
||||
[Third item, comma triggers semicolon],
|
||||
[Final item]
|
||||
)
|
||||
```
|
||||
#colbreak()
|
||||
#run-in-join(
|
||||
coordinator: "and/or",
|
||||
[First item],
|
||||
[Second item],
|
||||
[Third item, comma triggers semicolon],
|
||||
[Final item]
|
||||
)
|
||||
]
|
||||
|
||||
You can see that it inserts semicolons (auto detection) and “and/or” before the last item.
|
||||
|
||||
|
||||
|
||||
= Conclusion
|
||||
That’s your tour of the *run-in* functions! Remember:
|
||||
- If you want enumerations with `(1)` or `(A)` prefixes, use *`run-in-enum`*.
|
||||
- For bullet lists, use *`run-in-list`*.
|
||||
- For term–definition pairs, *`run-in-terms`*.
|
||||
- For verse lines, *`run-in-verse`*.
|
||||
- Or just call *`run-in-join`* yourself for custom needs.
|
||||
|
||||
Explore different *separators* (like `[ /~]`, `", "`, or `"; "`) and *coordinators* (`"and"`, `"or"`, `"none"`, etc.) to get the exact run-in style your text requires.
|
||||
|
||||
Happy Typst-ing!
|
||||
@@ -0,0 +1 @@
|
||||
#import "src/main.typ": run-in-join, run-in-enum, run-in-list, run-in-terms, run-in-verse
|
||||
@@ -0,0 +1,77 @@
|
||||
#let run-in-join(
|
||||
// Determines the in-between separator for all but the last item.
|
||||
// - If set to "auto", we'll detect whether content has commas.
|
||||
// - Otherwise, use it literally (e.g., ", ", " / ", etc.).
|
||||
separator: "auto",
|
||||
|
||||
// The word or phrase (e.g., "and", "or", "and/or") that comes before the last item.
|
||||
// - If set to `none`, we skip any coordinator.
|
||||
coordinator: "and",
|
||||
|
||||
// Content items you want to join.
|
||||
// e.g., `[ [#(1) " item one"], [#(2) " item two"], ... ]`
|
||||
..content,
|
||||
) = {
|
||||
// 1. Decide on the base separator.
|
||||
let sep = if separator == "auto" {
|
||||
// naive check: if any item in the content sequence includes a comma, use semicolons
|
||||
if content.pos().any((item) => repr(item).find(regex("\[[^]]*,[^]]*\]")) != none) {
|
||||
"; "
|
||||
} else {
|
||||
", "
|
||||
}
|
||||
} else {
|
||||
separator
|
||||
}
|
||||
|
||||
// 2. Figure out how to handle the last separator.
|
||||
// If `coordinator` is none, just do a normal join.
|
||||
// If `oxford` is true and there are 3+ items, insert a comma before coordinator.
|
||||
let final-sep = if coordinator != none and content.pos().len() == 2 {
|
||||
// For 3 or more items, we do something like: ", and "
|
||||
// That is, a final comma plus the coordinator
|
||||
" " + coordinator + " "
|
||||
} else if coordinator != none and content.pos().len() > 2 {
|
||||
// For 3 or more items, we do something like: ", and "
|
||||
// That is, a final comma plus the coordinator
|
||||
sep + coordinator + " "
|
||||
} else {
|
||||
// No coordinator or too few items; the final separator is just `sep`.
|
||||
sep
|
||||
}
|
||||
|
||||
// 3. Perform the join:
|
||||
content.pos().join(
|
||||
sep,
|
||||
last: final-sep
|
||||
)
|
||||
}
|
||||
|
||||
#let run-in-enum(separator: "auto", coordinator: "and", numbering-pattern: "(1)", numbering-formatter: (it) => [#it], ..items) = {
|
||||
let contents = items.pos().enumerate(start: 1).map(((index, item)) => {
|
||||
[#numbering-formatter(numbering(numbering-pattern, index))~#item]
|
||||
})
|
||||
run-in-join(separator: separator, coordinator: coordinator, ..contents)
|
||||
}
|
||||
|
||||
#let run-in-list(separator: "auto", coordinator: "and", marker: [•], ..items) = {
|
||||
let contents = items.pos().map((item) => {
|
||||
[#marker~#item]
|
||||
})
|
||||
run-in-join(separator: separator, coordinator: coordinator, ..contents)
|
||||
}
|
||||
|
||||
#let run-in-terms(separator: "auto", coordinator: "and", term-formatter: (it) => [#strong(it)], ..terms) = {
|
||||
let contents = terms.pos().map((t) => {
|
||||
if type(t) != array or t.len() != 2 {
|
||||
panic("arguments to run-in-terms must be arrays of the form (term, definition)")
|
||||
}
|
||||
[#term-formatter(t.at(0)):~#t.at(1)]
|
||||
})
|
||||
run-in-join(separator: separator, coordinator: coordinator, ..contents)
|
||||
}
|
||||
|
||||
#let run-in-verse(separator: [ /~], coordinator: none, ..verses) = {
|
||||
let contents = verses
|
||||
run-in-join(separator: separator, coordinator: coordinator, ..contents)
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.0 MiB |
@@ -0,0 +1,335 @@
|
||||
|
||||
// exhaustive-test.typ
|
||||
// =============================================================================
|
||||
// EXHAUSTIVE TESTS for your run-in library
|
||||
// =============================================================================
|
||||
// This file demonstrates almost every combination of named/positional arguments
|
||||
// for run-in-enum, run-in-list, run-in-terms, run-in-verse, and run-in-join,
|
||||
// including zero items, single item, multiple items, bracketed commas, etc.
|
||||
//
|
||||
// Adjust import path to your library as needed:
|
||||
//
|
||||
// #import "/lib.typ": * // or whatever your actual path is
|
||||
//
|
||||
// Then compile.
|
||||
// =============================================================================
|
||||
|
||||
#import "/lib.typ": *
|
||||
|
||||
#set page(height: auto, width: 6in, margin: 1em)
|
||||
|
||||
// A small helper for easy labeling:
|
||||
#let heading = (text) => {
|
||||
[#strong(text) "\n"]
|
||||
}
|
||||
#let subheading = (text) => {
|
||||
[#emph(text) "\n"]
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 1) run-in-enum TESTS
|
||||
// =============================================================================
|
||||
#heading("1) run-in-enum Tests")
|
||||
|
||||
// 1A. NO NAMED ARGUMENTS (uses defaults: separator=auto, coordinator=and, etc.)
|
||||
#subheading("1A: No named arguments")
|
||||
#text("Zero items => Should produce nothing:")
|
||||
#run-in-enum()
|
||||
|
||||
|
||||
#text("Single item => Should just produce \"(1) <item>\":")
|
||||
#run-in-enum([Single item here])
|
||||
|
||||
|
||||
#text("Two items => Typically comma, then \"and\":")
|
||||
#run-in-enum([First], [Second])
|
||||
|
||||
|
||||
#text("Three items => Commas, then \"and\" before last:")
|
||||
#run-in-enum([Apple], [Banana], [Cherry])
|
||||
|
||||
|
||||
#text("Three items w/ bracketed comma => triggers semicolons:")
|
||||
#run-in-enum([Item1], [[test, bracketed]], [Item3])
|
||||
|
||||
|
||||
// 1B. ALL NAMED ARGUMENTS
|
||||
#subheading("1B: All named arguments")
|
||||
#text("separator=', ', coordinator='or', numbering-pattern='(A)', custom numbering-formatter => bold:")
|
||||
#run-in-enum(
|
||||
separator: ", ",
|
||||
coordinator: "or",
|
||||
numbering-pattern: "(A)",
|
||||
numbering-formatter: (val) => [#strong(val)],
|
||||
[Alpha],
|
||||
[Beta],
|
||||
[Gamma]
|
||||
)
|
||||
|
||||
|
||||
#text("separator='; ', coordinator=none, numbering-pattern='(i)', numbering-formatter=>italics, 4 items:")
|
||||
#run-in-enum(
|
||||
separator: "; ",
|
||||
coordinator: none,
|
||||
numbering-pattern: "(i)",
|
||||
numbering-formatter: (val) => [#emph(val)],
|
||||
[Item A],
|
||||
[[Bracket, comma]],
|
||||
[Item C],
|
||||
[Item D]
|
||||
)
|
||||
|
||||
|
||||
// 1C. MIXED SCENARIOS
|
||||
#subheading("1C: Mixed scenarios")
|
||||
#text("Two items, coordinator='and/or':")
|
||||
#run-in-enum(
|
||||
coordinator: "and/or",
|
||||
[Red],
|
||||
[Blue]
|
||||
)
|
||||
|
||||
|
||||
#text("Single item, custom numbering-pattern='(###)':")
|
||||
#run-in-enum(
|
||||
numbering-pattern: "( -- 1 -- )",
|
||||
[JustOne]
|
||||
)
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// 2) run-in-list TESTS
|
||||
// =============================================================================
|
||||
#heading("2) run-in-list Tests (bulleted run-in)")
|
||||
|
||||
// 2A. NO NAMED ARGUMENTS (uses defaults: separator=auto, coordinator=and, marker=[•])
|
||||
#subheading("2A: No named arguments")
|
||||
#text("Zero items => Should produce nothing:")
|
||||
#run-in-list()
|
||||
|
||||
|
||||
#text("Single item => One bullet, no join needed:")
|
||||
#run-in-list([Only me])
|
||||
|
||||
|
||||
#text("Two items => bullet for each, comma by default, then 'and':")
|
||||
#run-in-list([First], [Second])
|
||||
|
||||
|
||||
#text("Three items => bracketed comma triggers semicolons, plus 'and':")
|
||||
#run-in-list([One], [[Two, bracketed]], [Three])
|
||||
|
||||
|
||||
// 2B. ALL NAMED ARGUMENTS
|
||||
#subheading("2B: All named arguments")
|
||||
#text("separator='; ', coordinator='or', marker=[-> ]:")
|
||||
#run-in-list(
|
||||
separator: "; ",
|
||||
coordinator: "or",
|
||||
marker: [-> ],
|
||||
[Apple],
|
||||
[Banana],
|
||||
[Cherry]
|
||||
)
|
||||
|
||||
|
||||
#text("separator=', ', coordinator=none, marker=[❖ ] (for instance):")
|
||||
#run-in-list(
|
||||
separator: ", ",
|
||||
coordinator: none,
|
||||
marker: [❖ ],
|
||||
[ListOne],
|
||||
[ListTwo],
|
||||
[ListThree]
|
||||
)
|
||||
|
||||
|
||||
// 2C. MIXED SCENARIOS
|
||||
#subheading("2C: Mixed scenarios")
|
||||
#text("Single item with custom marker [✓ ]:")
|
||||
#run-in-list(
|
||||
marker: [✓ ],
|
||||
[One item only]
|
||||
)
|
||||
|
||||
|
||||
#text("Three items, coordinator='and/or':")
|
||||
#run-in-list(
|
||||
coordinator: "and/or",
|
||||
[ItemA],
|
||||
[ItemB],
|
||||
[ItemC]
|
||||
)
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// 3) run-in-terms TESTS
|
||||
// =============================================================================
|
||||
#heading("3) run-in-terms Tests (term => definition)")
|
||||
|
||||
// 3A. NO NAMED ARGUMENTS (defaults: separator=auto, coordinator=and, term-formatter=(it)=>[#strong(it)])
|
||||
#subheading("3A: No named arguments")
|
||||
#text("Zero terms => produce nothing:")
|
||||
// #run-in-terms([]) // appropriately panics :)
|
||||
|
||||
|
||||
#text("Single term => no join needed:")
|
||||
#run-in-terms(
|
||||
([OnlyTerm], [ItsDefinition]),
|
||||
)
|
||||
|
||||
|
||||
#text("Two terms => comma then 'and':")
|
||||
#run-in-terms(
|
||||
([FirstTerm], [DefinitionOne]),
|
||||
([SecondTerm], [DefinitionTwo])
|
||||
)
|
||||
|
||||
|
||||
#text("Three terms => bracketed comma triggers semicolons + 'and':")
|
||||
#run-in-terms(
|
||||
([Term1], [Definition1]),
|
||||
([Term2], [Def, bracketed]),
|
||||
([Term3], [Definition3])
|
||||
)
|
||||
|
||||
|
||||
// 3B. ALL NAMED ARGUMENTS
|
||||
#subheading("3B: All named arguments")
|
||||
#text("separator='; ', coordinator='none', custom term-formatter => italic, 3 terms:")
|
||||
#run-in-terms(
|
||||
separator: "; ",
|
||||
coordinator: none,
|
||||
term-formatter: (txt) => [#emph(txt)],
|
||||
([Goal], [Summarize prior research]),
|
||||
([Methods], [Outline approach]),
|
||||
([Outcome], [Analyze results])
|
||||
)
|
||||
|
||||
|
||||
#text("separator=', ', coordinator='or', custom term-formatter => underline, 2 terms:")
|
||||
#run-in-terms(
|
||||
separator: ", ",
|
||||
coordinator: "or",
|
||||
term-formatter: (txt) => [#underline(txt)],
|
||||
([Key], [Value 1]),
|
||||
([Secondary], [Value 2])
|
||||
)
|
||||
|
||||
|
||||
// 3C. MIXED SCENARIOS
|
||||
#subheading("3C: Mixed scenarios")
|
||||
#text("Single term, coordinator='and/or' => no effect because only one term:")
|
||||
#run-in-terms(
|
||||
coordinator: "and/or",
|
||||
([OneTerm], [OneDefinition],)
|
||||
)
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// 4) run-in-verse TESTS
|
||||
// =============================================================================
|
||||
#heading("4) run-in-verse Tests")
|
||||
|
||||
// By default: separator=[ /~], coordinator=none, ..verses
|
||||
|
||||
// 4A. Testing zero, single, multiple verses
|
||||
#subheading("4A: No named arguments")
|
||||
#text("Zero verses => nothing:")
|
||||
#run-in-verse()
|
||||
|
||||
|
||||
#text("Single verse => no joins needed:")
|
||||
#run-in-verse([Alone in the verse])
|
||||
|
||||
|
||||
#text("Two verses => joined with ' / ':")
|
||||
#run-in-verse([Line one], [Line two])
|
||||
|
||||
|
||||
#text("Three verses => bracketed commas don't matter here, but let's try anyway:")
|
||||
#run-in-verse([LineA], [[Line, with comma]], [LineC])
|
||||
|
||||
|
||||
// 4B. Overriding the default separator (rare but possible)
|
||||
#subheading("4B: Custom separator")
|
||||
#text("Using separator=', ' while coordinator=none:")
|
||||
#run-in-verse(
|
||||
separator: ", ",
|
||||
[VerseOne],
|
||||
[VerseTwo],
|
||||
[VerseThree]
|
||||
)
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// 5) DIRECT run-in-join TESTS
|
||||
// =============================================================================
|
||||
#heading("5) Direct run-in-join Tests")
|
||||
|
||||
// We’ll systematically test zero, single, multiple items,
|
||||
// with or without named arguments.
|
||||
|
||||
#subheading("5A: Minimal usage => no named args, zero items => nothing.")
|
||||
#run-in-join()
|
||||
|
||||
|
||||
#text("Single item, no named args => no join needed:")
|
||||
#run-in-join([Solo])
|
||||
|
||||
|
||||
#text("Two items, no named args => comma + 'and':")
|
||||
#run-in-join([Item A], [Item B])
|
||||
|
||||
|
||||
#text("Three items, bracketed comma => semicolons + 'and':")
|
||||
#run-in-join([A1], [[B, bracketed]], [C1])
|
||||
|
||||
|
||||
#subheading("5B: All named args")
|
||||
#text("separator='; ', coordinator='or', 3 items => semicolons and \"or\"")
|
||||
#run-in-join(
|
||||
separator: "; ",
|
||||
coordinator: "or",
|
||||
[Alpha],
|
||||
[Beta],
|
||||
[Gamma]
|
||||
)
|
||||
|
||||
|
||||
#text("separator=[ /~], coordinator='and/or', 4 items => ' / ' as base sep + 'and/or' before last:")
|
||||
#run-in-join(
|
||||
separator: [ /~],
|
||||
coordinator: "and/or",
|
||||
[One],
|
||||
[Two],
|
||||
[Three],
|
||||
[Four]
|
||||
)
|
||||
|
||||
|
||||
#subheading("5C: Edge combos")
|
||||
#text("Two items, coordinator=none => just a single separator between them.")
|
||||
#run-in-join(
|
||||
coordinator: none,
|
||||
[X],
|
||||
[Y]
|
||||
)
|
||||
|
||||
|
||||
#text("Three items, separator=', ', coordinator=none => no 'and':")
|
||||
#run-in-join(
|
||||
separator: ", ",
|
||||
coordinator: none,
|
||||
[X2],
|
||||
[Y2],
|
||||
[Z2]
|
||||
)
|
||||
|
||||
|
||||
#text("Single item, bracketed comma => no effect since there's no join anyway.")
|
||||
#run-in-join([[Has, bracketed]])
|
||||
|
||||
|
||||
#text("Done with direct run-in-join tests.")
|
||||
|
||||
|
After Width: | Height: | Size: 129 KiB |
@@ -0,0 +1,39 @@
|
||||
#import "/lib.typ": *
|
||||
|
||||
#set page(margin: 1em, height: auto, width: 5in)
|
||||
|
||||
*`#run-in-enum()`* creates run-in numbered lists, like:
|
||||
#run-in-enum(
|
||||
[one],
|
||||
[two],
|
||||
[three],
|
||||
).
|
||||
|
||||
#line(length: 100%)
|
||||
|
||||
*`#run-in-list()`* creates run-in bullet points, like:
|
||||
#run-in-list(
|
||||
[one],
|
||||
[two],
|
||||
[three],
|
||||
).
|
||||
|
||||
#line(length: 100%)
|
||||
|
||||
*`#run-in-terms()`* creates run-in term lists, like:
|
||||
#run-in-terms(
|
||||
([enumerations], [numbered lists]),
|
||||
([lists], [bulleted lists]),
|
||||
([term lists], [definition lists]),
|
||||
([verses], [poetry (or similar) lines])
|
||||
).
|
||||
|
||||
#line(length: 100%)
|
||||
|
||||
*`#run-in-verse()`* creates run-in verses, like:
|
||||
#run-in-verse(
|
||||
[Now is the time],
|
||||
[for all good men],
|
||||
[to come to the aid],
|
||||
[of their country]
|
||||
).
|
||||
|
After Width: | Height: | Size: 29 KiB |
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "run-liners"
|
||||
version = "0.1.0"
|
||||
entrypoint = "lib.typ"
|
||||
authors = ["Stephen Waits <steve@waits.net>"]
|
||||
license = "MIT"
|
||||
description = "Functions to create various run-in lists."
|
||||
categories = ["model"]
|
||||
keywords = ["run-in", "enum", "list", "terms"]
|
||||
repository = "https://github.com/swaits/typst-collection"
|
||||
exclude = ["thumbnail.png", "tests", "bin", "docs/manual.pdf"]
|
||||
@@ -0,0 +1,2 @@
|
||||
tests/**/out/
|
||||
tests/**/diff/
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
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
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,57 @@
|
||||
# Tasteful Pairings
|
||||
|
||||
A carefully curated collection of font pairings for [Typst](https://typst.app/),
|
||||
focusing on readability and typographic harmony. Each pairing combines a
|
||||
sans-serif heading font with a serif body font, following established
|
||||
typographic principles for clear visual hierarchy and optimal reading
|
||||
experience.
|
||||
|
||||
## Installation
|
||||
|
||||
```typ
|
||||
#import "@preview/tasteful-pairings:0.1.0": *
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```typ
|
||||
#let pairing = font-pairings.at("modern-heritage")
|
||||
|
||||
#show heading: set text(font: pairing.heading)
|
||||
#set text(font: pairing.body)
|
||||
|
||||
= Your Document Title
|
||||
Your content here...
|
||||
```
|
||||
|
||||
## Available Pairings
|
||||
|
||||
- **`ibm-plex`** - Modern corporate-friendly superfamily
|
||||
- **`noto`** - Extensive language support, highly legible
|
||||
- **`source`** - Adobe's refined open-source pair
|
||||
- **`friendly-weather`** - Open Fira Sans with space-efficient Merriweather
|
||||
- **`android`** - Complete Roboto family look
|
||||
- **`kindle`** - Amazon's reading-optimized fonts
|
||||
- **`office`** - Classic Microsoft Office combination
|
||||
- **`modern-heritage`** - Contemporary Montserrat with timeless Georgia Pro
|
||||
- **`legible`** - Reading-focused Lexend and Literata
|
||||
|
||||
## Gallery
|
||||
|
||||

|
||||
|
||||
## Philosophy
|
||||
|
||||
The pairings in this collection follow these principles:
|
||||
|
||||
1. **Sans for Headlines, Serif for Body** - Following traditional typographic
|
||||
wisdom for clear hierarchy
|
||||
2. **Readability First** - Each pairing is tested for optimal reading experience
|
||||
3. **Complementary Characteristics** - Fonts are matched based on x-height,
|
||||
weight balance, and character width
|
||||
4. **Practical Applications** - Selected for real-world use cases from corporate
|
||||
documents to digital reading
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](LICENSE).
|
||||
@@ -0,0 +1 @@
|
||||
#import "src/main.typ": font-pairings
|
||||
@@ -0,0 +1,55 @@
|
||||
#let font-pairings = (
|
||||
"ibm-plex": (
|
||||
heading: "IBM Plex Sans",
|
||||
body: "IBM Plex Serif",
|
||||
description: "A modern corporate-friendly superfamily with a wide weight range. Clean, neutral, and highly legible."
|
||||
),
|
||||
|
||||
"noto": (
|
||||
heading: "Noto Sans",
|
||||
body: "Noto Serif",
|
||||
description: "Huge language coverage, highly legible, and neutral. Great for multilingual documents."
|
||||
),
|
||||
|
||||
"source": (
|
||||
heading: "Source Sans 3",
|
||||
body: "Source Serif 4",
|
||||
description: "Adobe's open-source pair. Clean, highly readable, and well-hinted for both screen and print."
|
||||
),
|
||||
|
||||
"friendly-weather": (
|
||||
heading: "Fira Sans",
|
||||
body: "Merriweather",
|
||||
description: "Open, friendly sans plus a space-efficient modern serif. Good for text-heavy documents."
|
||||
),
|
||||
|
||||
"android": (
|
||||
heading: "Roboto",
|
||||
body: "Roboto Serif",
|
||||
description: "A complete Android-friendly look. Roboto is extremely common; Roboto Serif is its matching new serif companion."
|
||||
),
|
||||
|
||||
"kindle": (
|
||||
heading: "Amazon Ember",
|
||||
body: "Bookerly",
|
||||
description: "The Kindle pairing. Bookerly is a warm, book-like serif; Amazon Ember is a clean, readable sans."
|
||||
),
|
||||
|
||||
"office": (
|
||||
heading: "Calibri",
|
||||
body: "Cambria",
|
||||
description: "A classic Microsoft Office pairing. Calibri (sans) for headings, Cambria (serif) for body text."
|
||||
),
|
||||
|
||||
"modern-heritage": (
|
||||
heading: "Montserrat",
|
||||
body: "Georgia Pro",
|
||||
description: "Merges the warm, traditional forms of Georgia Pro with Montserrat’s clean, geometric lines. A modern-yet-classic pairing, equally suited to formal reports or stylish web layouts."
|
||||
),
|
||||
|
||||
"legible": (
|
||||
heading: "Lexend",
|
||||
body: "Literata",
|
||||
description: "An ultra-legible pairing designed for reading fluency. Lexend’s tall x-height and open shapes reduce visual stress, while Literata brings a warm, bookish feel to body text."
|
||||
),
|
||||
)
|
||||
|
After Width: | Height: | Size: 994 KiB |
@@ -0,0 +1,23 @@
|
||||
#import "/lib.typ": *
|
||||
|
||||
#set page(margin: 1em, height: auto, width: 5.5in)
|
||||
#set par(justify: true, linebreaks: "optimized")
|
||||
|
||||
#let keys = font-pairings.keys().sorted()
|
||||
|
||||
#for key in keys {
|
||||
block(
|
||||
stroke: 1pt + navy,
|
||||
inset: 1em,
|
||||
radius: 1em,
|
||||
[
|
||||
#let pairing = font-pairings.at(key)
|
||||
#show heading: set text(font: pairing.heading, weight: "bold")
|
||||
= #pairing.heading & #pairing.body #h(1fr) #text(fill: eastern, weight: "light", size: 0.8em, baseline: -3pt, ["#key"])
|
||||
#set text(font: pairing.body, weight: "light")
|
||||
#pairing.description
|
||||
|
||||
#lorem(20)
|
||||
]
|
||||
)
|
||||
}
|
||||
|
After Width: | Height: | Size: 366 KiB |
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "tasteful-pairings"
|
||||
version = "0.1.0"
|
||||
entrypoint = "lib.typ"
|
||||
authors = ["Stephen Waits <steve@waits.net>"]
|
||||
license = "MIT"
|
||||
description = "A carefully curated collection of font pairings."
|
||||
keywords = ["font", "pairing", "typography"]
|
||||
repository = "https://github.com/swaits/typst-collection"
|
||||
exclude = ["thumbnail.png", "tests"]
|
||||