Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions packages/preview/fine-lncs/0.3.0/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2025 Johannes Zottele

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
74 changes: 74 additions & 0 deletions packages/preview/fine-lncs/0.3.0/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# fine-lncs

**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.

## Usage

```typst
#import "@preview/fine-lncs:0.3.0": lncs, institute, author, theorem, proof

#let inst_princ = institute("Princeton University",
addr: "Princeton NJ 08544, USA"
)
#let inst_springer = institute("Springer Heidelberg",
addr: "Tiergartenstr. 17, 69121 Heidelberg, Germany",
email: "[email protected]",
url: "http://www.springer.com/gp/computer-science/lncs"
)
#let inst_abc = institute("ABC Institute",
addr: "Rupert-Karls-University Heidelberg, Heidelberg, Germany",
email: "{abc,lncs}@uni-heidelberg.de"
)

#show: lncs.with(
title: "Contribution Title",
thanks: "Supported by organization x.",
authors: (
author("First Author",
insts: (inst_princ),
oicd: "0000-1111-2222-3333",
),
author("Second Author",
insts: (inst_springer, inst_abc),
oicd: "1111-2222-3333-4444",
),
author("Third Author",
insts: (inst_abc),
oicd: "2222-3333-4444-5555",
),
),
abstract: [
The abstract should briefly summarize the contents of the paper in
15--250 words.
],
keywords: ("First keyword", "Second keyword", "Another keyword"),
bibliography: bibliography("refs.bib")
)

= First Section

My awesome paper ...
```

### Local Usage

