I am brand new to Typst, and I am trying to format a novel such that chapter titles occupy half a page, with the chapter title and number vertically centred in that block.
I have defined a function (in chapter.typ
):
#let c = counter("chaptercounter")
#let chapter(title: str, body) = {
c.step()
layout(size => {
block(
height:size.height/2,
width:size.width,
[
#align(center + horizon)[
#heading(
text(
[
#smallcaps(title)
],
weight:"regular",
size:16pt),
level:1
)
]
#align(center)[
#heading(
text(
[
#smallcaps(
[
Chapter #context(
c.display()
)
]
)
],
weight:"regular",
size:14pt
),
level:2
)
]
],
)
})
body
}
Which is then called like this to make a chapter:
#import "../chapter.typ": chapter
#show: chapter.with(title: "TITLE")
Paragraph 1
Paragraph 2
And in the main file I have set:
#set par(justify: true, first-line-indent: 2em)
#let c = counter("chaptercounter")
This leads to two questions:
Firstly, am I defining the counter properly, by having counter("chaptercounter")
both in the main file and in the chapter.typ
file? It works, but it feels a bit off.
Secondly, and more importantly, the first paragraph is not intended, while the rest are. In the example above Paragraph 1
is not indented, but Paragraph 2
is. I would like them both to be indented.
Welcome to typst! The conventional style is to use formatting templates instead of functions for what you're attempting:
#let template(body) = {
// Heading styling
set heading(numbering: "1", supplement: "Chapter")
show heading: it => {
set text(weight: "regular")
layout(size => context {
block(height: size.height / 2, width: size.width)[
#set align(center + horizon)
#set text(16pt)
#smallcaps(it.body)
#set text(14pt)
#smallcaps[#it.supplement #counter(heading).display()]
]
})
}
// Body styling
set par(justify: true, first-line-indent: (amount: 2em, all: true))
// User's content
body
}
// Apply heading/body styling as needed to all text below
#show: template
= A Chapter Title
#lorem(100)
#lorem(100)
= The Next One
#lorem(100)
#lorem(100)
Since you're already using headings to display chapter titles, this way the title is automatically inferred from the heading's value -- no need to pass a title
separately. You can read more about templates here.
As for indenting, the docs here clarify that you can pass a dict of (amount: 2em, all: true)
to indent everything