Thanks for posing the questions, hopefully we can address all of them.
-
I don’t know what spacing you’re seeing after the em dash, a screenshot would help. The negative spaces you added to counteract them didn’t have effect, so I removed them.
As for counteracting the inline heading indentation caused by paragraphs, I swapped your
indentvariable forpar.first-line-indent.amount. Another solution worth considering: How can I prevent indent on paragraphs with run-in headings? -
That I also can’t reproduce. Isn’t kerning more like lacking whitespace?
-
I have added the conditionally-inserting period. You should be able to implement the conditionally-returning supplement similarly, otherwise feel free to ask.
-
Here’s what I’m seeing:
Less relevant changes:
-
Simplified use of modes.
-
Removed
it.numberingfromcounter(heading).display(it.numbering). -
Avoided too many
showrules for the same element. -
Acknowledged your code comment on preventing headings from becoming orphans:
- The docs there also say that
headingby default is ablockusingsticky: true. So when changingheadingviashow-setrules, we must also useblockto retain that behaviour. - But yes, I too don’t see how this could be applied to inline headings, because they’re not blocks and you’re not using them as inline headings everywhere. I assume you would want
Etc.---to stick to the following heading? Need need more help here.
- The docs there also say that
-
Swapped
widespaceforsym.space.figas your space was only a regular one. -
Swapped
snake_caseforkebab-caseas it’s the preferred styling.
New code:
Code
#set par(justify: true, first-line-indent: 1em, spacing: 0.6em)
#let body-size = 11pt
#set text(font: "New Computer Modern", size: body-size)
#set heading(numbering: "1.1." + sym.space.fig)
#show heading.where(level: 1): smallcaps
#show heading.where(level: 1): set align(center)
#show heading.where(level: 1): set text(size: 13pt, weight: "regular")
#let space-above-inline-heads = 1em
#show heading.where(level: 2): set text(size: body-size)
#show heading.where(level: 2): it => {
v(space-above-inline-heads)
h(-par.first-line-indent.amount)
counter(heading).display()
it.body
if it.body.text.last() not in (".", "?", "!") { "." }
"---"
}
#show heading.where(level: 3): set text(size: body-size, weight: "regular")
#show heading.where(level: 3): it => {
v(space-above-inline-heads)
h(-par.first-line-indent.amount)
emph({
counter(heading).display()
it.body
if it.body.text.last() not in (".", "?", "!") { "." }
"---"
})
}
// Clever trick to reduce spacing between consecutive headings
// See https://github.com/typst/typst/issues/2953#issuecomment-3187505828
#show heading: it => {
let previous-headings = query(selector(heading).before(here(), inclusive: false))
if previous-headings.len() > 0 {
let ploc = previous-headings.last().location().position()
let iloc = it.location().position()
if (iloc.page == ploc.page and iloc.x == ploc.x and iloc.y - ploc.y < 30pt) { // Threshold
v(-10pt) // Amount to reduce spacing, could make this dependent on it.level
}
}
it
}
= Introduction
#lorem(25)
#lorem(15)
== Motivation
#lorem(20)
=== Subsubsection
#lorem(15)
== Etc.
=== Subsubsection
#lorem(20)

