oaktree-sapling 0.0.1

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.
Files changed (37) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +66 -0
  3. package/ci/run.sh +64 -0
  4. package/dist/cli.cjs +1230 -0
  5. package/package.json +50 -0
  6. package/paper-base.yml +29 -0
  7. package/plugins/gallery.mjs +224 -0
  8. package/templates/instance/brand/brand.yml +15 -0
  9. package/templates/instance/brand/logo.svg +4 -0
  10. package/templates/instance/editions/edition.yml +14 -0
  11. package/templates/instance/journal.yml +58 -0
  12. package/templates/instance/registry/papers.yml +20 -0
  13. package/templates/paper/.github/actions/engine/action.yml +59 -0
  14. package/templates/paper/.github/actions/engine/pins.yml +16 -0
  15. package/templates/paper/.github/workflows/check-post.yml +79 -0
  16. package/templates/paper/.github/workflows/check.yml +72 -0
  17. package/templates/paper/.github/workflows/ci.yml +64 -0
  18. package/templates/paper/.github/workflows/prepare.yml +34 -0
  19. package/templates/paper/.github/workflows/preview-deploy.yml +52 -0
  20. package/templates/paper/.github/workflows/publish.yml +33 -0
  21. package/templates/paper/.github/workflows/version-bump.yml +29 -0
  22. package/templates/paper/CODEOWNERS +9 -0
  23. package/templates/paper/bib.bib +6 -0
  24. package/templates/paper/gitignore +8 -0
  25. package/templates/paper/index.md +12 -0
  26. package/templates/paper/myst.yml +37 -0
  27. package/templates/site/.github/workflows/site.yml +73 -0
  28. package/templates/site/gitignore +5 -0
  29. package/templates/site/myst.yml +32 -0
  30. package/templates/site/package.json +9 -0
  31. package/templates/site/pages/index.md +25 -0
  32. package/templates/typst/LICENSE +21 -0
  33. package/templates/typst/frontmatter.typ +244 -0
  34. package/templates/typst/lapreprint.typ +310 -0
  35. package/templates/typst/template.typ +112 -0
  36. package/templates/typst/template.yml +82 -0
  37. package/typst.version +1 -0
