main
1#import "../utils/invisible-heading.typ": invisible-heading
2#import "../utils/style.typ": 字体, 字号
3#import "@preview/numbly:0.1.0": numbly
4
5// 本科生英文目录
6#let bachelor-outline-page-en(
7 // documentclass 传入参数
8 twoside: false,
9 fonts: (:),
10 // 其他参数
11 depth: 3,
12 title: "Contents",
13 entry-numbering: ("Chapter {1}",),
14 outlined: false,
15 title-vspace: 14pt,
16 title-text-args: auto,
17 // 引用页码字体与字号
18 reference-font: auto,
19 reference-size: 字号.小四,
20 // 字体与字号
21 font: auto,
22 size: (字号.四号, 字号.小四),
23 weight: ("bold", "bold", "regular"),
24 // 目录样式
25 above: (20pt, 14pt),
26 below: (14pt, 14pt),
27 indent: (0pt, 18pt, 28pt),
28 fill: (repeat([.], gap: 0.15em),),
29 gap: .3em,
30) = {
31 // 1. 默认参数
32 fonts = 字体 + fonts
33 if title-text-args == auto {
34 title-text-args = (font: fonts.宋体, size: 字号.小三, weight: "bold")
35 }
36 if reference-font == auto {
37 reference-font = fonts.宋体
38 }
39 if font == auto {
40 font = (fonts.宋体, fonts.宋体, fonts.宋体)
41 }
42
43 // 2. 正式渲染
44 pagebreak(weak: true, to: if twoside { "odd" })
45
46 // 默认显示的字体
47 set text(font: reference-font, size: reference-size)
48
49 {
50 set align(center)
51 text(..title-text-args, title)
52 // 标记一个不可见的标题用于目录生成
53 invisible-heading(level: 1, outlined: outlined, title)
54 }
55
56 v(title-vspace)
57
58 // 目录样式
59 set outline(indent: level => indent
60 .slice(0, calc.min(level + 1, indent.len()))
61 .sum())
62 show outline.entry: entry => block(
63 above: above.at(entry.level - 1, default: above.last()),
64 below: below.at(entry.level - 1, default: below.last()),
65 link(
66 entry.element.location(),
67 entry.indented(
68 none,
69 {
70 text(
71 font: font.at(entry.level - 1, default: font.last()),
72 size: size.at(entry.level - 1, default: size.last()),
73 weight: weight.at(entry.level - 1, default: weight.last()),
74 {
75 if (
76 entry.prefix() not in (none, [])
77 and entry.element.numbering != none
78 ) {
79 let enentry-numbering-len = entry-numbering.len()
80 let used-numbering = if (
81 entry.element.level <= enentry-numbering-len
82 ) {
83 numbly(..entry-numbering)
84 } else {
85 entry.element.numbering
86 }
87 numbering(
88 used-numbering,
89 ..counter(outline.target).at(entry.element.location()),
90 )
91 h(gap)
92 }
93 {
94 let body = entry.body()
95 assert(
96 body.fields().keys().contains("children"),
97 message: "论文标题应在最后添加 `#metadata((en: \"英文标题\"))`",
98 )
99 let meta = body.children.last()
100 assert(
101 repr(meta).starts-with("metadata"),
102 message: "论文标题应在最后添加 `#metadata((en: \"英文标题\"))`",
103 )
104 assert(
105 meta.value.keys().contains("en"),
106 message: "论文标题应在最后添加 `#metadata((en: \"英文标题\"))`",
107 )
108 meta.value.en
109 }
110 },
111 )
112 box(width: 1fr, inset: (x: .25em), fill.at(
113 entry.level - 1,
114 default: fill.last(),
115 ))
116 entry.page()
117 },
118 gap: 0pt,
119 ),
120 ),
121 )
122
123 // 显示目录
124 outline(title: none, depth: depth)
125}