@anja.codes/vitakit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +159 -0
- package/dist/check.d.mts +22 -0
- package/dist/check.mjs +196 -0
- package/dist/cli.d.mts +45 -0
- package/dist/cli.mjs +225 -0
- package/dist/index.d.mts +398 -0
- package/dist/index.mjs +21 -0
- package/dist/nuxt.d.mts +15 -0
- package/dist/nuxt.mjs +98 -0
- package/dist/runtime/components/VitaDate.vue +20 -0
- package/dist/runtime/components/VitaEntry.vue +24 -0
- package/dist/runtime/components/VitaIssues.vue +25 -0
- package/dist/runtime/components/VitaLinks.vue +19 -0
- package/dist/runtime/components/VitaMarkdown.vue +14 -0
- package/dist/runtime/components/VitaPublication.vue +30 -0
- package/dist/runtime/components/VitaPublications.vue +39 -0
- package/dist/runtime/components/VitaSection.vue +60 -0
- package/dist/runtime/composables/useVitakit.ts +47 -0
- package/dist/schemas/education.ts +21 -0
- package/dist/schemas/employment.ts +21 -0
- package/dist/schemas/publications.ts +48 -0
- package/dist/schemas/supervision.ts +20 -0
- package/dist/schemas/talks.ts +19 -0
- package/dist/schemas/teaching.ts +19 -0
- package/dist/shared/index.d.mts +68 -0
- package/dist/shared/index.mjs +57 -0
- package/dist/shared/vitakit.BRhjqpAt.mjs +250 -0
- package/dist/shared/vitakit.BlU-p01e.mjs +14 -0
- package/dist/shared/vitakit.BxcnlFGP.mjs +325 -0
- package/dist/shared/vitakit.CypCF-4Q.mjs +503 -0
- package/dist/shared/vitakit.D8WRg_Xx.d.mts +153 -0
- package/dist/styles/vitakit-math.csl +314 -0
- package/dist/tex/templates/_generic.eta +6 -0
- package/dist/tex/templates/education.eta +9 -0
- package/dist/tex/templates/employment.eta +9 -0
- package/dist/tex/templates/publications.eta +7 -0
- package/dist/tex/templates/supervision.eta +4 -0
- package/dist/tex/templates/talks.eta +3 -0
- package/dist/tex/templates/teaching.eta +6 -0
- package/dist/tex/vitakit-cv.cls +119 -0
- package/dist/tex.d.mts +93 -0
- package/dist/tex.mjs +129 -0
- package/package.json +121 -0
- package/src/bin/vitakit-build-cv.mjs +50 -0
- package/src/bin/vitakit-check.mjs +57 -0
- package/src/bin/vitakit.mjs +158 -0
- package/styles/vitakit-math.csl +314 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!--
|
|
3
|
+
The vitakit default style for content/publications.bib on the website.
|
|
4
|
+
|
|
5
|
+
To change it, copy it into your project and edit the copy:
|
|
6
|
+
|
|
7
|
+
pnpm vitakit eject publications.csl # -> content/publications.csl
|
|
8
|
+
|
|
9
|
+
content/publications.csl is picked up automatically, by the dev server, the
|
|
10
|
+
build and vitakit-check alike. Any CSL 1.0 style works there, for instance one
|
|
11
|
+
from https://www.zotero.org/styles saved under that name.
|
|
12
|
+
|
|
13
|
+
Links are not this file's job. vitakit links the title (to the url, doi or
|
|
14
|
+
arxiv field, in that order) and appends badges (DOI, arXiv, MR, zbMATH), and
|
|
15
|
+
it removes those identifiers from what the style sees, so that a style which
|
|
16
|
+
prints them does not repeat them as raw text. A <text variable="DOI"/> or
|
|
17
|
+
<text variable="URL"/> here therefore prints nothing for an entry whose DOI
|
|
18
|
+
or URL is already linked.
|
|
19
|
+
|
|
20
|
+
The PDF does not use this file: it is typeset by biblatex.
|
|
21
|
+
-->
|
|
22
|
+
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only">
|
|
23
|
+
<info>
|
|
24
|
+
<title>vitakit (mathematics)</title>
|
|
25
|
+
<id>https://github.com/anja-codes/vitakit/styles/vitakit-math</id>
|
|
26
|
+
<author>
|
|
27
|
+
<name>Benjamin Hackl</name>
|
|
28
|
+
</author>
|
|
29
|
+
<summary>Numeric style for mathematics: author-year ordering, linked titles, short journal information.</summary>
|
|
30
|
+
<category citation-format="numeric"/>
|
|
31
|
+
<category field="engineering"/>
|
|
32
|
+
<category field="generic-base"/>
|
|
33
|
+
<updated>2026-09-25T00:00:00+00:00</updated>
|
|
34
|
+
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
|
|
35
|
+
</info>
|
|
36
|
+
<locale xml:lang="en">
|
|
37
|
+
<terms>
|
|
38
|
+
<term name="chapter" form="short">ch.</term>
|
|
39
|
+
<term name="presented at">presented at the</term>
|
|
40
|
+
</terms>
|
|
41
|
+
</locale>
|
|
42
|
+
<!-- Macros -->
|
|
43
|
+
<macro name="edition">
|
|
44
|
+
<choose>
|
|
45
|
+
<if type="bill book chapter graphic legal_case legislation motion_picture paper-conference report song" match="any">
|
|
46
|
+
<choose>
|
|
47
|
+
<if is-numeric="edition">
|
|
48
|
+
<group delimiter=" ">
|
|
49
|
+
<number variable="edition" form="ordinal"/>
|
|
50
|
+
<text term="edition" form="short"/>
|
|
51
|
+
</group>
|
|
52
|
+
</if>
|
|
53
|
+
<else>
|
|
54
|
+
<text variable="edition" text-case="capitalize-first" suffix="."/>
|
|
55
|
+
</else>
|
|
56
|
+
</choose>
|
|
57
|
+
</if>
|
|
58
|
+
</choose>
|
|
59
|
+
</macro>
|
|
60
|
+
<macro name="issued">
|
|
61
|
+
<choose>
|
|
62
|
+
<if type="article-journal report" match="any">
|
|
63
|
+
<date variable="issued">
|
|
64
|
+
<date-part name="month" form="short" suffix=" "/>
|
|
65
|
+
<date-part name="year" form="long"/>
|
|
66
|
+
</date>
|
|
67
|
+
</if>
|
|
68
|
+
<else-if type=" bill book chapter graphic legal_case legislation motion_picture paper-conference song thesis" match="any">
|
|
69
|
+
<date variable="issued">
|
|
70
|
+
<date-part name="year" form="long"/>
|
|
71
|
+
</date>
|
|
72
|
+
</else-if>
|
|
73
|
+
<else>
|
|
74
|
+
<date variable="issued">
|
|
75
|
+
<date-part name="day" form="numeric-leading-zeros" suffix="-"/>
|
|
76
|
+
<date-part name="month" form="short" suffix="-" strip-periods="true"/>
|
|
77
|
+
<date-part name="year" form="long"/>
|
|
78
|
+
</date>
|
|
79
|
+
</else>
|
|
80
|
+
</choose>
|
|
81
|
+
</macro>
|
|
82
|
+
<macro name="author">
|
|
83
|
+
<names variable="author">
|
|
84
|
+
<name delimiter=", " and="text"/>
|
|
85
|
+
<label form="short" prefix=", " text-case="capitalize-first"/>
|
|
86
|
+
<substitute>
|
|
87
|
+
<names variable="editor"/>
|
|
88
|
+
<names variable="translator"/>
|
|
89
|
+
</substitute>
|
|
90
|
+
</names>
|
|
91
|
+
</macro>
|
|
92
|
+
<macro name="editor">
|
|
93
|
+
<names variable="editor">
|
|
94
|
+
<name initialize-with=". " delimiter=", " and="text"/>
|
|
95
|
+
<label form="short" prefix=", " text-case="capitalize-first"/>
|
|
96
|
+
</names>
|
|
97
|
+
</macro>
|
|
98
|
+
<macro name="locators">
|
|
99
|
+
<group delimiter=", ">
|
|
100
|
+
<text macro="edition"/>
|
|
101
|
+
<group delimiter=" ">
|
|
102
|
+
<text term="volume" form="short"/>
|
|
103
|
+
<number variable="volume" form="numeric" font-weight="bold"/>
|
|
104
|
+
</group>
|
|
105
|
+
<group delimiter=" ">
|
|
106
|
+
<number variable="number-of-volumes" form="numeric"/>
|
|
107
|
+
<text term="volume" form="short" plural="true"/>
|
|
108
|
+
</group>
|
|
109
|
+
<group delimiter=" ">
|
|
110
|
+
<text term="issue" form="short"/>
|
|
111
|
+
<number variable="issue" form="numeric"/>
|
|
112
|
+
</group>
|
|
113
|
+
</group>
|
|
114
|
+
</macro>
|
|
115
|
+
<macro name="title">
|
|
116
|
+
<!-- Title linking is handled by @behackl/citation-js-extras at render time;
|
|
117
|
+
the CSL just outputs the plain italic title text. -->
|
|
118
|
+
<text variable="title" font-style="italic"/>
|
|
119
|
+
</macro>
|
|
120
|
+
<macro name="publisher">
|
|
121
|
+
<choose>
|
|
122
|
+
<if type=" bill book chapter graphic legal_case legislation motion_picture paper-conference song" match="any">
|
|
123
|
+
<group delimiter=": ">
|
|
124
|
+
<text variable="publisher-place"/>
|
|
125
|
+
<text variable="publisher"/>
|
|
126
|
+
</group>
|
|
127
|
+
</if>
|
|
128
|
+
<else>
|
|
129
|
+
<group delimiter=", ">
|
|
130
|
+
<text variable="publisher"/>
|
|
131
|
+
<text variable="publisher-place"/>
|
|
132
|
+
</group>
|
|
133
|
+
</else>
|
|
134
|
+
</choose>
|
|
135
|
+
</macro>
|
|
136
|
+
<macro name="event">
|
|
137
|
+
<choose>
|
|
138
|
+
<if type="paper-conference speech" match="any">
|
|
139
|
+
<choose>
|
|
140
|
+
<!-- Published Conference Paper -->
|
|
141
|
+
<if variable="container-title">
|
|
142
|
+
<group delimiter=", ">
|
|
143
|
+
<group delimiter=" ">
|
|
144
|
+
<text term="in"/>
|
|
145
|
+
<text variable="container-title" font-style="italic"/>
|
|
146
|
+
</group>
|
|
147
|
+
<text variable="event-place"/>
|
|
148
|
+
</group>
|
|
149
|
+
</if>
|
|
150
|
+
<!-- Unpublished Conference Paper -->
|
|
151
|
+
<else>
|
|
152
|
+
<group delimiter=", ">
|
|
153
|
+
<group delimiter=" ">
|
|
154
|
+
<text term="presented at"/>
|
|
155
|
+
<text variable="event"/>
|
|
156
|
+
</group>
|
|
157
|
+
<text variable="event-place"/>
|
|
158
|
+
</group>
|
|
159
|
+
</else>
|
|
160
|
+
</choose>
|
|
161
|
+
</if>
|
|
162
|
+
</choose>
|
|
163
|
+
</macro>
|
|
164
|
+
<macro name="page">
|
|
165
|
+
<group>
|
|
166
|
+
<label variable="page" form="short" suffix=" "/>
|
|
167
|
+
<text variable="page"/>
|
|
168
|
+
</group>
|
|
169
|
+
</macro>
|
|
170
|
+
<macro name="citation-locator">
|
|
171
|
+
<group delimiter=" ">
|
|
172
|
+
<choose>
|
|
173
|
+
<if locator="page">
|
|
174
|
+
<label variable="locator" form="short"/>
|
|
175
|
+
</if>
|
|
176
|
+
<else>
|
|
177
|
+
<label variable="locator" form="short" text-case="capitalize-first"/>
|
|
178
|
+
</else>
|
|
179
|
+
</choose>
|
|
180
|
+
<text variable="locator"/>
|
|
181
|
+
</group>
|
|
182
|
+
</macro>
|
|
183
|
+
<!-- Citation -->
|
|
184
|
+
<citation collapse="citation-number">
|
|
185
|
+
<sort>
|
|
186
|
+
<key variable="citation-number"/>
|
|
187
|
+
</sort>
|
|
188
|
+
<layout delimiter=", ">
|
|
189
|
+
<group prefix="[" suffix="]" delimiter=", ">
|
|
190
|
+
<text variable="citation-number"/>
|
|
191
|
+
<text macro="citation-locator"/>
|
|
192
|
+
</group>
|
|
193
|
+
</layout>
|
|
194
|
+
</citation>
|
|
195
|
+
<!-- Bibliography -->
|
|
196
|
+
<bibliography entry-spacing="0">
|
|
197
|
+
<layout>
|
|
198
|
+
<!-- Author(s) -->
|
|
199
|
+
<text macro="author" suffix=", "/>
|
|
200
|
+
<!-- Rest of Citation -->
|
|
201
|
+
<group suffix=". ">
|
|
202
|
+
<choose>
|
|
203
|
+
<!-- Specific Formats -->
|
|
204
|
+
<if type="article-journal">
|
|
205
|
+
<group delimiter=", ">
|
|
206
|
+
<text macro="title"/>
|
|
207
|
+
<text variable="container-title" font-style="italic" form="short"/>
|
|
208
|
+
<text macro="locators"/>
|
|
209
|
+
<text macro="page"/>
|
|
210
|
+
<text macro="issued"/>
|
|
211
|
+
</group>
|
|
212
|
+
</if>
|
|
213
|
+
<else-if type="paper-conference">
|
|
214
|
+
<group delimiter=", ">
|
|
215
|
+
<text macro="title"/>
|
|
216
|
+
<text macro="event"/>
|
|
217
|
+
<text macro="issued"/>
|
|
218
|
+
<text macro="locators"/>
|
|
219
|
+
<text macro="page"/>
|
|
220
|
+
</group>
|
|
221
|
+
</else-if>
|
|
222
|
+
<else-if type="report">
|
|
223
|
+
<group delimiter=", ">
|
|
224
|
+
<text macro="title"/>
|
|
225
|
+
<text macro="publisher"/>
|
|
226
|
+
<group delimiter=" ">
|
|
227
|
+
<text variable="genre"/>
|
|
228
|
+
<text variable="number"/>
|
|
229
|
+
</group>
|
|
230
|
+
<text macro="issued"/>
|
|
231
|
+
</group>
|
|
232
|
+
</else-if>
|
|
233
|
+
<else-if type="thesis">
|
|
234
|
+
<group delimiter=", ">
|
|
235
|
+
<text macro="title"/>
|
|
236
|
+
<text variable="genre"/>
|
|
237
|
+
<text macro="publisher"/>
|
|
238
|
+
<text macro="issued"/>
|
|
239
|
+
</group>
|
|
240
|
+
</else-if>
|
|
241
|
+
<else-if type="webpage">
|
|
242
|
+
<group delimiter=", ">
|
|
243
|
+
<text macro="title"/>
|
|
244
|
+
<text variable="container-title" font-style="italic"/>
|
|
245
|
+
<text macro="issued"/>
|
|
246
|
+
</group>
|
|
247
|
+
</else-if>
|
|
248
|
+
<else-if type="patent">
|
|
249
|
+
<group delimiter=", ">
|
|
250
|
+
<text macro="title"/>
|
|
251
|
+
<text variable="number"/>
|
|
252
|
+
<text macro="issued"/>
|
|
253
|
+
</group>
|
|
254
|
+
</else-if>
|
|
255
|
+
<!-- Generic/Fallback Formats -->
|
|
256
|
+
<else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">
|
|
257
|
+
<group delimiter=", " suffix=". ">
|
|
258
|
+
<text macro="title"/>
|
|
259
|
+
<text macro="locators"/>
|
|
260
|
+
</group>
|
|
261
|
+
<group delimiter=", ">
|
|
262
|
+
<text macro="publisher"/>
|
|
263
|
+
<text macro="issued"/>
|
|
264
|
+
<text macro="page"/>
|
|
265
|
+
</group>
|
|
266
|
+
</else-if>
|
|
267
|
+
<else-if type="article-magazine article-newspaper broadcast interview manuscript map patent personal_communication song speech thesis webpage" match="any">
|
|
268
|
+
<group delimiter=", ">
|
|
269
|
+
<text macro="title"/>
|
|
270
|
+
<text variable="container-title" font-style="italic"/>
|
|
271
|
+
<text macro="locators"/>
|
|
272
|
+
<text macro="publisher"/>
|
|
273
|
+
<text macro="page"/>
|
|
274
|
+
<text macro="issued"/>
|
|
275
|
+
</group>
|
|
276
|
+
</else-if>
|
|
277
|
+
<else-if type="chapter paper-conference" match="any">
|
|
278
|
+
<group delimiter=", " suffix=", ">
|
|
279
|
+
<text macro="title"/>
|
|
280
|
+
<group delimiter=" ">
|
|
281
|
+
<text term="in"/>
|
|
282
|
+
<text variable="container-title" font-style="italic"/>
|
|
283
|
+
</group>
|
|
284
|
+
<text macro="locators"/>
|
|
285
|
+
</group>
|
|
286
|
+
<text macro="editor" suffix=" "/>
|
|
287
|
+
<group delimiter=", ">
|
|
288
|
+
<text macro="publisher"/>
|
|
289
|
+
<text macro="issued"/>
|
|
290
|
+
<text macro="page"/>
|
|
291
|
+
</group>
|
|
292
|
+
</else-if>
|
|
293
|
+
<else>
|
|
294
|
+
<group delimiter=", " suffix=". ">
|
|
295
|
+
<text macro="title"/>
|
|
296
|
+
<text variable="container-title" font-style="italic"/>
|
|
297
|
+
<text macro="locators"/>
|
|
298
|
+
<choose>
|
|
299
|
+
<if variable="note">
|
|
300
|
+
<text variable="note"/>
|
|
301
|
+
</if>
|
|
302
|
+
</choose>
|
|
303
|
+
</group>
|
|
304
|
+
<group delimiter=", ">
|
|
305
|
+
<text macro="publisher"/>
|
|
306
|
+
<text macro="page"/>
|
|
307
|
+
<text macro="issued"/>
|
|
308
|
+
</group>
|
|
309
|
+
</else>
|
|
310
|
+
</choose>
|
|
311
|
+
</group>
|
|
312
|
+
</layout>
|
|
313
|
+
</bibliography>
|
|
314
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<% for (const item of it.entries) { %>
|
|
2
|
+
\vitaentry{<%~ it.date(item.date) %>}{<%~ it.rich(item.degree) %>}{<%~ it.inst(item.institution) %>}
|
|
3
|
+
<% if (item.thesis) { %>
|
|
4
|
+
\vitanote{<%~ it.tex(item.thesis.type ?? 'Thesis') %>: \emph{<%~ it.rich(item.thesis.title) %>}<% if (item.thesis.supervisor) { %>, supervised by <%~ it.linkOrText(item.thesis.supervisor) %><% } %>}
|
|
5
|
+
<% } %>
|
|
6
|
+
<% if (item.note) { %>
|
|
7
|
+
\vitanote{<%~ it.rich(item.note) %>}
|
|
8
|
+
<% } %>
|
|
9
|
+
<% } %>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<% for (const item of it.entries) { %>
|
|
2
|
+
\vitaentry{<%~ it.date(item.date) %>}{<%~ it.rich(item.position) %>}{<%~ it.inst(item.institution) %>}
|
|
3
|
+
<% if (item.project) { %>
|
|
4
|
+
\vitanote{Project <% if (item.project.url) { %>\href{<%~ it.url(item.project.url) %>}{\emph{<%~ it.rich(item.project.title) %>}}<% } else { %>\emph{<%~ it.rich(item.project.title) %>}<% } %><% if (item.project.funder) { %> (<%~ it.tex(item.project.funder) %><% if (item.project.grant) { %>~<%~ it.tex(item.project.grant) %><% } %>)<% } %>}
|
|
5
|
+
<% } %>
|
|
6
|
+
<% if (item.note) { %>
|
|
7
|
+
\vitanote{<%~ it.rich(item.note) %>}
|
|
8
|
+
<% } %>
|
|
9
|
+
<% } %>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<% for (const item of it.entries) { %>
|
|
2
|
+
\vitaentry{<%~ it.date(item.date) %><% if (item.ongoing) { %>--<% } %>}{<%~ it.tex(item.student) %>}{<%~ [item.degree && it.tex(item.degree), it.inst(item.institution)].filter(Boolean).join(', ') %>}
|
|
3
|
+
\vitanote{\emph{<%~ it.rich(item.title) %>}<% if (item.coSupervisor) { %>, with <%~ it.tex(item.coSupervisor) %><% } %><% if (item.ongoing) { %> (in progress)<% } %>}
|
|
4
|
+
<% } %>
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
%% vitakit-cv.cls -- document class for CVs generated by vitakit.
|
|
2
|
+
%%
|
|
3
|
+
%% The generated section files only ever use the macros defined here, so the
|
|
4
|
+
%% entire visual design can be changed by redefining them in preamble.tex
|
|
5
|
+
%% without touching anything vitakit produces.
|
|
6
|
+
\NeedsTeXFormat{LaTeX2e}
|
|
7
|
+
\ProvidesClass{vitakit-cv}[2026/01/01 vitakit CV class]
|
|
8
|
+
|
|
9
|
+
%% Options must be declared and processed before the base class is loaded.
|
|
10
|
+
\newif\ifvita@bib \vita@bibtrue
|
|
11
|
+
\DeclareOption{nobib}{\vita@bibfalse}
|
|
12
|
+
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
|
|
13
|
+
\ProcessOptions\relax
|
|
14
|
+
\LoadClass[11pt,a4paper]{article}
|
|
15
|
+
|
|
16
|
+
\RequirePackage[margin=2.5cm]{geometry}
|
|
17
|
+
\RequirePackage{enumitem}
|
|
18
|
+
\RequirePackage{xcolor}
|
|
19
|
+
\RequirePackage{titlesec}
|
|
20
|
+
\RequirePackage{amsmath,amssymb}
|
|
21
|
+
\RequirePackage{hyperref}
|
|
22
|
+
|
|
23
|
+
%% --- bibliography ---------------------------------------------------------
|
|
24
|
+
%% biblatex is loaded here so that a CV needs no bibliography setup at all.
|
|
25
|
+
%% Pass [nobib] to the class and load it yourself to use a different style.
|
|
26
|
+
\ifvita@bib
|
|
27
|
+
\RequirePackage[backend=biber, style=numeric, sorting=ydnt,
|
|
28
|
+
defernumbers=true, maxbibnames=99, giveninits=true]{biblatex}
|
|
29
|
+
%% \vitabibgroup{id}{key,key,...} defines the bibliography check `vita-id`,
|
|
30
|
+
%% which keeps exactly the listed entries. The generated publications.tex
|
|
31
|
+
%% uses one per group: vitakit decides the groups, with the website's rules
|
|
32
|
+
%% (a missing `status` is `published`, case does not matter), so the PDF
|
|
33
|
+
%% lists what the website lists. Keys are compared as strings.
|
|
34
|
+
\newcommand{\vitabibgroup}[2]{%
|
|
35
|
+
\defbibcheck{vita-#1}{%
|
|
36
|
+
\edef\vita@bibkey{\thefield{entrykey}}%
|
|
37
|
+
\def\vita@bibfound{0}%
|
|
38
|
+
\forcsvlist{\vita@bibmatch}{#2}%
|
|
39
|
+
\ifnum\vita@bibfound=0 \skipentry\fi}}
|
|
40
|
+
\newcommand{\vita@bibmatch}[1]{%
|
|
41
|
+
\expandafter\ifstrequal\expandafter{\vita@bibkey}{#1}{\def\vita@bibfound{1}}{}}
|
|
42
|
+
%% `status` is also copied to `keywords`, for hand-written
|
|
43
|
+
%% \printbibliography[keyword=...] calls.
|
|
44
|
+
\DeclareSourcemap{\maps[datatype=bibtex]{
|
|
45
|
+
\map{\step[fieldsource=status, fieldtarget=keywords]}
|
|
46
|
+
%% The same custom fields the website turns into badges. `final` stops the
|
|
47
|
+
%% map for entries without the field, which must not become arXiv eprints.
|
|
48
|
+
\map{\step[fieldsource=arxiv, final]
|
|
49
|
+
\step[fieldsource=arxiv, fieldtarget=eprint]
|
|
50
|
+
\step[fieldset=eprinttype, fieldvalue=arxiv]}
|
|
51
|
+
%% biblatex expects a bare DOI; exports also write doi:10... or a URL.
|
|
52
|
+
\map{\step[fieldsource=doi,
|
|
53
|
+
match=\regexp{\A(doi:\s*|https?://(dx\.)?doi\.org/)}, replace={}]}
|
|
54
|
+
}}
|
|
55
|
+
\fi
|
|
56
|
+
|
|
57
|
+
\definecolor{vitalink}{HTML}{1D4ED8}
|
|
58
|
+
\definecolor{vitamuted}{HTML}{555555}
|
|
59
|
+
\hypersetup{colorlinks=true, urlcolor=vitalink, linkcolor=vitalink, pdfborder={0 0 0}}
|
|
60
|
+
|
|
61
|
+
%% --- document selection --------------------------------------------------
|
|
62
|
+
%% \vitadocument{name} points \vitasection at cv-tex/generated/<name>/.
|
|
63
|
+
\newcommand{\vitadocument}[1]{\def\vita@document{#1}}
|
|
64
|
+
\vitadocument{cv}
|
|
65
|
+
|
|
66
|
+
%% --- data from content/profile.yml ---------------------------------------
|
|
67
|
+
\newcommand{\vitaname}[1]{\def\vita@name{#1}}
|
|
68
|
+
\newcommand{\vitatagline}[1]{\def\vita@tagline{#1}}
|
|
69
|
+
\newcommand{\vitacontact}[1]{\def\vita@contact{#1}}
|
|
70
|
+
\vitaname{} \vitatagline{} \vitacontact{}
|
|
71
|
+
|
|
72
|
+
\newcommand{\vitaheader}{%
|
|
73
|
+
\begingroup
|
|
74
|
+
\noindent{\LARGE\bfseries\vita@name}\par
|
|
75
|
+
\ifx\vita@tagline\empty\else\vspace{0.2em}\noindent{\color{vitamuted}\vita@tagline}\par\fi
|
|
76
|
+
\ifx\vita@contact\empty\else\vspace{0.2em}\noindent{\small\vita@contact}\par\fi
|
|
77
|
+
\vspace{1em}\hrule\vspace{1.5em}
|
|
78
|
+
\endgroup}
|
|
79
|
+
|
|
80
|
+
%% --- sections ------------------------------------------------------------
|
|
81
|
+
%% Section headings are real \section commands, so the table of contents and
|
|
82
|
+
%% PDF bookmarks work as usual.
|
|
83
|
+
\titleformat{\section}{\large\bfseries}{}{0pt}{}
|
|
84
|
+
\titlespacing*{\section}{0pt}{1.4em}{0.6em}
|
|
85
|
+
|
|
86
|
+
%% Per-document heading overrides: \vitasectiontitle{teaching}{Courses taught}
|
|
87
|
+
\newcommand{\vitasectiontitle}[2]{\expandafter\def\csname vita@title@#1\endcsname{#2}}
|
|
88
|
+
\newcommand{\vita@titlefor}[1]{%
|
|
89
|
+
\ifcsname vita@title@#1\endcsname\csname vita@title@#1\endcsname\else#1\fi}
|
|
90
|
+
|
|
91
|
+
\newenvironment{vitaentries}
|
|
92
|
+
{\begin{list}{}{%
|
|
93
|
+
\setlength{\leftmargin}{7em}\setlength{\labelwidth}{6.4em}%
|
|
94
|
+
\setlength{\labelsep}{0.6em}\setlength{\itemsep}{0.5em}%
|
|
95
|
+
\setlength{\parsep}{0pt}\setlength{\topsep}{0.3em}%
|
|
96
|
+
\renewcommand{\makelabel}[1]{\small\color{vitamuted}##1\hfill}}}
|
|
97
|
+
{\end{list}}
|
|
98
|
+
|
|
99
|
+
%% \vitaentry{date}{title}{context}
|
|
100
|
+
\newcommand{\vitaentry}[3]{%
|
|
101
|
+
\item[#1]{\bfseries #2}%
|
|
102
|
+
\ifx\relax#3\relax\else\par{\small #3}\fi}
|
|
103
|
+
|
|
104
|
+
%% A continuation line inside the current entry. Uses \par rather than \\ so
|
|
105
|
+
%% that it is safe after any preceding content, including none.
|
|
106
|
+
\newcommand{\vitanote}[1]{\par{\small\color{vitamuted}#1}}
|
|
107
|
+
|
|
108
|
+
%% \vitasection{id} -- heading plus the generated file for this document.
|
|
109
|
+
\newcommand{\vitasection}[1]{%
|
|
110
|
+
\section{\vita@titlefor{#1}}%
|
|
111
|
+
\begin{vitaentries}%
|
|
112
|
+
\input{generated/\vita@document/#1.tex}%
|
|
113
|
+
\end{vitaentries}}
|
|
114
|
+
|
|
115
|
+
%% \vitainput{id} -- the generated file without heading or list wrapper,
|
|
116
|
+
%% for sections that bring their own structure (publications).
|
|
117
|
+
\newcommand{\vitainput}[1]{\input{generated/\vita@document/#1.tex}}
|
|
118
|
+
|
|
119
|
+
\endinput
|
package/dist/tex.d.mts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { Entry, PublicationGroup } from './index.mjs';
|
|
3
|
+
|
|
4
|
+
interface BuildOptions {
|
|
5
|
+
rootDir: string;
|
|
6
|
+
/** Build only these documents; all of them when empty. */
|
|
7
|
+
only?: string[];
|
|
8
|
+
/** Emit .tex but skip latexmk. */
|
|
9
|
+
noPdf?: boolean;
|
|
10
|
+
}
|
|
11
|
+
declare function buildCv(options: BuildOptions): Promise<string[]>;
|
|
12
|
+
/** Read a generated file, for tests and diagnostics. */
|
|
13
|
+
declare function readGenerated(rootDir: string, document: string, section: string): Promise<string>;
|
|
14
|
+
|
|
15
|
+
declare const documentSchema: z.ZodObject<{
|
|
16
|
+
visibility: z.ZodDefault<z.ZodEnum<{
|
|
17
|
+
public: "public";
|
|
18
|
+
cv: "cv";
|
|
19
|
+
private: "private";
|
|
20
|
+
}>>;
|
|
21
|
+
sections: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
22
|
+
where: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>;
|
|
23
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
24
|
+
since: z.ZodOptional<z.ZodNumber>;
|
|
25
|
+
until: z.ZodOptional<z.ZodNumber>;
|
|
26
|
+
title: z.ZodOptional<z.ZodString>;
|
|
27
|
+
}, z.core.$strict>>>;
|
|
28
|
+
publications: z.ZodDefault<z.ZodObject<{
|
|
29
|
+
groups: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
30
|
+
}, z.core.$strict>>;
|
|
31
|
+
}, z.core.$strict>;
|
|
32
|
+
type DocumentOptions = z.infer<typeof documentSchema>;
|
|
33
|
+
interface DocumentSource {
|
|
34
|
+
/** Base name, e.g. `cv` for `cv-tex/cv.tex`. */
|
|
35
|
+
name: string;
|
|
36
|
+
texFile: string;
|
|
37
|
+
options: DocumentOptions;
|
|
38
|
+
}
|
|
39
|
+
/** Read every `cv-tex/*.tex` and its options. */
|
|
40
|
+
declare function discoverDocuments(cvDir: string): Promise<DocumentSource[]>;
|
|
41
|
+
/** Select the entries of one section for one document. */
|
|
42
|
+
declare function selectEntries(entries: Entry[], options: DocumentOptions, sectionId: string): Entry[];
|
|
43
|
+
|
|
44
|
+
/** `tex/` in the installed package: templates and the document class. */
|
|
45
|
+
declare const bundledTexDir: string;
|
|
46
|
+
interface EmitOptions {
|
|
47
|
+
sections: Record<string, Entry[]>;
|
|
48
|
+
publications: PublicationGroup[];
|
|
49
|
+
options: DocumentOptions;
|
|
50
|
+
/** `cv-tex/templates/`, where user overrides live. */
|
|
51
|
+
templateDir: string;
|
|
52
|
+
/** `cv-tex/generated/<document>/`. */
|
|
53
|
+
outDir: string;
|
|
54
|
+
/** `profile.url`: where the website is published, for links to paths on it. */
|
|
55
|
+
siteUrl?: string;
|
|
56
|
+
/** Path of the .bib file, relative to the generated directory. */
|
|
57
|
+
bibPath?: string;
|
|
58
|
+
}
|
|
59
|
+
/** Write one `.tex` file per section, plus `publications.tex`. */
|
|
60
|
+
declare function emitDocument(emit: EmitOptions): Promise<string[]>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* LaTeX escaping.
|
|
64
|
+
*
|
|
65
|
+
* This is the single most error-prone part of generating `.tex` from data, so
|
|
66
|
+
* it is centralised, tested, and applied by every helper a template can call
|
|
67
|
+
* (see `emit.ts`).
|
|
68
|
+
*
|
|
69
|
+
* Content fields may contain inline mathematics (`$k$-ary`), which must survive
|
|
70
|
+
* unescaped while the surrounding prose is escaped.
|
|
71
|
+
*/
|
|
72
|
+
interface EscapeOptions {
|
|
73
|
+
typography?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Original field value, set by `escapeRichTex`. A `$` reaching this function
|
|
76
|
+
* from rich text means a formula was never closed, which would otherwise
|
|
77
|
+
* produce silently wrong output.
|
|
78
|
+
*/
|
|
79
|
+
source?: string;
|
|
80
|
+
}
|
|
81
|
+
/** Escape a string for LaTeX text mode, without touching mathematics. */
|
|
82
|
+
declare function escapeTex(value: string, { typography, source }?: EscapeOptions): string;
|
|
83
|
+
/**
|
|
84
|
+
* Escape prose while preserving `$...$` and `$$...$$` spans verbatim.
|
|
85
|
+
*
|
|
86
|
+
* Used for `richText` fields, where a mathematician writes `Random $k$-ary
|
|
87
|
+
* trees` and expects the formula to reach LaTeX untouched.
|
|
88
|
+
*/
|
|
89
|
+
declare function escapeRichTex(value: string): string;
|
|
90
|
+
declare function escapeUrl(value: string): string;
|
|
91
|
+
|
|
92
|
+
export { buildCv, bundledTexDir, discoverDocuments, documentSchema, emitDocument, escapeRichTex, escapeTex, escapeUrl, readGenerated, selectEntries };
|
|
93
|
+
export type { BuildOptions, DocumentOptions, DocumentSource, EmitOptions, EscapeOptions };
|