If you want to use this template locally, clone it and use [Typship](https://github.com/sjfhsjfh/typship) to install it using
```
typship install local
```
This allows you to import the template using
```
#import "@local/fine-lncs:0.3.0": lncs, institute, author, theorem, proof
```

## Development

To work on this template locally, use [Typship](https://github.com/sjfhsjfh/typship) to simplify development.
Use `typship dev` to setup a symlink of this library in the local preview package directory.

For testing, the project uses [tytanic](https://github.com/tingerrr/tytanic).
After installing `tytanic`, you can run all tests with:

```bash
tt run
```
282 changes: 282 additions & 0 deletions packages/preview/fine-lncs/0.3.0/src/lib.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
#import "theorem_proof_cnf.typ": *

// all theorem related elements
#let (
theorem,
__thm-rules,
definition,
__def-rules,
proposition,
__prop-rules,
lemma,
__lem-rules,
proof,
__proof-rules,
corollary,
__corol-rules,
) = __llncs_thm_cnf()


// The project function defines how your document looks.
// It takes your content and some metadata and formats it.
// Go ahead and customize it to your liking!
#let lncs(
title: [Contribution Title],
thanks: none,
abstract: [],
authors: (),
keywords: (),
// The result of a call to the `bibliography` function or `none`.
bibliography: none,
page-config: (:),
body,
) = {
//// CONSTANTS
let PAR_INDENT = 15pt
let TOP_PAGE_MARING = 50mm
let TITLE_SIZE = 14pt

// Set the document's basic properties.
set document(author: authors.map(a => a.name), title: title)
set text(font: "New Computer Modern", lang: "en", size: 10pt)


//// EVALUATIONS
let author_running = {
let an = authors.map(it => {
let ns = it.name.split(" ")
[#ns.at(0).at(0). #ns.last()]
})
if an.len() < 2 {
an.join(", ")
} else {
[#an.first() et al.]
}
}

//// PAR CONFIG
set par(leading: 0.50em, spacing: 0.4em)

//// PAGE CONFIG
set page(paper: "us-letter")
set page(margin: (left: 47.5mm, right: 44mm, top: TOP_PAGE_MARING, bottom: 45mm))
// set page header
set page(
header: context {
let pagenumer = counter(page).get().first()
if pagenumer == 1 { return [] }

if (calc.rem(pagenumer, 2) == 1) {
align(right)[
#title
#h(1cm)
#counter(page).display()
]
} else {
align(left)[
#counter(page).display()
#h(1cm)
#author_running
]
}
},
)
// apply custom page configs
set page(..page-config)

//// HEADING CONFIGS
set heading(numbering: "1.1")
show heading: it => if it.numbering == none { it } else { block(counter(heading).display(it.numbering) + h(4.5mm) + it.body) }
// padding
show heading.where(level: 1): pad.with(bottom: 0.45em, top: 0.64em)
show heading.where(level: 2): pad.with(bottom: 0.7em)
show heading: it => {
if it.level == 1 {
set text(12pt, weight: "bold")
it
} else if it.level == 2 {
set text(10pt, weight: "bold")
it
} else if it.level == 3 {
set text(10pt, weight: "bold")
[#v(2em)#h(-PAR_INDENT) #it.body]
} else if it.level == 4 {
set text(10pt, weight: "regular", style: "italic")
[#v(1.3em)#h(-PAR_INDENT)#it.body]
}
}


//// SUPER CONFIGS
set super(size: 8pt)

//// FOOTNOTE CONFIGS
show footnote.entry: set text(9pt)
show footnote.entry: it => pad(left: 1mm, top: 0mm, it)
set footnote.entry(separator: line(start: (10pt, 0pt), length: 57pt, stroke: 0.5pt))

///// FIGURE CONFIG
set figure.caption(separator: [. ]) // separator to .
show figure.caption: it => align(center)[*#it.supplement #context it.counter.display()#it.separator*#it.body] // bold figure kind
show figure.where(kind: table): set figure.caption(position: top) // caption for table above figure
show figure.where(kind: image): set image(width: 100%)
set figure(gap: 4.5mm)
show figure: pad.with(top: 20.5pt, bottom: 22pt)
show figure: set text(9pt)
show figure: align.with(left)
// let Figure display as Fig
let fig_replace(it) = {
show "Figure": "Fig."
it
}
show figure.where(kind: image): fig_replace
show ref: fig_replace

//// TABLE CONFIG
let table_stroke = 0.5pt
set table(stroke: (x, y) => (left: table_stroke, right: table_stroke))
set table(inset: (x: 0.7mm, y: 0.74mm))
set table.hline(stroke: table_stroke)


//// ---- Start of content -----

v(-9mm)

// Title row.
align(center)[
#block()[
#text(weight: "bold", TITLE_SIZE, title)
#if type(thanks) == str and thanks.trim() != "" {
set super(size: 10pt)
footnote(numbering: it => [⋆#h(2pt)], thanks)
}
]
]

v(8.5mm)

// encapsulated styling
{
set align(center)


let insts = authors.map(it => it.insts).flatten().dedup()

// Author information.

authors
.enumerate()
.map(it => {
let a = it.at(1)
// find references
let refs = a.insts.map(ai => str(insts.position(i => i == ai) + 1)).join(",")

let oicd = if a.oicd != none { [[#a.oicd]] } else { "" }

// add "and" infront of last author
let und = if it.at(0) > 0 and it.at(0) == authors.len() - 1 { "and" } else { "" }

[#und #a.name#super([#refs#oicd])]
})
.join(", ")

if authors.len() == 0 {
[ No Author Given]
}


v(3.6mm)

{ // Institute information.
set text(9pt)

insts
.enumerate()
.map(it => {
let inst = it.at(1)
[#super([#{ it.at(0) + 1 }]) ]
[#inst.name]
if inst.addr != none [, #inst.addr ]
linebreak()
if inst.email != none [#text(font: "New Computer Modern Mono", size: 9pt, inst.email) \ ]
if inst.url != none [#inst.url \ ]
})
.join()

if insts.len() == 0 {
[ No Institute Given]
}
}

v(10.7mm)


// abstract and keywords.
block(width: 104mm)[
#set align(left)
#set par(justify: true)
#set text(size: 9pt)
#if abstract != [] [
*Abstract.* #abstract
]
#if keywords.len() > 0 {
v(4.5mm)
let display = if type(keywords) == str { keywords } else { keywords.join([ $dot$ ]) }
text[*Keywords:* #display]
}
]
}

v(1mm)

// Main body.

//// PAR CONFIG MAIN
set par(justify: true, first-line-indent: PAR_INDENT)

// show theorem rules
show: __thm-rules
show: __def-rules
show: __prop-rules
show: __lem-rules
show: __proof-rules
show: __corol-rules

// show actual body
body

v(8pt)

// Style bibliography.
show std.bibliography: set text(9pt)
set std.bibliography(title: text(12pt)[References], style: "springer-lecture-notes-in-computer-science")

// Display bibliography.
bibliography
}

/// Author creation function
#let author(name, oicd: none, insts: ()) = {
// make sure it is always an one dimensional array
if type(insts) != array {
insts = (insts,)
}

(
name: name,
oicd: oicd,
insts: insts,
)
}


/// Institute creation function
#let institute(name, addr: none, email: none, url: none) = {
(
name: name,
addr: addr,
email: if email != none { link("mailto: " + email) } else { none },
url: if url != none { link(url) } else { none },
)
}
Loading