@@ -0,0 +1,244 @@
1
+ #let orcidLogo(
2
+ // The ORCID identifier with no URL, e.g. `0000-0000-0000-0000`
3
+ orcid: none,
4
+ ) = {
5
+ /* Logos */
6
+ let orcidSvg = ```<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 24 24"><path fill="#AECD54" d="M21.8,12c0,5.4-4.4,9.8-9.8,9.8S2.2,17.4,2.2,12S6.6,2.2,12,2.2S21.8,6.6,21.8,12z M8.2,5.8c-0.4,0-0.8,0.3-0.8,0.8s0.3,0.8,0.8,0.8S9,7,9,6.6S8.7,5.8,8.2,5.8z M10.5,15.4h1.2v-6c0,0-0.5,0,1.8,0s3.3,1.4,3.3,3s-1.5,3-3.3,3s-1.9,0-1.9,0H10.5v1.1H9V8.3H7.7v8.2h2.9c0,0-0.3,0,3,0s4.5-2.2,4.5-4.1s-1.2-4.1-4.3-4.1s-3.2,0-3.2,0L10.5,15.4z"/></svg>```.text
7
+
8
+ if (orcid == none) {
9
+ // Do not
10
+ box(height: 1.1em, baseline: 13.5%, [#image.decode(orcidSvg)])
11
+ return
12
+ }
13
+
14
+ link("https://orcid.org/" + orcid)[#box(height: 1.1em, baseline: 13.5%)[#image(bytes(orcidSvg))]]
15
+ }
16
+
17
+ #let validateString(raw, name, alias: none) = {
18
+ if (name in raw) {
19
+ assert(type(raw.at(name)) == str, message: name + " must be a string")
20
+ return raw.at(name)
21
+ }
22
+ if (type(alias) != array) {
23
+ return
24
+ }
25
+ for a in alias {
26
+ if (a in raw) {
27
+ assert(type(raw.at(a)) == str, message: a + " must be a string")
28
+ return raw.at(a)
29
+ }
30
+ }
31
+ }
32
+
33
+ #let validateBoolean(raw, name, alias: none) = {
34
+ if (name in raw) {
35
+ assert(type(raw.at(name)) == bool, message: name + " must be a boolean")
36
+ return raw.at(name)
37
+ }
38
+ if (type(alias) != array) {
39
+ return
40
+ }
41
+ for a in alias {
42
+ if (a in raw) {
43
+ assert(type(raw.at(a)) == bool, message: a + " must be a boolean")
44
+ return raw.at(a)
45
+ }
46
+ }
47
+ }
48
+
49
+
50
+ #let validateAffiliation(raw) = {
51
+ let out = (:)
52
+ if (type(raw) == str) {
53
+ out.name = raw;
54
+ return out;
55
+ }
56
+ let id = validateString(raw, "id")
57
+ if (id != none) { out.id = id }
58
+ let name = validateString(raw, "name")
59
+ if (name != none) { out.name = name }
60
+ let institution = validateString(raw, "institution")
61
+ if (institution != none) { out.institution = institution }
62
+ let department = validateString(raw, "department")
63
+ if (department != none) { out.department = department }
64
+ let doi = validateString(raw, "doi")
65
+ if (doi != none) { out.doi = doi }
66
+ let ror = validateString(raw, "ror")
67
+ if (ror != none) { out.ror = ror }
68
+ let address = validateString(raw, "address")
69
+ if (address != none) { out.address = address }
70
+ let city = validateString(raw, "city")
71
+ if (city != none) { out.city = city }
72
+ let region = validateString(raw, "region", alias: ("state", "province"))
73
+ if (region != none) { out.region = region }
74
+ let postal-code = validateString(raw, "postal-code", alias: ("postal_code", "postalCode", "zip_code", "zip-code", "zipcode", "zipCode"))
75
+ if (postal-code != none) { out.postal-code = postal-code }
76
+ let country = validateString(raw, "country")
77
+ if (country != none) { out.country = country }
78
+ let phone = validateString(raw, "phone")
79
+ if (phone != none) { out.phone = phone }
80
+ let fax = validateString(raw, "fax")
81
+ if (fax != none) { out.fax = fax }
82
+ let email = validateString(raw, "email")
83
+ if (email != none) { out.email = email }
84
+ let url = validateString(raw, "url")
85
+ if (url != none) { out.url = url }
86
+ let collaboration = validateBoolean(raw, "collaboration")
87
+ if (collaboration != none) { out.collaboration = collaboration }
88
+ return out;
89
+ }
90
+
91
+ #let pickAffiliationsObject(raw) = {
92
+ if ("affiliation" in raw and "affiliations" in raw) {
93
+ panic("You can only use `affiliation` or `affiliations`, not both")
94
+ }
95
+ if ("affiliation" in raw) {
96
+ raw.affiliations = raw.affiliation
97
+ }
98
+ if ("affiliations" not in raw) { return; }
99
+ if (type(raw.affiliations) == str or type(raw.affiliations) == dictionary) {
100
+ // convert to a list
101
+ return (validateAffiliation(raw.affiliations),)
102
+ } else if (type(raw.affiliations) == array) {
103
+ // validate each entry
104
+ return raw.affiliations.map(validateAffiliation)
105
+ } else {
106
+ panic("The `affiliation` or `affiliations` must be a array, dictionary or string, got:", type(raw.affiliations))
107
+ }
108
+ }
109
+
110
+
111
+ #let validateAuthor(raw) = {
112
+ let out = (:)
113
+ if (type(raw) == str) {
114
+ out.name = raw;
115
+ return out;
116
+ }
117
+ let name = validateString(raw, "name")
118
+ if (name != none) { out.name = name }
119
+ let orcid = validateString(raw, "orcid")
120
+ if (orcid != none) { out.orcid = orcid }
121
+ let email = validateString(raw, "email")
122
+ if (email != none) { out.email = email }
123
+ let url = validateString(raw, "url")
124
+ if (url != none) { out.url = url }
125
+
126
+ let affiliations = pickAffiliationsObject(raw);
127
+ if (affiliations != none) { out.affiliations = affiliations } else { out.affiliations = () }
128
+
129
+ return out;
130
+ }
131
+
132
+ #let consolidateAffiliations(authors, affiliations) = {
133
+ let cnt = 0
134
+ for affiliation in affiliations {
135
+ if ("id" not in affiliation) {
136
+ affiliation.insert("id", "aff-" + str(cnt + 1))
137
+ }
138
+ affiliations.at(cnt) = affiliation
139
+ cnt += 1
140
+ }
141
+
142
+ let authorCnt = 0
143
+ for author in authors {
144
+ let affCnt = 0
145
+ for affiliation in author.affiliations {
146
+ let pos = affiliations.position(item => { ("id" in item and item.id == affiliation.name) or ("name" in item and item.name == affiliation.name) })
147
+ if (pos != none) {
148
+ affiliation.remove("name")
149
+ affiliation.id = affiliations.at(pos).id
150
+ affiliations.at(pos) = affiliations.at(pos) + affiliation
151
+ } else {
152
+ affiliation.id = if ("id" in affiliation) { affiliation.id } else { affiliation.name }
153
+ affiliations.push(affiliation)
154
+ }
155
+ author.affiliations.at(affCnt) = (id: affiliation.id)
156
+ affCnt += 1
157
+ }
158
+ authors.at(authorCnt) = author
159
+ authorCnt += 1
160
+ }
161
+
162
+ // Now that they are normalized, loop again and update the numbers
163
+ let fullAffCnt = 0
164
+ let authorCnt = 0
165
+ for author in authors {
166
+ let affCnt = 0
167
+ for affiliation in author.affiliations {
168
+ let pos = affiliations.position(item => { item.id == affiliation.id })
169
+ let aff = affiliations.at(pos)
170
+ if ("index" not in aff) {
171
+ fullAffCnt += 1
172
+ aff.index = fullAffCnt
173
+ affiliations.at(pos) = affiliations.at(pos) + (index: fullAffCnt)
174
+ }
175
+ author.affiliations.at(affCnt) = (id: affiliation.id, index: aff.index)
176
+ affCnt += 1
177
+ }
178
+ authors.at(authorCnt) = author
179
+ authorCnt += 1
180
+ }
181
+ return (authors: authors, affiliations: affiliations)
182
+ }
183
+
184
+ #let loadFrontmatter(raw) = {
185
+ let out = (:)
186
+ let title = validateString(raw, "title")
187
+ if (title != none) { out.title = title }
188
+ let subtitle = validateString(raw, "subtitle")
189
+ if (subtitle != none) { out.subtitle = subtitle }
190
+ let short-title = validateString(raw, "short-title", alias: ("short_title", "shortTitle", "runningHead",))
191
+ if (short-title != none) { out.short-title = short-title }
192
+
193
+ // author information
194
+ if ("author" in raw and "authors" in raw) {
195
+ panic("You can only use `author` or `authors`, not both")
196
+ }
197
+ if ("author" in raw) {
198
+ raw.authors = raw.author
199
+ }
200
+ if ("authors" in raw) {
201
+ if (type(raw.authors) == str or type(raw.authors) == dictionary) {
202
+ // convert to a list
203
+ out.authors = (validateAuthor(raw.authors),)
204
+ } else if (type(raw.authors) == array) {
205
+ // validate each entry
206
+ out.authors = raw.authors.map(validateAuthor)
207
+ } else {
208
+ panic("The `author` or `authors` must be a array, dictionary or string, got:", type(raw.authors))
209
+ }
210
+ }
211
+
212
+ let affiliations = pickAffiliationsObject(raw);
213
+ if (affiliations != none) { out.affiliations = affiliations } else { out.affiliations = () }
214
+
215
+ let open-access = validateBoolean(raw, "open-access", alias: ("open_access", "openAccess",))
216
+ if (open-access != none) { out.open-access = open-access }
217
+ let doi = validateString(raw, "doi")
218
+ if (doi != none) {
219
+ assert(not doi.starts-with("http"), message: "DOIs should not include the link, use only the part after `https://doi.org/[]`")
220
+ out.doi = doi
221
+ }
222
+
223
+ let date = none;
224
+ let citation = validateString(raw, "citation")
225
+ if (citation != none) {
226
+ out.citation = citation;
227
+ } else {
228
+ // Create a citation, e.g. Cockett et al., 2023
229
+ let year = if (date != none) { ", " + date.display("[year]") } else { ", " + datetime.today().display("[year]") }
230
+ if (out.authors.len() == 1) {
231
+ out.citation = out.authors.at(0).name.split(" ").last() + year
232
+ } else if (out.authors.len() == 2) {
233
+ out.citation = out.authors.at(0).name.split(" ").last() + " & " + out.authors.at(1).name.split(" ").last() + year
234
+ } else if (out.authors.len() > 2) {
235
+ out.citation = out.authors.at(0).name.split(" ").last() + " " + emph("et al.") + year
236
+ }
237
+ }
238
+
239
+ let consolidated = consolidateAffiliations(out.authors, out.affiliations)
240
+ out.authors = consolidated.authors
241
+ out.affiliations = consolidated.affiliations
242
+
243
+ return out
244
+ }
@@ -0,0 +1,310 @@
1
+ #import "frontmatter.typ": orcidLogo, loadFrontmatter
2
+
3
+ #let template(
4
+ // The paper's title.
5
+ title: "Paper Title",
6
+ subtitle: none,
7
+
8
+ // An array of authors. For each author you can specify a name, orcid, and affiliations.
9
+ // affiliations should be content, e.g. "1", which is shown in superscript and should match the affiliations list.
10
+ // Everything but but the name is optional.
11
+ authors: (),
12
+ // This is the affiliations list. Include an id and `name` in each affiliation. These are shown below the authors.
13
+ affiliations: (),
14
+ // The paper's abstract. Can be omitted if you don't have one.
15
+ abstract: none,
16
+ // The short-title is shown in the running header
17
+ short-title: none,
18
+ // The short-citation is shown in the running header, if set to auto it will show the author(s) and the year in APA format.
19
+ short-citation: auto,
20
+ // The venue is show in the footer
21
+ venue: none,
22
+ // An image path that is shown in the top right of the page. Can also be content.
23
+ logo: none,
24
+ // A DOI link, shown in the header on the first page. Should be just the DOI, e.g. `10.10123/123456` ,not a URL
25
+ doi: none,
26
+ heading-numbering: "1.a.i",
27
+ // Show an Open Access badge on the first page, and support open science, default is true, because that is what the default should be.
28
+ open-access: true,
29
+ // A list of keywords to display after the abstract
30
+ keywords: (),
31
+ // The "kind" of the content, e.g. "Original Research", this is shown as the title of the margin content on the first page.
32
+ kind: none,
33
+ // Content to put on the margin of the first page
34
+ // Should be a list of dicts with `title` and `content`
35
+ margin: (),
36
+ paper-size: "us-letter",
37
+ // A color for the theme of the document
38
+ theme: blue.darken(30%),
39
+ // Date published, for example, when you publish your preprint to an archive server.
40
+ // To hide the date, set this to `none`. You can also supply a list of dicts with `title` and `date`.
41
+ date: datetime.today(),
42
+ // Feel free to change this, the font applies to the whole document
43
+ font-face: none,
44
+ // The path to a bibliography file if you want to cite some external works.
45
+ bibliography-file: none,
46
+ bibliography-style: "apa",
47
+ // The paper's content.
48
+ body
49
+ ) = {
50
+ let spacer = text(fill: gray)[#h(8pt) | #h(8pt)]
51
+
52
+ let dates;
53
+ if (type(date) == datetime) {
54
+ dates = ((title: "Published", date: date),)
55
+ } else if (type(date) == dictionary) {
56
+ dates = (date,)
57
+ } else {
58
+ dates = date
59
+ }
60
+ date = dates.at(0).date
61
+
62
+ // Create a short-citation, e.g. Cockett et al., 2023
63
+ let year = if (date != none) { ", " + date.display("[year]") }
64
+ if (short-citation == auto and authors.len() == 1) {
65
+ short-citation = authors.at(0).name.split(" ").last() + year
66
+ } else if (short-citation == auto and authors.len() == 2) {
67
+ short-citation = authors.at(0).name.split(" ").last() + " & " + authors.at(1).name.split(" ").last() + year
68
+ } else if (short-citation == auto and authors.len() > 2) {
69
+ short-citation = authors.at(0).name.split(" ").last() + " " + emph("et al.") + year
70
+ } else if (short-citation == auto) {
71
+ short-citation = none
72
+ }
73
+
74
+ // Set document metadata.
75
+ set document(title: title, author: authors.map(author => author.name))
76
+
77
+ show link: it => [#text(fill: theme)[#it]]
78
+ show ref: it => [#text(fill: theme)[#it]]
79
+
80
+ set page(
81
+ paper-size,
82
+ margin: (left: 25%),
83
+ header: context {
84
+ let loc = here()
85
+ if(loc.page() == 1) {
86
+ let headers = (
87
+ if (open-access) {smallcaps[Open Access]},
88
+ if (doi != none) { link("https://doi.org/" + doi, "https://doi.org/" + doi)}
89
+ )
90
+ return align(left, text(size: 8pt, fill: gray, headers.filter(header => header != none).join(spacer)))
91
+ } else {
92
+ return align(right, text(size: 8pt, fill: gray.darken(50%),
93
+ (short-title, short-citation).join(spacer)
94
+ ))
95
+ }
96
+ },
97
+ footer: block(
98
+ width: 100%,
99
+ stroke: (top: 1pt + gray),
100
+ inset: (top: 8pt, right: 2pt),
101
+ context [
102
+ #grid(columns: (75%, 25%),
103
+ align(left, text(size: 9pt, fill: gray.darken(50%),
104
+ (
105
+ if(venue != none) {emph(venue)},
106
+ if(date != none) {date.display("[month repr:long] [day], [year]")}
107
+ ).filter(t => t != none).join(spacer)
108
+ )),
109
+ align(right)[
110
+ #text(
111
+ size: 9pt, fill: gray.darken(50%)
112
+ )[
113
+ #counter(page).display() of #counter(page).final().first()
114
+ ]
115
+ ]
116
+ )
117
+ ]
118
+ )
119
+ )
120
+
121
+ // Set the body font.
122
+ if (font-face != none) {
123
+ set text(font: font-face, size: 10pt)
124
+ } else {
125
+ set text(size: 10pt)
126
+ }
127
+ // Configure equation numbering and spacing.
128
+ set math.equation(numbering: "(1)")
129
+ show math.equation: set block(spacing: 1em)
130
+
131
+ // Configure lists.
132
+ set enum(indent: 10pt, body-indent: 9pt)
133
+ set list(indent: 10pt, body-indent: 9pt)
134
+
135
+ // Configure headings.
136
+ set heading(numbering: heading-numbering)
137
+ show heading: it => context {
138
+ let loc = here()
139
+ // Find out the final number of the heading counter.
140
+ let levels = counter(heading).at(loc)
141
+ set text(10pt, weight: 400)
142
+ if it.level == 1 [
143
+ // First-level headings are centered smallcaps.
144
+ // We don't want to number of the acknowledgment section.
145
+ #let is-ack = it.body in ([Acknowledgment], [Acknowledgement])
146
+ // #set align(center)
147
+ #set text(if is-ack { 10pt } else { 12pt })
148
+ #show: smallcaps
149
+ #v(20pt, weak: true)
150
+ #if it.numbering != none and not is-ack {
151
+ numbering(heading-numbering, ..levels)
152
+ [.]
153
+ h(7pt, weak: true)
154
+ }
155
+ #it.body
156
+ #v(13.75pt, weak: true)
157
+ ] else if it.level == 2 [
158
+ // Second-level headings are run-ins.
159
+ #set par(first-line-indent: 0pt)
160
+ #set text(style: "italic")
161
+ #v(10pt, weak: true)
162
+ #if it.numbering != none {
163
+ numbering(heading-numbering, ..levels)
164
+ [.]
165
+ h(7pt, weak: true)
166
+ }
167
+ #it.body
168
+ #v(10pt, weak: true)
169
+ ] else [
170
+ // Third level headings are run-ins too, but different.
171
+ #if it.level == 3 {
172
+ numbering(heading-numbering, ..levels)
173
+ [. ]
174
+ }
175
+ _#(it.body):_
176
+ ]
177
+ }
178
+
179
+
180
+ if (logo != none) {
181
+ place(
182
+ top,
183
+ dx: -33%,
184
+ float: false,
185
+ box(
186
+ width: 27%,
187
+ {
188
+ if (type(logo) == content) {
189
+ logo
190
+ } else {
191
+ image(logo, width: 100%)
192
+ }
193
+ },
194
+ ),
195
+ )
196
+ }
197
+
198
+
199
+ // Title and subtitle
200
+ box(inset: (bottom: 2pt), width: 100%, text(17pt, weight: "bold", fill: theme, title))
201
+ if subtitle != none {
202
+ parbreak()
203
+ box(width: 100%, text(14pt, fill: gray.darken(30%), subtitle))
204
+ }
205
+ // Authors and affiliations
206
+ if authors.len() > 0 {
207
+ box(inset: (y: 10pt), {
208
+ authors.map(author => {
209
+ text(11pt, weight: "semibold", author.name)
210
+ h(1pt)
211
+ if "affiliations" in author {
212
+ super(author.affiliations)
213
+ }
214
+ if "orcid" in author {
215
+ orcidLogo(orcid: author.orcid)
216
+ }
217
+ }).join(", ", last: ", and ")
218
+ })
219
+ }
220
+ if affiliations.len() > 0 {
221
+ box(inset: (bottom: 10pt), {
222
+ affiliations.map(affiliation => {
223
+ super(affiliation.id)
224
+ h(1pt)
225
+ affiliation.name
226
+ }).join(", ")
227
+ })
228
+ }
229
+
230
+
231
+ place(
232
+ left + bottom,
233
+ dx: -33%,
234
+ dy: -10pt,
235
+ box(width: 27%, {
236
+ if (kind != none) {
237
+ show par: set par(spacing: 0em)
238
+ text(11pt, fill: theme, weight: "semibold", smallcaps(kind))
239
+ parbreak()
240
+ }
241
+ if (dates != none) {
242
+ let formatted-dates
243
+
244
+ grid(columns: (40%, 60%), gutter: 7pt,
245
+ ..dates.zip(range(dates.len())).map((formatted-dates) => {
246
+ let d = formatted-dates.at(0);
247
+ let i = formatted-dates.at(1);
248
+ let weight = "light"
249
+ if (i == 0) {
250
+ weight = "bold"
251
+ }
252
+ return (
253
+ text(size: 7pt, fill: theme, weight: weight, d.title),
254
+ text(size: 7pt, d.date.display("[month repr:short] [day], [year]"))
255
+ )
256
+ }).flatten()
257
+ )
258
+ }
259
+ v(2em)
260
+ grid(columns: 1, gutter: 2em, ..margin.map(side => {
261
+ text(size: 7pt, {
262
+ if ("title" in side) {
263
+ text(fill: theme, weight: "bold", side.title)
264
+ [\ ]
265
+ }
266
+ set enum(indent: 0.1em, body-indent: 0.25em)
267
+ set list(indent: 0.1em, body-indent: 0.25em)
268
+ side.content
269
+ })
270
+ }))
271
+ }),
272
+ )
273
+
274
+
275
+ let abstracts
276
+ if (type(abstract) == content or type(abstract) == str) {
277
+ abstracts = ((title: "Abstract", content: abstract),)
278
+ } else {
279
+ abstracts = abstract
280
+ }
281
+
282
+ if (abstracts != none and abstracts.len() > 0) {
283
+ box(inset: (top: 16pt, bottom: 16pt), width: 100%, stroke: (top: 1pt + gray, bottom: 1pt + gray), {
284
+ abstracts.map(abs => {
285
+ set par(justify: true)
286
+ text(fill: theme, weight: "semibold", size: 9pt, abs.title)
287
+ parbreak()
288
+ abs.content
289
+ }).join(parbreak())
290
+ })
291
+ }
292
+ if (keywords.len() > 0) {
293
+ text(size: 9pt, {
294
+ text(fill: theme, weight: "semibold", "Keywords")
295
+ h(8pt)
296
+ keywords.join(", ")
297
+ })
298
+ }
299
+ v(10pt)
300
+
301
+ show par: set par(spacing: 1.5em)
302
+
303
+ // Display the paper's contents.
304
+ body
305
+
306
+ if (bibliography-file != none) {
307
+ show bibliography: set text(8pt)
308
+ bibliography(bibliography-file, title: text(10pt, "References"), style: bibliography-style)
309
+ }
310
+ }
@@ -0,0 +1,112 @@
1
+ #import "lapreprint.typ": *
2
+ #show: template.with(
3
+ title: "[-doc.title-]",
4
+ [# if parts.abstract or parts.summary #]
5
+ abstract: (
6
+ [# if parts.abstract #]
7
+ (
8
+ title: "Abstract",
9
+ content: [
10
+ [-parts.abstract-]
11
+ ]
12
+ ),
13
+ [# endif #]
14
+ [# if parts.summary #]
15
+ (
16
+ title: "Plain Language Summary",
17
+ content: [
18
+ [-parts.summary-]
19
+ ]
20
+ ),
21
+ [# endif #]
22
+ ),
23
+ [# endif #]
24
+ [# if doc.subtitle #]
25
+ subtitle: "[-doc.subtitle-]",
26
+ [# endif #]
27
+ [# if doc.short_title #]
28
+ short-title: "[-doc.short_title-]",
29
+ [# endif #]
30
+ [# if options.short_citation #]
31
+ short-citation: "[-options.short_citation-]",
32
+ [# endif #]
33
+ [# if options.heading_numbering #]
34
+ heading-numbering: "[-options.heading_numbering-]",
35
+ [# endif #]
36
+ [# if options.theme #]
37
+ theme: [-options.theme-],
38
+ [# endif #]
39
+ [# if doc.open_access !== undefined #]
40
+ open-access: [-doc.open_access-],
41
+ [# endif #]
42
+ [# if doc.doi #]
43
+ doi: "[-doc.doi-]",
44
+ [# endif #]
45
+ [# if doc.date #]
46
+ date: datetime(
47
+ year: [-doc.date.year-],
48
+ month: [-doc.date.month-],
49
+ day: [-doc.date.day-],
50
+ ),
51
+ [# endif #]
52
+ [# if doc.keywords #]
53
+ keywords: (
54
+ [#- for keyword in doc.keywords -#]"[-keyword-]",[#- endfor -#]
55
+ ),
56
+ [# endif #]
57
+ [# if doc.bibtex #]
58
+ bibliography-file: "[-doc.bibtex-]",
59
+ [# endif #]
60
+ authors: (
61
+ [# for author in doc.authors #]
62
+ (
63
+ name: "[-author.name-]",
64
+ [# if author.orcid #]
65
+ orcid: "[-author.orcid-]",
66
+ [# endif #]
67
+ [# if author.affiliations #]
68
+ affiliations: "[#- for aff in author.affiliations -#][-aff.index-][#- if not loop.last -#],[#- endif -#][#- endfor -#]",
69
+ [# endif #]
70
+ ),
71
+ [# endfor #]
72
+ ),
73
+ affiliations: (
74
+ [# for aff in doc.affiliations #]
75
+ (
76
+ id: "[-aff.index-]",
77
+ name: "[-aff.name-]",
78
+ ),
79
+ [# endfor #]
80
+ ),
81
+ [# if doc.venue.title #]
82
+ venue: "[-doc.venue.title-]",
83
+ [# endif #]
84
+ [# if options.logo #]
85
+ logo: "[-options.logo-]",
86
+ [# endif #]
87
+ [# if options.kind #]
88
+ kind: "[-options.kind-]",
89
+ [# endif #]
90
+ margin: (
91
+ [# if parts.acknowledgements #]
92
+ (
93
+ title: "Acknowledgements",
94
+ content: [
95
+ [-parts.acknowledgements-]
96
+ ],
97
+ ),
98
+ [# endif #]
99
+ [# if parts.availability #]
100
+ (
101
+ title: "Data Availability",
102
+ content: [
103
+ [-parts.availability-]
104
+ ],
105
+ ),
106
+ [# endif #]
107
+ ),
108
+ )
109
+
110
+ [-IMPORTS-]
111
+
112
+ [-CONTENT-]