-
Notifications
You must be signed in to change notification settings - Fork 1
/
delegis.typ
199 lines (169 loc) · 5.23 KB
/
delegis.typ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// Copyright (c) 2024 WüSpace e. V.
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
// sentence number substitution marker
#let s = "XXXXXXSENTENCEXXXNUMBERXXXXXX"
/// Create an unmarkes section, such as a preamble.
/// Usage: `#unnumbered[Preamble]`
#let unnumbered = (it, ..rest) => heading(level: 6, numbering: none, ..rest, it)
/// Manually create a section. Useful when unsupported characters are used in the heading.
/// Usage: `#section[§ 3][Administrator*innen]`
#let section = (number, it, ..rest) => unnumbered(
{
number + "\n" + it
},
..rest,
)
/// Division prefixes for different languages.
#let division-prefixes-de = ("Teil", "Kapitel", "Abschnitt", "Unterabschnitt")
#let division-prefixes-en = ("Part", "Chapter", "Division", "Subdivision")
/// Initialize a delegis document.
#let delegis = (
// Metadata
title : "Vereinsordnung zur IT-Infrastruktur",
abbreviation : "ITVO",
resolution : "3. Beschluss des Vorstands vom 24.01.2024",
in-effect : "24.01.2024",
draft : false,
// Template
logo : none,
// Overrides
size : 11pt,
font : "Atkinson Hyperlegible",
lang : "de",
paper: "a5",
division-prefixes: none, // use language-specific prefixes by default
str-draft : "Entwurf",
str-intro : (resolution, in-effect) => [Mit Beschluss (#resolution) tritt zum #in-effect in Kraft:],
// Content
body
) => {
/// Language-specific division prefixes
let division-prefixes = if division-prefixes != none {
division-prefixes
} else if lang == "en" {
division-prefixes-en
} else {
division-prefixes-de // default to German
}
/// Metadata
set document(title: title + " (" + abbreviation + ")", keywords: (title, abbreviation, resolution, in-effect))
/// General Formatting
let bg = if draft {
rotate(45deg, text(100pt, fill: luma(85%), font: font, str-draft))
}
set page(paper: paper, numbering: "1 / 1", background: bg)
set text(hyphenate: true, lang: lang, size: size, font: font)
/// Clause Detection
show regex("§ ([0-9a-zA-Z]+) (.+)$"): it => {
let (_, number, ..rest) = it.text.split()
heading(
level: 6,
numbering: none,
{
"§ " + number + "\n" + rest.join(" ")
},
)
}
/// Heading Formatting
set heading(numbering: (..nums) => {
// Handbuch der Rechtsförmlichkeit, Rn. 379 f.
// After the final named level, use "X.X.X" for the numbering using the final prefix
nums = nums.pos()
let level = nums.len() // level of the heading
let number = nums.slice(calc.min(
division-prefixes.len(),
level,
) - 1)
let prefix = division-prefixes.at(
calc.min(
level - 1,
division-prefixes.len() - 1,
),
)
let str-number = numbering("1.1", ..number)
[
#prefix #str-number:
]
})
show heading: set align(center)
show heading: set text(size: size, weight: "regular")
show heading.where(level: 1): set text(style: "italic")
show heading.where(level: 2): set text(style: "italic")
show heading.where(level: 3): set text(style: "italic")
show heading.where(level: 4): set text(style: "italic")
show heading.where(level: 5): set text(style: "italic")
show heading.where(level: 6): set text(weight: "bold")
// Enumeration numbering
// 1. -> a) -> aa) -(unofficial)-> (1) -> i. -> i.i. -> ...
// Handbuch der Rechtsförmlichkeit, Rn. 374
set enum(
numbering: (..numbers) => {
let nums = numbers.pos()
if (nums.len() == 1) {
return numbering("1.", ..nums)
} else if (nums.len() == 2) {
return numbering("a)", ..nums.slice(1))
} else if (nums.len() == 3) {
let letter = numbering("a", ..nums.slice(2))
return [ #letter#letter) ]
} else if (nums.len() == 4) {
return numbering("(1)", ..nums.slice(3))
} else {
return numbering("i.", ..nums.slice(4))
}
},
full: true, // get full number arrays passed into the numbering function
)
/// Outlines
show outline.entry: it => {
show linebreak: it => { } // disable manual line breaks
show "\n": " " // disable section number line breaks
it
}
set outline(indent: 1cm)
show outline: it => {
it
pagebreak(weak: true)
}
/// Sentence Numbering
show regex(s): it => {
counter("sentence").step()
super(strong(counter("sentence").display()))
}
show parbreak: it => {
counter("sentence").update(0)
it
}
/// Title Page
page(
numbering: none,
{
place(top + right, block(width: 2cm, logo))
v(1fr)
show par: set block(spacing: .6em)
if draft {
text[#str-draft:]
} else {
par(text(str-intro(resolution, in-effect)))
}
par(text(2em, strong[#title (#abbreviation)]), leading: 0.6em)
v(3cm)
},
)
// Metadata once again. Needs to be down here to have the page size set.
// Can be used with `typst query`, e.g.:
//
// `typst query example.typ "<title>" --field value --one` returns `"[title]"`
[
#metadata(title)<title>
#metadata(abbreviation)<abbreviation>
#metadata(resolution)<resolution>
#metadata(in-effect)<in-effect>
]
// allow footnotes that don't conflict with sentence numbers
set footnote(numbering: "[1]")
/// Content
body
}