feat(template): themed blockquotes, references, chapter-based numbering for textbook
- Add themed blockquote styles (课堂小实验, 关键洞察, etc.) via quote block - Add #references() wrapper for bibliography formatting - Implement chapter-based figure/table numbering (1-1, 2-1, ...) - Start each chapter on a new page (except first) - Increase list spacing to match long-form reading rhythm - Fix first-line indent to apply on all paragraphs
This commit is contained in:
@@ -5,6 +5,51 @@
|
||||
#import "@preview/codly:1.3.0": *
|
||||
#import "@preview/showybox:2.0.4": showybox
|
||||
|
||||
// ── helpers ──────────────────────────────────────────────────────────────
|
||||
|
||||
#let content-to-string(content) = {
|
||||
if content.has("text") {
|
||||
content.text
|
||||
} else if content.has("children") {
|
||||
content.children.map(content-to-string).join("")
|
||||
} else if content.has("body") {
|
||||
content-to-string(content.body)
|
||||
} else if content == [ ] {
|
||||
" "
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
// ── blockquote themes ────────────────────────────────────────────────────
|
||||
|
||||
#let blockquote-themes = (
|
||||
("课堂小实验", rgb("#F0FDF4"), rgb("#16A34A")),
|
||||
("关键洞察", rgb("#FFFBEB"), rgb("#D97706")),
|
||||
("工程警示", rgb("#FEF2F2"), rgb("#DC2626")),
|
||||
("前沿瞭望", rgb("#F3E8FF"), rgb("#9333EA")),
|
||||
("历史视角", rgb("#FEF3C7"), rgb("#B45309")),
|
||||
("你知道吗", rgb("#ECFEFF"), rgb("#0891B2")),
|
||||
)
|
||||
|
||||
#let themed-blockquote(body) = {
|
||||
let body-str = content-to-string(body)
|
||||
let theme = blockquote-themes.find(t => body-str.contains(t.at(0)))
|
||||
let (fill-color, stroke-color) = if theme != none {
|
||||
(theme.at(1), theme.at(2))
|
||||
} else {
|
||||
(rgb("#F1F5F9"), rgb("#64748B"))
|
||||
}
|
||||
block(
|
||||
fill: fill-color,
|
||||
stroke: (left: 4pt + stroke-color),
|
||||
inset: (x: 14pt, y: 10pt),
|
||||
radius: (right: 4pt),
|
||||
spacing: 1.2em,
|
||||
body,
|
||||
)
|
||||
}
|
||||
|
||||
#let primary = rgb("#1F4E79")
|
||||
#let secondary = rgb("#2C3E50")
|
||||
#let accent = rgb("#3467A8")
|
||||
@@ -92,6 +137,20 @@
|
||||
table(..new_children, ..kwargs)
|
||||
}
|
||||
|
||||
// Reference-list block: smaller text, hanging indent, tighter rhythm.
|
||||
// Wrap a 参考文献 / References section's body via `#references[ ... ]`.
|
||||
#let references(body) = block({
|
||||
set text(size: 9.5pt)
|
||||
set par(
|
||||
justify: true,
|
||||
leading: 0.7em,
|
||||
spacing: 0.6em,
|
||||
first-line-indent: 0pt,
|
||||
hanging-indent: 1.5em,
|
||||
)
|
||||
body
|
||||
})
|
||||
|
||||
#let textbook(
|
||||
title: none,
|
||||
subtitle: none,
|
||||
@@ -124,7 +183,7 @@
|
||||
justify: true,
|
||||
leading: 0.86em,
|
||||
spacing: 1.2em,
|
||||
first-line-indent: 2em,
|
||||
first-line-indent: (amount: 2em, all: true),
|
||||
)
|
||||
|
||||
show: codly-init
|
||||
@@ -140,12 +199,29 @@
|
||||
show: great-theorems-init
|
||||
set heading(numbering: "1.1")
|
||||
|
||||
// Same 11pt body as default: match list rhythm to default template
|
||||
set list(indent: 1.2em, body-indent: 0.45em, spacing: 0.62em)
|
||||
set enum(indent: 1.2em, body-indent: 0.45em, spacing: 0.62em)
|
||||
// 按章编号:每章开始时重置图片/表格计数器
|
||||
set figure(numbering: (..nums) => {
|
||||
let h = counter(heading).get()
|
||||
let ch = if h.len() > 0 { h.first() } else { 1 }
|
||||
numbering("1-1", ch, nums.pos().first())
|
||||
})
|
||||
|
||||
// List rhythm: spacing ≥ leading (0.86em), slightly looser than body for long-form reading
|
||||
set list(indent: 1.2em, body-indent: 0.45em, spacing: 0.98em)
|
||||
set enum(indent: 1.2em, body-indent: 0.45em, spacing: 0.98em)
|
||||
|
||||
// 每章从新页开始(第一章除外,因为前面已有 pagebreak)
|
||||
let first-chapter = state("first-chapter", true)
|
||||
|
||||
// Vertical rhythm matches manual (long-form); font sizes differ
|
||||
show heading.where(level: 1): it => {
|
||||
counter(figure.where(kind: image)).update(0)
|
||||
counter(figure.where(kind: table)).update(0)
|
||||
|
||||
context if not first-chapter.get() {
|
||||
pagebreak()
|
||||
}
|
||||
first-chapter.update(false)
|
||||
|
||||
v(1.45em)
|
||||
text(size: 18pt, weight: "bold", fill: primary, it)
|
||||
v(0.55em)
|
||||
@@ -163,6 +239,9 @@
|
||||
v(0.4em)
|
||||
}
|
||||
|
||||
// Blockquote → themed block
|
||||
show quote.where(block: true): it => themed-blockquote(it.body)
|
||||
|
||||
set page(
|
||||
paper: "a4",
|
||||
margin: (top: 2.5cm, bottom: 2.5cm, left: 2.5cm, right: 2.5cm),
|
||||
|
||||
Reference in New Issue
Block a user