Skip to content

Commit ee5ad1a

Browse files
authored
fine-lncs:0.3.0 (#3300)
1 parent 3fd7715 commit ee5ad1a

File tree

9 files changed

+617
-0
lines changed

9 files changed

+617
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Johannes Zottele
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.
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# fine-lncs
2+
3+
**fine-lncs** is a [Typst](https://typst.app) template that tries to closely replicate the look and structure of the official [Springer LNCS (Lecture Notes in Computer Science)](https://www.overleaf.com/latex/templates/springer-lecture-notes-in-computer-science/kzwwpvhwnvfj#.WuA4JS5uZpi) LaTeX template.
4+
5+
## Usage
6+
7+
```typst
8+
#import "@preview/fine-lncs:0.3.0": lncs, institute, author, theorem, proof
9+
10+
#let inst_princ = institute("Princeton University",
11+
addr: "Princeton NJ 08544, USA"
12+
)
13+
#let inst_springer = institute("Springer Heidelberg",
14+
addr: "Tiergartenstr. 17, 69121 Heidelberg, Germany",
15+
16+
url: "http://www.springer.com/gp/computer-science/lncs"
17+
)
18+
#let inst_abc = institute("ABC Institute",
19+
addr: "Rupert-Karls-University Heidelberg, Heidelberg, Germany",
20+
email: "{abc,lncs}@uni-heidelberg.de"
21+
)
22+
23+
#show: lncs.with(
24+
title: "Contribution Title",
25+
thanks: "Supported by organization x.",
26+
authors: (
27+
author("First Author",
28+
insts: (inst_princ),
29+
oicd: "0000-1111-2222-3333",
30+
),
31+
author("Second Author",
32+
insts: (inst_springer, inst_abc),
33+
oicd: "1111-2222-3333-4444",
34+
),
35+
author("Third Author",
36+
insts: (inst_abc),
37+
oicd: "2222-3333-4444-5555",
38+
),
39+
),
40+
abstract: [
41+
The abstract should briefly summarize the contents of the paper in
42+
15--250 words.
43+
],
44+
keywords: ("First keyword", "Second keyword", "Another keyword"),
45+
bibliography: bibliography("refs.bib")
46+
)
47+
48+
= First Section
49+
50+
My awesome paper ...
51+
```
52+
53+
### Local Usage
54+
55+
If you want to use this template locally, clone it and use [Typship](https://github.com/sjfhsjfh/typship) to install it using
56+
```
57+
typship install local
58+
```
59+
This allows you to import the template using
60+
```
61+
#import "@local/fine-lncs:0.3.0": lncs, institute, author, theorem, proof
62+
```
63+
64+
## Development
65+
66+
To work on this template locally, use [Typship](https://github.com/sjfhsjfh/typship) to simplify development.
67+
Use `typship dev` to setup a symlink of this library in the local preview package directory.
68+
69+
For testing, the project uses [tytanic](https://github.com/tingerrr/tytanic).
70+
After installing `tytanic`, you can run all tests with:
71+
72+
```bash
73+
tt run
74+
```
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
#import "theorem_proof_cnf.typ": *
2+
3+
// all theorem related elements
4+
#let (
5+
theorem,
6+
__thm-rules,
7+
definition,
8+
__def-rules,
9+
proposition,
10+
__prop-rules,
11+
lemma,
12+
__lem-rules,
13+
proof,
14+
__proof-rules,
15+
corollary,
16+
__corol-rules,
17+
) = __llncs_thm_cnf()
18+
19+
20+
// The project function defines how your document looks.
21+
// It takes your content and some metadata and formats it.
22+
// Go ahead and customize it to your liking!
23+
#let lncs(
24+
title: [Contribution Title],
25+
thanks: none,
26+
abstract: [],
27+
authors: (),
28+
keywords: (),
29+
// The result of a call to the `bibliography` function or `none`.
30+
bibliography: none,
31+
page-config: (:),
32+
body,
33+
) = {
34+
//// CONSTANTS
35+
let PAR_INDENT = 15pt
36+
let TOP_PAGE_MARING = 50mm
37+
let TITLE_SIZE = 14pt
38+
39+
// Set the document's basic properties.
40+
set document(author: authors.map(a => a.name), title: title)
41+
set text(font: "New Computer Modern", lang: "en", size: 10pt)
42+
43+
44+
//// EVALUATIONS
45+
let author_running = {
46+
let an = authors.map(it => {
47+
let ns = it.name.split(" ")
48+
[#ns.at(0).at(0). #ns.last()]
49+
})
50+
if an.len() < 2 {
51+
an.join(", ")
52+
} else {
53+
[#an.first() et al.]
54+
}
55+
}
56+
57+
//// PAR CONFIG
58+
set par(leading: 0.50em, spacing: 0.4em)
59+
60+
//// PAGE CONFIG
61+
set page(paper: "us-letter")
62+
set page(margin: (left: 47.5mm, right: 44mm, top: TOP_PAGE_MARING, bottom: 45mm))
63+
// set page header
64+
set page(
65+
header: context {
66+
let pagenumer = counter(page).get().first()
67+
if pagenumer == 1 { return [] }
68+
69+
if (calc.rem(pagenumer, 2) == 1) {
70+
align(right)[
71+
#title
72+
#h(1cm)
73+
#counter(page).display()
74+
]
75+
} else {
76+
align(left)[
77+
#counter(page).display()
78+
#h(1cm)
79+
#author_running
80+
]
81+
}
82+
},
83+
)
84+
// apply custom page configs
85+
set page(..page-config)
86+
87+
//// HEADING CONFIGS
88+
set heading(numbering: "1.1")
89+
show heading: it => if it.numbering == none { it } else { block(counter(heading).display(it.numbering) + h(4.5mm) + it.body) }
90+
// padding
91+
show heading.where(level: 1): pad.with(bottom: 0.45em, top: 0.64em)
92+
show heading.where(level: 2): pad.with(bottom: 0.7em)
93+
show heading: it => {
94+
if it.level == 1 {
95+
set text(12pt, weight: "bold")
96+
it
97+
} else if it.level == 2 {
98+
set text(10pt, weight: "bold")
99+
it
100+
} else if it.level == 3 {
101+
set text(10pt, weight: "bold")
102+
[#v(2em)#h(-PAR_INDENT) #it.body]
103+
} else if it.level == 4 {
104+
set text(10pt, weight: "regular", style: "italic")
105+
[#v(1.3em)#h(-PAR_INDENT)#it.body]
106+
}
107+
}
108+
109+
110+
//// SUPER CONFIGS
111+
set super(size: 8pt)
112+
113+
//// FOOTNOTE CONFIGS
114+
show footnote.entry: set text(9pt)
115+
show footnote.entry: it => pad(left: 1mm, top: 0mm, it)
116+
set footnote.entry(separator: line(start: (10pt, 0pt), length: 57pt, stroke: 0.5pt))
117+
118+
///// FIGURE CONFIG
119+
set figure.caption(separator: [. ]) // separator to .
120+
show figure.caption: it => align(center)[*#it.supplement #context it.counter.display()#it.separator*#it.body] // bold figure kind
121+
show figure.where(kind: table): set figure.caption(position: top) // caption for table above figure
122+
show figure.where(kind: image): set image(width: 100%)
123+
set figure(gap: 4.5mm)
124+
show figure: pad.with(top: 20.5pt, bottom: 22pt)
125+
show figure: set text(9pt)
126+
show figure: align.with(left)
127+
// let Figure display as Fig
128+
let fig_replace(it) = {
129+
show "Figure": "Fig."
130+
it
131+
}
132+
show figure.where(kind: image): fig_replace
133+
show ref: fig_replace
134+
135+
//// TABLE CONFIG
136+
let table_stroke = 0.5pt
137+
set table(stroke: (x, y) => (left: table_stroke, right: table_stroke))
138+
set table(inset: (x: 0.7mm, y: 0.74mm))
139+
set table.hline(stroke: table_stroke)
140+
141+
142+
//// ---- Start of content -----
143+
144+
v(-9mm)
145+
146+
// Title row.
147+
align(center)[
148+
#block()[
149+
#text(weight: "bold", TITLE_SIZE, title)
150+
#if type(thanks) == str and thanks.trim() != "" {
151+
set super(size: 10pt)
152+
footnote(numbering: it => [⋆#h(2pt)], thanks)
153+
}
154+
]
155+
]
156+
157+
v(8.5mm)
158+
159+
// encapsulated styling
160+
{
161+
set align(center)
162+
163+
164+
let insts = authors.map(it => it.insts).flatten().dedup()
165+
166+
// Author information.
167+
168+
authors
169+
.enumerate()
170+
.map(it => {
171+
let a = it.at(1)
172+
// find references
173+
let refs = a.insts.map(ai => str(insts.position(i => i == ai) + 1)).join(",")
174+
175+
let oicd = if a.oicd != none { [[#a.oicd]] } else { "" }
176+
177+
// add "and" infront of last author
178+
let und = if it.at(0) > 0 and it.at(0) == authors.len() - 1 { "and" } else { "" }
179+
180+
[#und #a.name#super([#refs#oicd])]
181+
})
182+
.join(", ")
183+
184+
if authors.len() == 0 {
185+
[ No Author Given]
186+
}
187+
188+
189+
v(3.6mm)
190+
191+
{ // Institute information.
192+
set text(9pt)
193+
194+
insts
195+
.enumerate()
196+
.map(it => {
197+
let inst = it.at(1)
198+
[#super([#{ it.at(0) + 1 }]) ]
199+
[#inst.name]
200+
if inst.addr != none [, #inst.addr ]
201+
linebreak()
202+
if inst.email != none [#text(font: "New Computer Modern Mono", size: 9pt, inst.email) \ ]
203+
if inst.url != none [#inst.url \ ]
204+
})
205+
.join()
206+
207+
if insts.len() == 0 {
208+
[ No Institute Given]
209+
}
210+
}
211+
212+
v(10.7mm)
213+
214+
215+
// abstract and keywords.
216+
block(width: 104mm)[
217+
#set align(left)
218+
#set par(justify: true)
219+
#set text(size: 9pt)
220+
#if abstract != [] [
221+
*Abstract.* #abstract
222+
]
223+
#if keywords.len() > 0 {
224+
v(4.5mm)
225+
let display = if type(keywords) == str { keywords } else { keywords.join([ $dot$ ]) }
226+
text[*Keywords:* #display]
227+
}
228+
]
229+
}
230+
231+
v(1mm)
232+
233+
// Main body.
234+
235+
//// PAR CONFIG MAIN
236+
set par(justify: true, first-line-indent: PAR_INDENT)
237+
238+
// show theorem rules
239+
show: __thm-rules
240+
show: __def-rules
241+
show: __prop-rules
242+
show: __lem-rules
243+
show: __proof-rules
244+
show: __corol-rules
245+
246+
// show actual body
247+
body
248+
249+
v(8pt)
250+
251+
// Style bibliography.
252+
show std.bibliography: set text(9pt)
253+
set std.bibliography(title: text(12pt)[References], style: "springer-lecture-notes-in-computer-science")
254+
255+
// Display bibliography.
256+
bibliography
257+
}
258+
259+
/// Author creation function
260+
#let author(name, oicd: none, insts: ()) = {
261+
// make sure it is always an one dimensional array
262+
if type(insts) != array {
263+
insts = (insts,)
264+
}
265+
266+
(
267+
name: name,
268+
oicd: oicd,
269+
insts: insts,
270+
)
271+
}
272+
273+
274+
/// Institute creation function
275+
#let institute(name, addr: none, email: none, url: none) = {
276+
(
277+
name: name,
278+
addr: addr,
279+
email: if email != none { link("mailto: " + email) } else { none },
280+
url: if url != none { link(url) } else { none },
281+
)
282+
}

0 commit comments

Comments
 (0)