typst

First paragraph after block is not indented


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.


Solution

  • 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

    enter image description here