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
30 changes: 30 additions & 0 deletions doc/manual.typ
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,36 @@ CTyp 包提供了以下预定义的字体集合:`fandol`, `fangzheng`, `source
[`..block-args`], [捕获所有其他传递到 `block` 函数的参数。], []
)]

== 列表编号设置

自 v0.3.0 版本起,使用 CTyp 包提供两个函数 `ItemLabel` 和 `EnumLabel` 可以实现对列表每级编号格式参数的设置。
这两个函数分别接受一个位置参数,设置符号或者编号格式。
此外,可以单独设置以下参数:

/ `width`: 列表编号的宽度。
/ `sep`: 编号与内容之间的间隔。
/ `alignment`: 编号的对齐方式。可选值为 `left`, `center`, `right`。

例如,可以通过以下代码设置编号列表的编号格式:

```typ
#let (theme, _) = ctyp(
fix-enum-args: (
numberer: (
EnumLabel("1.", width: 1em, alignment: left),
"a.",
EnumLabel("i)", width: 1em, alignment: right),
)
),
fix-list-args: (
marker: (
ItemLabel(sym.suit, width: 1em),
sym.dash
)
)
)
```

= 页面设置

#note-ctyp-func[page-grid][设置页芯大小,优先保证宽度为整字符数,避免过多分散对齐问题。]
Expand Down
2 changes: 1 addition & 1 deletion src/ctyp.typ
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#import "./fonts/index.typ": *
#import "./utils/enumitem.typ": enumitem
#import "./utils/enumitem.typ": enumitem, ItemLabel, EnumLabel
#import "./utils/page-grid.typ": page-grid
#import "./utils/heading-numbering.typ": _config-heading-numbering

Expand Down
4 changes: 4 additions & 0 deletions src/index.typ
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@
#import "utils/page-grid.typ": (
page-grid
)
#import "utils/enumitem.typ": (
ItemLabel,
EnumLabel,
)
122 changes: 88 additions & 34 deletions src/utils/enumitem.typ
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#import "@preview/elembic:1.1.1" as e: field, element, types

#let mod(x, y) = {
if x < y {
x
Expand All @@ -14,14 +16,72 @@
inset: (left: 0em)
)

#let ItemLabel = element.declare(
"ItemLabel",
prefix: "@preview/ctyp,v0.2.1",
fields: (
field("symbol", content, required: true),
field("width", length, default: 1em),
field("sep", length, default: 0em),
field("alignment", alignment, default: left),
field("stroke", types.option(stroke), default: none)
),
display: it => box(
width: it.width,
inset: (right: it.sep),
stroke: it.stroke,
align(it.alignment, it.symbol)
),
)

#let EnumLabel = element.declare(
"EnumLabel",
prefix: "@preview/ctyp,v0.2.1",
fields: (
field("numbering", str, required: true),
field("width", length, default: 1em),
field("sep", length, default: 0em),
field("alignment", alignment, default: left),
field("stroke", types.option(stroke), default: none),
field("body", content)
),
display: it => box(
width: it.width,
inset: (right: it.sep),
stroke: it.stroke,
align(it.alignment, it.body)
),
)

#let convert-content-to-marker(it) = {
let casted = e.types.cast(it, ItemLabel)
if casted.first() {
it
} else {
ItemLabel(it, width: 0.5em, sep: 0em, alignment: right)
}
}

#let convert-str-to-numberer(it) = {
if type(it) == str {
EnumLabel(it, width: 1.5em, sep: 0em, alignment: right)
} else {
it
}
}

#let default-list-markers = (sym.circle.filled, sym.triangle.r.filled, sym.square.filled).map(it => text(it, baseline: -.1em)).map(convert-content-to-marker)

#let default-enum-numberers = ("1)", "a)", "i.").map(convert-str-to-numberer)

/// 自定义列表和枚举布局,修复符号和文字不对齐的问题。
#let enumitem(
/// 符号列表可选用的符号。将循环使用。
/// -> array
marker: (sym.circle.filled, sym.triangle.r.filled, sym.dash),
marker: default-list-markers,
/// 编号列表可选用的编号格式。将循环使用。
/// -> array
numberer: ("1)", "a)", "i)"),
numberer: default-enum-numberers,
/// 是否使用紧凑布局。
/// 紧凑布局会使用 `par.leading` 作为列表项目之间的间隔,
/// 否则使用 `par.spacing`。
Expand Down Expand Up @@ -58,6 +118,8 @@
children
) = context {
let block-args = (:..default-block-args, ..block-args.named())
let marker = marker.map(convert-content-to-marker)
let numberer = numberer.map(convert-str-to-numberer)
show: block.with(..block-args)
let spacing = if spacing == auto {
if tight {
Expand All @@ -67,29 +129,24 @@
}
}
let item-template(
label-width: 1em,
label-sep: label-sep,
alignment: left,
label: [],
label,
body: []
) = block(
inset: (left: indent + label-width + body-indent),
stroke: if (debug) { green + 1pt } else { none },
above: spacing,
below: spacing,
{
set par(first-line-indent: (amount: 0em, all: true), hanging-indent: 0em)
box(
width: 0em,
move(box(
width: label-width,
inset: (right: label-sep),
stroke: if (debug) { red } else { none },
align(alignment, label)
), dx: - label-width - body-indent)
) + body
}
)
) = {
let label-width = e.fields(label).width
block(
inset: (left: indent + label-width + body-indent),
stroke: if (debug) { green + 1pt } else { none },
above: spacing,
below: spacing,
{
set par(first-line-indent: (amount: 0em, all: true), hanging-indent: 0em)
box(
width: 0em,
move(label, dx: - label-width - body-indent)
) + body
}
)
}
let queue = ((
marker: none,
body: []
Expand All @@ -106,7 +163,7 @@
while cur.at(0) < cur-max.at(0) {
if cur.at(depth) >= cur-max.at(depth) {
let qe = queue.pop()
queue.last().body += item-template(..qe)
queue.last().body += item-template(qe.label, body: qe.body)
let _ = cur.pop()
let _ = cur-max.pop()
if cur-type.len() > 0 {
Expand Down Expand Up @@ -153,7 +210,6 @@
if "children" in elem.body.fields() and elem.body.children.any(is-elem-item) {
queue.push((
label: label,
label-width: marker-width,
body: []
))
depth += 1
Expand All @@ -162,12 +218,11 @@
} else {
queue.push((
label: label,
label-width: marker-width,
body: elem.body
))
cur.at(depth) += 1
let qe = queue.pop()
queue.last().body += item-template(..qe)
queue.last().body += item-template(qe.label, body: qe.body)
}
} else if elem.func() == enum.item {
if cur-type.len() == 0 {
Expand All @@ -190,12 +245,13 @@
}
let number = cur-number.at(depth)
cur-number.at(depth) += 1
let label = numbering(numberer.at(cur-numberer), number)
let cur-numberer-fields = e.fields(numberer.at(cur-numberer))
let cur-numberer-template = cur-numberer-fields.remove("numbering")
let label-number = numbering(cur-numberer-template, number)
let label = EnumLabel(cur-numberer-template, ..cur-numberer-fields, body: label-number)
if "children" in elem.body.fields() and elem.body.children.any(is-elem-item) {
queue.push((
label: label,
label-width: number-width,
alignment: right,
body: []
))
depth += 1
Expand All @@ -204,13 +260,11 @@
} else {
queue.push((
label: label,
label-width: number-width,
alignment: right,
body: elem.body
))
cur.at(depth) += 1
let qe = queue.pop()
queue.last().body += item-template(..qe)
queue.last().body += item-template(qe.label, body: qe.body)
}
} else {
queue.last().body += elem
Expand Down
Binary file modified tests/core/ref/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/core/ref/4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/fix-list/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/fix-list/ref/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/fix-list/ref/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/fix-list/ref/5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions tests/fix-list/test.typ
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,32 @@
+ 项目2.3.3.1
+ 项目2.3.3.2
+ 项目2.3.3.2.1
]

#testcase[
#let (theme, _) = ctyp(
fix-enum-args: (
numberer: (
EnumLabel("1.", width: 1em, alignment: left),
"a.",
EnumLabel("i)", width: 1em, alignment: right),
)
),
fix-list-args: (
marker: (
ItemLabel(sym.suit, width: 1em),
sym.dash
)
)
)
#show: theme

= 设置编号格式

+ 测试
+ 测试
+ 测试

- 测试
- 测试
]