├── .gitignore ├── typst.toml ├── lib.typ ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.pdf 2 | -------------------------------------------------------------------------------- /typst.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "numbly" 3 | version = "0.1.0" 4 | entrypoint = "lib.typ" 5 | authors = ["flaribbit <@flaribbit>"] 6 | license = "MIT" 7 | description = "A package that helps you to specify different numbering formats for different levels of headings." 8 | categories = ["utility"] 9 | keywords = ["numbering", "helper", "tool"] 10 | repository = "https://github.com/flaribbit/numbly" -------------------------------------------------------------------------------- /lib.typ: -------------------------------------------------------------------------------- 1 | #let numbly(..arr, default: "1.") = (..nums) => { 2 | let arr = arr.pos() 3 | nums = nums.pos() 4 | if nums.len() > arr.len() { 5 | if default == none { 6 | return none 7 | } 8 | if type(default) == function { 9 | return default(..nums) 10 | } 11 | return numbering(default, ..nums) 12 | } 13 | let format = arr.at(nums.len() - 1) 14 | if format == none { 15 | return none 16 | } 17 | if type(format) == function { 18 | return format(..nums) 19 | } 20 | format.replace( 21 | regex("\{(\d)(:(.+?))?\}"), 22 | m => { 23 | let (a, b, c) = m.captures 24 | if b != none { 25 | numbering(c, nums.at(int(a) - 1)) 26 | } else { 27 | str(nums.at(int(a) - 1)) 28 | } 29 | }, 30 | ) 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 梦飞翔 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # numbly 2 | 3 | A package that helps you to specify different numbering formats for different levels of headings. 4 | 5 | ## Usage example 6 | 7 | Suppose you want to specify the following numbering format for your document: 8 | 9 | - Appendix A. Guide 10 | - A.1. Installation 11 | - Step 1. Download 12 | - Step 2. Install 13 | - A.2. Usage 14 | 15 | You might use `if` to achieve this: 16 | 17 | ```typst 18 | #set heading(numbering: (..nums) => { 19 | nums = nums.pos() 20 | if nums.len() == 1 { 21 | return "Appendix " + numbering("A.", ..nums) 22 | } else if nums.len() == 2 { 23 | return numbering("A.1.", ..nums) 24 | } else { 25 | return "Step " + numbering("1.", nums.last()) 26 | } 27 | }) 28 | 29 | = Guide 30 | == Installation 31 | === Download 32 | === Install 33 | == Usage 34 | ``` 35 | 36 | But with `numbly`, you can do this more easily: 37 | 38 | ```typst 39 | #import "@preview/numbly:0.1.0": numbly 40 | #set heading(numbering: numbly( 41 | "Appendix {1:A}.", // use {level:format} to specify the format 42 | "{1:A}.{2}.", // if format is not specified, arabic numbers will be used 43 | "Step {3}.", // here, we only want the 3rd level 44 | )) 45 | 46 | = Guide 47 | == Installation 48 | === Download 49 | === Install 50 | == Usage 51 | ``` 52 | 53 | ![image](https://github.com/user-attachments/assets/27e81a8e-e154-43b8-bed7-d3cd8ef4b2a4) 54 | 55 | Here is another example: 56 | ```typst 57 | #import "@preview/numbly:0.1.0": numbly 58 | #set heading(numbering: numbly( 59 | "Part {1:I}:", 60 | "{2}.", 61 | "{2}.{3}.", 62 | )) 63 | #show heading.where(level: 1): set align(center) 64 | 65 | = Getting Started with Python 66 | == Introduction to Python 67 | === What is Python? 68 | === Why Choose Python? 69 | === Python 2 vs. Python 3 70 | == Setting Up Your Environment 71 | === Installing Python 72 | === Setting up an Integrated Development Environment (IDE) 73 | = Core Concepts 74 | == Control Structures 75 | == Functions 76 | ``` 77 | 78 | ![image](https://github.com/user-attachments/assets/a80432d1-e679-4354-a2ac-2eb2c5c8edd0) 79 | 80 | ## General explanation 81 | 82 | In general the function `numbly` takes an arbitrary number of string arguments. 83 | The first argument specifies the formating of the numbering of the first level headers, the second for the second level headers and so on. 84 | If one wants to access the number of the $n$th level header, one can use `{n:f}`, where `f` is a counting symbol, which states how the number is represented (e.g. `1` stands for arabic numbers, which is the default, `I` for roman numbers from capital letters and so on). A list of all possible counting symbols can be found in the typst documentation of numbering (https://typst.app/docs/reference/model/numbering/). 85 | 86 | ## Bonus 87 | 88 | Although the following scenario was not initially considered, we were surprised to find that this library can also be used to number lists and page numbers! 89 | 90 | ```typst 91 | #import "@preview/numbly:0.1.0": numbly 92 | #set enum(full: true, numbering: numbly( 93 | "{1:A}.", 94 | "{2}.", 95 | "{3})", 96 | )) 97 | 98 | + Item 1 99 | + Item 2 100 | + Item 3 101 | + Item 4 102 | + Item 5 103 | + Item 6 104 | + Item 7 105 | ``` 106 | 107 | ![image](https://github.com/user-attachments/assets/03ee2c54-3429-4dba-a832-984be7ad32b4) 108 | 109 | ```typst 110 | #import "@preview/numbly:0.1.0": numbly 111 | #set text(lang: "zh") 112 | #set page(numbering: numbly("{1}", "第{1}页/共{2}页")) 113 | 114 | #outline() 115 | = 你说得对 116 | #pagebreak() 117 | = 但是原神 118 | ``` 119 | 120 | ![image](https://github.com/user-attachments/assets/1b1cf577-b5fe-4a74-a0b6-6d3eb7231a7a) 121 | --------------------------------------------------------------------------------