列表符号/编号和内容错位怎么办?
如果列表只写汉字
现象
若分别设置了中西字体,那么即使只写汉字,enum
或list
的符号/编号和内容也可能错位,例如下图:
typst
#set text(font: ((name: "New Computer Modern", covers: "latin-in-cjk"), "SimSun"))
= `enum`
+ 鲁镇的酒店的格局
= `list`
+ 鲁镇的酒店的格局

并且直接写编号完全正常:
typst
#[1.] 鲁镇的酒店的格局

已知存在问题的字体组合
- 西文:New Computer Modern / Libertinus Serif
- 中文:中易宋体/方正书宋/方正新书宋
法一:数字也用中文字体
typst
#set text(font: "SimSun")
+ 鲁镇的酒店的格局

法二:修改编号对齐方式
typst
#set text(font: ((name: "New Computer Modern", covers: "latin-in-cjk"), "SimSun"))
= `enum`
#set enum(number-align: bottom)
+ 鲁镇的酒店的格局
= `list`
#set list(marker: ([•], [‣], [–]).map(align.with(horizon)))
- 鲁镇的酒店的格局

法三:修改汉字边框计算方式
typst
#set text(font: ((name: "New Computer Modern", covers: "latin-in-cjk"), "SimSun"))
#set text(top-edge: "ascender", bottom-edge: "descender")
= `enum`
+ 鲁镇的酒店的格局
= `list`
- 鲁镇的酒店的格局

不过这样会在视觉上增大行距,详见文字外框的解释。
如果列表内容复杂
来自 @OrangeX4 的解决方案
typst
/// Align the list marker with the baseline of the first line of the list item.
///
/// Usage: `#show: align-list-marker-with-baseline`
#let align-list-marker-with-baseline(body) = {
show list.item: it => context {
let current-marker = {
set text(fill: text.fill)
if type(list.marker) == array {
list.marker.at(0)
} else {
list.marker
}
}
let hanging-indent = measure(current-marker).width + .6em + .3pt
set terms(hanging-indent: hanging-indent)
if type(list.marker) == array {
terms.item(
current-marker,
{
// set the value of list.marker in a loop
set list(marker: list.marker.slice(1) + (list.marker.at(0),))
it.body
},
)
} else {
terms.item(current-marker, it.body)
}
}
body
}
/// Align the enum marker with the baseline of the first line of the enum item. It will only work when the enum item has a number like `1.`.
///
/// Usage: `#show: align-enum-marker-with-baseline`
#let align-enum-marker-with-baseline(body) = {
show enum.item: it => context {
if not it.has("number") or it.number == none or enum.full == true {
// If the enum item does not have a number, or the number is none, or the enum is full
return it
}
let weight-map = (
thin: 100,
extralight: 200,
light: 300,
regular: 400,
medium: 500,
semibold: 600,
bold: 700,
extrabold: 800,
black: 900,
)
let current-marker = {
set text(
fill: text.fill,
weight: if type(text.weight) == int {
text.weight - 300
} else {
weight-map.at(text.weight) - 300
},
)
numbering(enum.numbering, it.number) + h(-.1em)
}
let hanging-indent = measure(current-marker).width + .6em + .3pt
set terms(hanging-indent: hanging-indent)
terms.item(current-marker, it.body)
}
body
}
#show: align-list-marker-with-baseline
#show: align-enum-marker-with-baseline
- 1 + $display(integral) + x$
- 1 + $display(integral)$
1. 1 + $display(integral) + x$
2. 1 + $display(integral)$
