diff --git a/packages/preview/modern-cqut-thesis/0.1.0/.gitignore b/packages/preview/modern-cqut-thesis/0.1.0/.gitignore
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/.gitignore
@@ -0,0 +1 @@
+
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/LICENSE b/packages/preview/modern-cqut-thesis/0.1.0/LICENSE
new file mode 100644
index 000000000..12b814ad8
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2024 aFei-CQUT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/README.md b/packages/preview/modern-cqut-thesis/0.1.0/README.md
new file mode 100644
index 000000000..28124976d
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/README.md
@@ -0,0 +1,86 @@
+# 重庆理工大学学位论文
+
+重庆理工大学毕业论文(设计)的 Typst 模板,能够简洁、快速、持续生成 PDF 格式的毕业论文。
+
+需要注意的是我们没有提供线上的模板(复习时间有点紧张…),但是你不要紧张!本地编辑不需要线上模板,如果你需要@preview的话,请运行`bat`或者`py`脚本。
+
+## 使用
+
+**只需修改 `thesis.typ` 文件即可,基本可以满足你的所有需求。**
+
+## 平台
+
+1. 在 VS Code 中安装 [Tinymist Typst](https://marketplace.visualstudio.com/items?itemName=myriad-dreamin.tinymist) 和 [Typst Preview](https://marketplace.visualstudio.com/items?itemName=mgt19937.typst-preview) 插件。前者负责语法高亮和错误检查等功能,后者负责预览。
+ - 推荐下载 [Typst Companion](https://marketplace.visualstudio.com/items?itemName=CalebFiggers.typst-companion) 插件,其提供了例如 `Ctrl + B` 进行加粗等便捷的快捷键。
+ - 你还可以下载 [Typst Sync](https://marketplace.visualstudio.com/items?itemName=OrangeX4.vscode-typst-sync) 和 [Typst Sympy Calculator](https://marketplace.visualstudio.com/items?itemName=OrangeX4.vscode-typst-sympy-calculator) 插件,前者提供了本地包的云同步功能,后者提供了基于 Typst 语法的科学计算器功能。
+3. 用 VS Code 打开生成的目录,打开 `thesis.typ` 文件,并按下 `Ctrl + K V` 进行实时编辑和预览。
+
+
+## 开发者指南
+
+### template 目录
+
+- `thesis.typ` 文件: 你的论文源文件,可以随意更改这个文件的名字,甚至你可以将这个文件在同级目录下复制多份,维持多个版本。
+- `thesis.bib` 文件: 用于放置参考文献。
+- `logos` 目录: 用于放置logo的文件夹。
+
+
+### 内部目录
+
+1. `utils` 目录: 包含了模板使用到的各种自定义辅助函数,存放没有外部依赖,且 **不会渲染出页面的函数**。
+2. `pages` 目录: 包含了模板用到的各个 **独立页面**,例如封面页、声明页、摘要等,即 **会渲染出不影响其他页面的独立页面的函数**。
+3. `layouts` 目录: 布局目录,存放着用于排篇布局的、应用于 `show` 指令的、**横跨多个页面的函数**,例如为了给页脚进行罗马数字编码的前言 `preface` 函数。
+ - 主要分成了 `doc` 文稿、`preface` 前言、`mainmatter` 正文与 `appendix` 附录/后记。
+4. `lib.typ`:
+ - **职责一**: 作为一个统一的对外接口,暴露出内部的 utils 函数。
+ - **职责二**: 使用 **函数闭包** 特性,通过 `documentclass` 函数类进行全局信息配置,然后暴露出拥有了全局配置的、具体的 `layouts` 和 `pages` 内部函数。
+
+### TodoList
+
+- **说明文档**
+ - [ ] 编写更详细的说明文档,后续考虑使用 [tidy](https://github.com/typst/packages/tree/main/packages/preview/tidy/0.1.0) 编写,你现在可以先参考 [NJUThesis](https://mirror-hk.koddos.net/CTAN/macros/unicodetex/latex/njuthesis/njuthesis.pdf) 的文档,参数大体保持一致,或者直接查阅对应源码函数的参数
+- **类型检查**
+ - [ ] 应该对所有函数入参进行类型检查,及时报错
+- **全局配置**
+ - [x] 类似 LaTeX 中的 `documentclass` 的全局信息配置
+ - [x] **盲审模式**,将个人信息替换成小黑条,并且隐藏致谢页面,论文提交阶段使用
+ - [x] **双面模式**,会加入空白页,便于打印
+ - [x] **自定义字体配置**,可以配置「宋体」、「黑体」与「楷体」等字体对应的具体字体
+ - [x] **数学字体配置**:模板不提供配置,用户可以自己使用 `#show math.equation: set text(font: "Fira Math")` 更改
+- **模板**
+ - [x] 本科生模板
+ - [x] 字体测试页
+ - [x] 毕业论文封面
+ - [x] 课程设计封面
+ - [x] 声明页
+ - [x] 中文摘要
+ - [x] 英文摘要
+ - [x] 目录页
+ - [x] 插图目录
+ - [x] 表格目录
+ - [x] 符号表
+ - [x] 致谢
+ - [x] 研究生模板
+ - [x] 封面
+ - [x] 声明页
+ - [x] 摘要
+ - [x] 页眉
+ - [ ] 国家图书馆封面
+ - [ ] 出版授权书
+ - [ ] 博士后模板
+- **编号**
+ - [x] 前言使用罗马数字编号
+ - [x] 附录使用罗马数字编号
+ - [x] 表格使用 `1.1` 格式进行编号
+ - [x] 数学公式使用 `(1.1)` 格式进行编号
+- **环境**
+ - [x] 定理环境(这个也可以自己使用第三方包配置)
+ - [x] 化学环境
+- **其他文件**
+ - [x] 本科生开题报告
+ - [x] 研究生开题报告
+
+
+## 致谢
+
+- 感谢 [HUST-typst-template](https://github.com/werifu/HUST-typst-template) ,[sysu-thesis-typst](https://github.com/howardlau1999/sysu-thesis-typst) ,[modern-nju-thesis](https://github.com/nju-lug/modern-nju-thesis) 与 [PKU-typst-template](https://github.com/pku-typst) 等Typst中文模板。
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/layouts/appendix.typ b/packages/preview/modern-cqut-thesis/0.1.0/layouts/appendix.typ
new file mode 100644
index 000000000..ee33f6086
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/layouts/appendix.typ
@@ -0,0 +1,24 @@
+#import "@preview/i-figured:0.2.4"
+#import "../utils/custom-numbering.typ": custom-numbering
+
+// 后记,重置 heading 计数器
+#let appendix(
+ numbering: custom-numbering.with(first-level: "", depth: 4, "1.1 "),
+ // figure 计数
+ show-figure: i-figured.show-figure.with(numbering: "1.1"),
+ // equation 计数
+ show-equation: i-figured.show-equation.with(numbering: "(1.1)"),
+ // 重置计数
+ reset-counter: false,
+ it,
+) = {
+ set heading(numbering: numbering)
+ if reset-counter {
+ counter(heading).update(0)
+ }
+ // 设置 figure 的编号
+ show figure: show-figure
+ // 设置 equation 的编号
+ show math.equation.where(block: true): show-equation
+ it
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/layouts/doc.typ b/packages/preview/modern-cqut-thesis/0.1.0/layouts/doc.typ
new file mode 100644
index 000000000..2222e0c08
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/layouts/doc.typ
@@ -0,0 +1,34 @@
+// 文稿设置,可以进行一些像页面边距这类的全局设置
+#let doc(
+ // documentclass 传入参数
+ info: (:),
+ // 其他参数
+ fallback: false, // 字体缺失时使用 fallback,不显示豆腐块
+ lang: "zh",
+ margin: (x: 89pt),
+ it,
+) = {
+ // 1. 默认参数
+ info = (
+ title: ("基于 Typst 的", "重庆理工大学学位论文"),
+ author: "张三",
+ ) + info
+
+ // 2. 对参数进行处理
+ // 2.1 如果是字符串,则使用换行符将标题分隔为列表
+ if type(info.title) == str {
+ info.title = info.title.split("\n")
+ }
+
+ // 3. 基本的样式设置
+ set text(fallback: fallback, lang: lang)
+ set page(margin: margin)
+
+ // 4. PDF 元信息
+ set document(
+ title: (("",)+ info.title).sum(),
+ author: info.author,
+ )
+
+ it
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/layouts/mainmatter.typ b/packages/preview/modern-cqut-thesis/0.1.0/layouts/mainmatter.typ
new file mode 100644
index 000000000..013232e9c
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/layouts/mainmatter.typ
@@ -0,0 +1,176 @@
+#import "@preview/i-figured:0.2.4"
+#import "../utils/anti-matter.typ": anti-front-end
+#import "../utils/style.typ": 字号, 字体
+#import "../utils/custom-numbering.typ": custom-numbering
+#import "../utils/custom-heading.typ": heading-display, active-heading, current-heading
+#import "../utils/indent.typ": fake-par
+#import "../utils/unpairs.typ": unpairs
+
+#let mainmatter(
+ // documentclass 传入参数
+ twoside: false,
+ fonts: (:),
+ // 其他参数
+ leading: 1.5 * 15.6pt - 0.7em,
+ spacing: 1.5 * 15.6pt - 0.7em,
+ justify: true,
+ first-line-indent: 2em,
+ numbering: custom-numbering.with(first-level: "第一章 ", depth: 4, "1.1 "),
+ // 正文字体与字号参数
+ text-args: auto,
+ // 标题字体与字号
+ heading-font: auto,
+ heading-size: (字号.四号,),
+ heading-weight: ("regular",),
+ heading-above: (2 * 15.6pt - 0.7em, 2 * 15.6pt - 0.7em),
+ heading-below: (2 * 15.6pt - 0.7em, 1.5 * 15.6pt - 0.7em),
+ heading-pagebreak: (true, false),
+ heading-align: (center, auto),
+ // 页眉
+ header-render: auto,
+ header-vspace: 0em,
+ display-header: false,
+ skip-on-first-level: true,
+ stroke-width: 0.5pt,
+ reset-footnote: true,
+ // caption 的 separator
+ separator: " ",
+ // caption 样式
+ caption-style: strong,
+ caption-size: 字号.五号,
+ // figure 计数
+ show-figure: i-figured.show-figure,
+ // equation 计数
+ show-equation: i-figured.show-equation,
+ ..args,
+ it,
+) = {
+ // 0. 标志前言结束
+ anti-front-end()
+
+ // 1. 默认参数
+ fonts = 字体 + fonts
+ if (text-args == auto) {
+ text-args = (font: fonts.宋体, size: 字号.小四)
+ }
+ // 1.1 字体与字号
+ if (heading-font == auto) {
+ heading-font = (fonts.黑体,)
+ }
+ // 1.2 处理 heading- 开头的其他参数
+ let heading-text-args-lists = args.named().pairs()
+ .filter((pair) => pair.at(0).starts-with("heading-"))
+ .map((pair) => (pair.at(0).slice("heading-".len()), pair.at(1)))
+
+ // 2. 辅助函数
+ let array-at(arr, pos) = {
+ arr.at(calc.min(pos, arr.len()) - 1)
+ }
+
+ // 3. 设置基本样式
+ // 3.1 文本和段落样式
+ set text(..text-args)
+ set par(
+ leading: leading,
+ justify: justify,
+ first-line-indent: first-line-indent,
+ spacing: spacing
+ )
+ show raw: set text(font: fonts.等宽)
+ // 3.2 脚注样式
+ show footnote.entry: set text(font: fonts.宋体, size: 字号.五号)
+ // 3.3 设置 figure 的编号
+ show heading: i-figured.reset-counters
+ show figure: show-figure
+ // 3.4 设置 equation 的编号和假段落首行缩进
+ show math.equation.where(block: true): show-equation
+ // 3.5 表格表头置顶 + 不用冒号用空格分割 + 样式
+ show figure.where(
+ kind: table
+ ): set figure.caption(position: top)
+ set figure.caption(separator: separator)
+ show figure.caption: caption-style
+ show figure.caption: set text(font: fonts.宋体, size: 字号.五号)
+ // 3.6 优化列表显示
+ // 术语列表 terms 不应该缩进
+ show terms: set par(first-line-indent: 0pt)
+
+ // 4. 处理标题
+ // 4.1 设置标题的 Numbering
+ set heading(numbering: numbering)
+ // 4.2 设置字体字号并加入假段落模拟首行缩进
+ show heading: it => {
+ set text(
+ font: array-at(heading-font, it.level),
+ size: array-at(heading-size, it.level),
+ weight: array-at(heading-weight, it.level),
+ ..unpairs(heading-text-args-lists
+ .map((pair) => (pair.at(0), array-at(pair.at(1), it.level))))
+ )
+ set block(
+ above: array-at(heading-above, it.level),
+ below: array-at(heading-below, it.level),
+ )
+ it
+ fake-par
+ }
+ // 4.3 标题居中与自动换页
+ show heading: it => {
+ if (array-at(heading-pagebreak, it.level)) {
+ // 如果打上了 no-auto-pagebreak 标签,则不自动换页
+ if ("label" not in it.fields() or str(it.label) != "no-auto-pagebreak") {
+ pagebreak(weak: true)
+ }
+ }
+ if (array-at(heading-align, it.level) != auto) {
+ set align(array-at(heading-align, it.level))
+ it
+ } else {
+ it
+ }
+ }
+
+ // 5. 处理页眉
+ set page(..(if display-header {
+ (
+ header: {
+ // 重置 footnote 计数器
+ if reset-footnote {
+ counter(footnote).update(0)
+ }
+ locate(loc => {
+ // 5.1 获取当前页面的一级标题
+ let cur-heading = current-heading(level: 1, loc)
+ // 5.2 如果当前页面没有一级标题,则渲染页眉
+ if not skip-on-first-level or cur-heading == none {
+ if header-render == auto {
+ // 一级标题和二级标题
+ let first-level-heading = if not twoside or calc.rem(loc.page(), 2) == 0 { heading-display(active-heading(level: 1, loc)) } else { "" }
+ let second-level-heading = if not twoside or calc.rem(loc.page(), 2) == 2 { heading-display(active-heading(level: 2, prev: false, loc)) } else { "" }
+ set text(font: fonts.楷体, size: 字号.五号)
+ stack(
+ first-level-heading + h(1fr) + second-level-heading,
+ v(0.25em),
+ if first-level-heading != "" or second-level-heading != "" { line(length: 100%, stroke: stroke-width + black) },
+ )
+ } else {
+ header-render(loc)
+ }
+ v(header-vspace)
+ }
+ })
+ }
+ )
+ } else {
+ (
+ header: {
+ // 重置 footnote 计数器
+ if reset-footnote {
+ counter(footnote).update(0)
+ }
+ }
+ )
+ }))
+
+ it
+}
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/layouts/preface.typ b/packages/preview/modern-cqut-thesis/0.1.0/layouts/preface.typ
new file mode 100644
index 000000000..63a14fbb1
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/layouts/preface.typ
@@ -0,0 +1,18 @@
+#import "../utils/anti-matter.typ": anti-matter
+
+// 前言,重置页面计数器
+#let preface(
+ // documentclass 传入的参数
+ twoside: false,
+ // 其他参数
+ spec: (front: "I", inner: "1", back: "I"),
+ ..args,
+ it,
+) = {
+ // 分页
+ if (twoside) {
+ pagebreak() + " "
+ }
+ counter(page).update(0)
+ anti-matter(spec: spec, ..args, it)
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/lib.typ b/packages/preview/modern-cqut-thesis/0.1.0/lib.typ
new file mode 100644
index 000000000..f9bcefc58
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/lib.typ
@@ -0,0 +1,300 @@
+#import "layouts/doc.typ": doc
+#import "layouts/preface.typ": preface
+#import "layouts/mainmatter.typ": mainmatter
+#import "layouts/appendix.typ": appendix
+#import "pages/fonts-display-page.typ": fonts-display-page
+#import "pages/design-cover.typ": design-cover
+#import "pages/bachelor-cover.typ": bachelor-cover
+#import "pages/master-cover.typ": master-cover
+#import "pages/bachelor-decl-page.typ": bachelor-decl-page
+#import "pages/master-decl-page.typ": master-decl-page
+#import "pages/bachelor-abstract.typ": bachelor-abstract
+#import "pages/master-abstract.typ": master-abstract
+#import "pages/bachelor-abstract-en.typ": bachelor-abstract-en
+#import "pages/master-abstract-en.typ": master-abstract-en
+#import "pages/bachelor-outline-page.typ": bachelor-outline-page
+#import "pages/list-of-figures.typ": list-of-figures
+#import "pages/list-of-tables.typ": list-of-tables
+#import "pages/notation.typ": notation
+#import "pages/acknowledgement.typ": acknowledgement
+
+#import "utils/anti-matter.typ": anti-inner-end as mainmatter-end
+#import "utils/custom-cuti.typ": *
+#import "utils/bilingual-bibliography.typ": bilingual-bibliography
+#import "utils/custom-numbering.typ": custom-numbering
+#import "utils/custom-heading.typ": heading-display, active-heading, current-heading
+#import "utils/indent.typ": indent, fake-par
+#import "@preview/i-figured:0.2.4": show-figure, show-equation
+#import "utils/style.typ": 字体, 字号
+#import "utils/theorem.typ": *
+#import "utils/chem-for.typ": ca, cb
+#import "utils/cite-style.typ": custom-cite
+
+
+
+// 使用函数闭包特性,通过 `documentclass` 函数类进行全局信息配置,然后暴露出拥有了全局配置的、具体的 `layouts` 和 `templates` 内部函数。
+#let documentclass(
+ doctype: "bachelor", // "bachelor" | "master" | "doctor" | "postdoc",文档类型,默认为本科生 bachelor
+ degree: "academic", // "academic" | "professional",学位类型,默认为学术型 academic
+ nl-cover: false, // TODO: 是否使用国家图书馆封面,默认关闭
+ de-cover: false, // 是否使用 design-cover 渲染封面,默认关闭
+ twoside: false, // 双面模式,会加入空白页,便于打印
+ anonymous: false, // 盲审模式
+ bibliography: none, // 原来的参考文献函数
+ fonts: (:), // 字体,应传入「宋体」、「黑体」、「楷体」、「仿宋」、「等宽」
+ info: (:),
+) = {
+ // 默认参数
+ fonts = 字体 + fonts
+ info = (
+ title: ("基于 Typst 的", "重庆理工大学学位论文"),
+ title-en: "CQUT Thesis Template for Typst",
+ grade: "20XX",
+ student-id: "1234567890",
+ author: "张三",
+ author-en: "Zhang San",
+ department: "某学院",
+ department-en: "XX Department",
+ major: "某专业",
+ major-en: "XX Major",
+ field: "某方向",
+ field-en: "XX Field",
+ supervisor: ("李四", "教授"),
+ supervisor-en: "Professor Li Si",
+ supervisor-ii: (),
+ supervisor-ii-en: "",
+ submit-date: datetime.today(),
+ // 以下为研究生项
+ defend-date: datetime.today(),
+ confer-date: datetime.today(),
+ bottom-date: datetime.today(),
+ chairman: "某某某 教授",
+ reviewer: ("某某某 教授", "某某某 教授"),
+ clc: "O643.12",
+ udc: "544.4",
+ secret-level: "公开",
+ supervisor-contact: "重庆理工大学 重庆市巴南区红光大道59号",
+ email: "xyz@smail.cqut.edu.cn",
+ school-code: "10284",
+ degree: auto,
+ degree-en: auto,
+ ) + info
+
+ (
+ // 将传入参数再导出
+ doctype: doctype,
+ degree: degree,
+ nl-cover: nl-cover,
+ twoside: twoside,
+ anonymous: anonymous,
+ fonts: fonts,
+ info: info,
+ // 页面布局
+ doc: (..args) => {
+ doc(
+ ..args,
+ info: info + args.named().at("info", default: (:)),
+ )
+ },
+ preface: (..args) => {
+ preface(
+ twoside: twoside,
+ ..args,
+ )
+ },
+ mainmatter: (..args) => {
+ if doctype == "master" or doctype == "doctor" {
+ mainmatter(
+ twoside: twoside,
+ display-header: true,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ )
+ } else {
+ mainmatter(
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ )
+ }
+ },
+ mainmatter-end: (..args) => {
+ mainmatter-end(
+ ..args,
+ )
+ },
+ appendix: (..args) => {
+ appendix(
+ ..args,
+ )
+ },
+
+ // 字体展示页
+ fonts-display-page: (..args) => {
+ fonts-display-page(
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ )
+ },
+
+ // 封面页,通过 type 分发到不同函数
+ cover: (..args) => {
+ if de-cover {
+ // 如果 de-cover 为 true,使用 design-cover 渲染封面
+ design-cover(
+ anonymous: anonymous,
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ info: info + args.named().at("info", default: (:)),
+ )
+ } else if doctype == "master" or doctype == "doctor" {
+ master-cover(
+ doctype: doctype,
+ degree: degree,
+ nl-cover: nl-cover,
+ anonymous: anonymous,
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ info: info + args.named().at("info", default: (:)),
+ )
+ } else if doctype == "postdoc" {
+ panic("postdoc has not yet been implemented.")
+ } else {
+ bachelor-cover(
+ anonymous: anonymous,
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ info: info + args.named().at("info", default: (:)),
+ )
+ }
+ },
+
+ // 声明页,通过 type 分发到不同函数
+ decl-page: (..args) => {
+ if doctype == "master" or doctype == "doctor" {
+ master-decl-page(
+ anonymous: anonymous,
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ )
+ } else if doctype == "postdoc" {
+ panic("postdoc has not yet been implemented.")
+ } else {
+ bachelor-decl-page(
+ anonymous: anonymous,
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ info: info + args.named().at("info", default: (:)),
+ )
+ }
+ },
+
+ // 中文摘要页,通过 type 分发到不同函数
+ abstract: (..args) => {
+ if doctype == "master" or doctype == "doctor" {
+ master-abstract(
+ doctype: doctype,
+ degree: degree,
+ anonymous: anonymous,
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ info: info + args.named().at("info", default: (:)),
+ )
+ } else if doctype == "postdoc" {
+ panic("postdoc has not yet been implemented.")
+ } else {
+ bachelor-abstract(
+ anonymous: anonymous,
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ info: info + args.named().at("info", default: (:)),
+ )
+ }
+ },
+
+ // 英文摘要页,通过 type 分发到不同函数
+ abstract-en: (..args) => {
+ if doctype == "master" or doctype == "doctor" {
+ master-abstract-en(
+ doctype: doctype,
+ degree: degree,
+ anonymous: anonymous,
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ info: info + args.named().at("info", default: (:)),
+ )
+ } else if doctype == "postdoc" {
+ panic("postdoc has not yet been implemented.")
+ } else {
+ bachelor-abstract-en(
+ anonymous: anonymous,
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ info: info + args.named().at("info", default: (:)),
+ )
+ }
+ },
+
+ // 目录页
+ outline-page: (..args) => {
+ bachelor-outline-page(
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ )
+ },
+
+ // 插图目录页
+ list-of-figures: (..args) => {
+ list-of-figures(
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ )
+ },
+
+ // 表格目录页
+ list-of-tables: (..args) => {
+ list-of-tables(
+ twoside: twoside,
+ ..args,
+ fonts: fonts + args.named().at("fonts", default: (:)),
+ )
+ },
+
+ // 符号表页
+ notation: (..args) => {
+ notation(
+ twoside: twoside,
+ ..args,
+ )
+ },
+
+ // 参考文献页
+ bilingual-bibliography: (..args) => {
+ bilingual-bibliography(
+ bibliography: bibliography,
+ ..args,
+ )
+ },
+
+ // 致谢页
+ acknowledgement: (..args) => {
+ acknowledgement(
+ anonymous: anonymous,
+ twoside: twoside,
+ ..args,
+ )
+ },
+ )
+}
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/logos/1.svg b/packages/preview/modern-cqut-thesis/0.1.0/logos/1.svg
new file mode 100644
index 000000000..df888fe45
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/logos/1.svg
@@ -0,0 +1,290 @@
+
+
+
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/logos/2.svg b/packages/preview/modern-cqut-thesis/0.1.0/logos/2.svg
new file mode 100644
index 000000000..b8036d115
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/logos/2.svg
@@ -0,0 +1,254 @@
+
+
+
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/logos/3.svg b/packages/preview/modern-cqut-thesis/0.1.0/logos/3.svg
new file mode 100644
index 000000000..ec7057d20
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/logos/3.svg
@@ -0,0 +1,649 @@
+
+
+
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/others/bachelor-proposal.typ b/packages/preview/modern-cqut-thesis/0.1.0/others/bachelor-proposal.typ
new file mode 100644
index 000000000..07a7a5ca1
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/others/bachelor-proposal.typ
@@ -0,0 +1,88 @@
+#import "style.typ": 字体, 字号
+
+#let table-stroke = 0.5pt
+
+#set page(numbering: "1")
+
+#align(center, text(
+ font: 字体.黑体,
+ size: 字号.三号,
+ weight: "bold",
+ "重庆理工大学本科毕业论文(设计)开题报告"
+))
+
+#set text(font: 字体.宋体, size: 字号.五号)
+#set underline(offset: 0.1em)
+
+#align(center)[
+ 填表人签名#underline(" ")填表时间:#underline(" ")年#underline(" ")月#underline(" ")日
+]
+
+#v(-0.7em)
+
+#{
+ set text(size: 字号.小四)
+ table(
+ columns: (100pt, 1fr, 100pt, 1fr),
+ stroke: table-stroke,
+ align: center + horizon,
+ [学生姓名], [], [学号], [],
+ [院系专业], [], [手机号], [],
+ [指导教师姓名一 \ (必填)], [], [职称], [],
+ [导师所在院系], [], [是否校内], [],
+ [指导教师姓名二 \ (选填)], [], [职称], [],
+ [导师所在院系], [], [是否校内], [],
+ [毕设类型], table.cell(colspan: 3)[#sym.ballot.x 毕业论文 #h(1fr) #sym.ballot 毕业设计(含毕业作品) #h(1fr)],
+ [论文题目], table.cell(colspan: 3)[],
+ )
+}
+
+#v(-1.37em)
+
+#table(
+ columns: 1fr,
+ stroke: table-stroke,
+ inset: 10pt,
+)[
+ *一、研究背景及意义*(附参考文献)
+
+ #v(45em)
+][
+ *二、国内外研究现状*(文献综述,附参考文献,不少于800字)
+
+ #v(45em)
+][
+ *三、主要研究或解决的问题和拟采用的方法*
+
+ #v(45em)
+][
+ *四、工作进度计划*(每两周为一个单位)
+
+ #v(20em)
+][
+ *指导教师意见*(不少于50个字)
+
+ #v(20em)
+
+ #set align(right)
+
+ *签名:* #h(6em)
+
+ #v(1em)
+
+ #strong(" 年 月 日")
+][
+ *院系意见:*
+
+ *(自动写同意)*
+
+ #v(1fr)
+
+ #set align(right)
+
+ *院系负责人签名:* #h(6em)
+
+ #v(1em)
+
+ #strong(" 年 月 日")
+]
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/others/master-proposal-logo.png b/packages/preview/modern-cqut-thesis/0.1.0/others/master-proposal-logo.png
new file mode 100644
index 000000000..0b1e63c83
Binary files /dev/null and b/packages/preview/modern-cqut-thesis/0.1.0/others/master-proposal-logo.png differ
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/others/master-proposal.typ b/packages/preview/modern-cqut-thesis/0.1.0/others/master-proposal.typ
new file mode 100644
index 000000000..52d379cb4
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/others/master-proposal.typ
@@ -0,0 +1,151 @@
+#import "style.typ": 字体, 字号
+
+#let table-stroke = 0.5pt
+
+#set page(numbering: "1")
+#set par(leading: 1em)
+
+// 封面
+#{
+ set align(center)
+
+ v(5em)
+
+ image("master-proposal-logo.png", width: 7cm)
+
+ v(2em)
+
+ par(text(
+ font: 字体.黑体,
+ size: 字号.一号,
+ weight: "bold",
+ "某某学院\n硕士研究生论文开题报告",
+ ))
+
+ v(8em)
+
+ let info-inset = 0pt
+
+ let info-key(body) = {
+ rect(
+ width: 100%,
+ inset: info-inset,
+ stroke: none,
+ text(font: 字体.黑体, size: 字号.三号, weight: "bold", body),
+ )
+ }
+
+ let info-value(body) = {
+ set align(center)
+ rect(
+ width: 100%,
+ inset: info-inset,
+ stroke: (bottom: table-stroke + black),
+ text(
+ font: 字体.黑体,
+ size: 字号.三号,
+ bottom-edge: "descender",
+ body,
+ ),
+ )
+ }
+
+ grid(
+ columns: (100pt, 150pt),
+ column-gutter: -5pt,
+ row-gutter: 15pt,
+ info-key[论 文 题 目], info-value[题目],
+ info-key[作 者 姓 名], info-value[张三],
+ info-key[作 者 学 号], info-value[1234567890],
+ info-key[专 业 名 称], info-value[某专业],
+ info-key[研 究 方 向], info-value[某方向],
+ info-key[指 导 教 师], info-value[李四],
+ )
+
+ v(10em)
+
+ text(
+ font: 字体.黑体,
+ size: 字号.三号,
+ weight: "bold",
+ "二0 年 月 日",
+ )
+}
+
+#pagebreak(weak: true)
+
+// 主体
+#align(center, text(
+ font: 字体.黑体,
+ size: 字号.三号,
+ weight: "bold",
+ "开题报告",
+))
+
+#set text(font: 字体.宋体, size: 字号.五号)
+#set underline(offset: 0.1em)
+
+#table(
+ columns: (2em, 1fr),
+ align: (center + horizon, auto),
+ stroke: table-stroke,
+ inset: 10pt,
+)[
+ 题 \ \ 目
+][
+ #v(5em)
+][
+ 题 \ \ 目 \ \ 来 \ \ 源 \ \ 及 \ \ 类 \ \ 型
+][
+ #v(25em)
+][
+ 研 \ \ 究 \ \ 背 \ \ 景 \ \ 及 \ \ 意 \ \ 义
+][
+ #v(1fr)
+][
+ 国 \ \ 内 \ \ 外 \ \ 现 \ \ 状 \ \ 及 \ \ 分 \ \ 析
+][
+ #v(1fr)
+][
+ 研 \ \ 究 \ \ 目 \ \ 标 \ \ 、 \ \ 研 \ \ 究 \ \ 内 \ \ 容 \ \ 和 \ \ 拟 \ \ 解 \ \ 决 \ \ 的 \ \ 关 \ \ 键 \ \ 问 \ \ 题
+][
+ #v(1fr)
+][
+ 研 \ \ 究 \ \ 方 \ \ 法 \ \ 、 \ \ 设 \ \ 计 \ \ 及 \ \ 试 \ \ 验 \ \ 方 \ \ 案 \ \ 、 \ \ 可 \ \ 行 \ \ 性 \ \ 分 \ \ 析
+][
+ #v(1fr)
+][
+ 计 \ \ 划 \ \ 进 \ \ 度 \ \ 和 \ \ 质 \ \ 量 \ \ 保 \ \ 证
+][
+ #v(1fr)
+][
+ 预 \ \ 期 \ \ 成 \ \ 果 \ \ 与 \ \ 创 \ \ 新 \ \ 点
+][
+ #v(1fr)
+][
+ 参 \ \ 考 \ \ 文 \ \ 献 \ \ ︵ \ \ 不 \ \ 少 \ \ 于 \ \ 20 \ \ 篇 \ \ ︶
+][
+ #v(1fr)
+][
+ 导 \ \ 师 \ \ 意 \ \ 见
+][
+ #v(28em)
+][
+ 考 \ \ 核 \ \ 小 \ \ 组 \ \ 意 \ \ 见 \ \ 及 \ \ 结 \ \ 论
+][
+ #v(20em)
+
+ 是否进入论文写作:#h(1em) 是 #sym.ballot #h(2em) 否 #sym.ballot
+
+ // 是否进入论文写作:#h(1em) 是 #sym.ballot.x #h(2em) 否 #sym.ballot
+
+ #v(5em)
+
+ 签字:#underline(" " * 10) #h(1em) #underline(" " * 10) #h(1em) #underline(" " * 10) #h(1em)
+
+ #v(3em)
+
+ 日期:#h(4em) 年 #h(2em) 月 #h(2em) 日
+]
+
+*注:需向导师提供电子版开题报告,可打印粘贴。*
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/others/style.typ b/packages/preview/modern-cqut-thesis/0.1.0/others/style.typ
new file mode 100644
index 000000000..dcdc41812
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/others/style.typ
@@ -0,0 +1,42 @@
+#let 字号 = (
+ 初号: 42pt,
+ 小初: 36pt,
+ 一号: 26pt,
+ 小一: 24pt,
+ 二号: 22pt,
+ 小二: 18pt,
+ 三号: 16pt,
+ 小三: 15pt,
+ 四号: 14pt,
+ 中四: 13pt,
+ 小四: 12pt,
+ 五号: 10.5pt,
+ 小五: 9pt,
+ 六号: 7.5pt,
+ 小六: 6.5pt,
+ 七号: 5.5pt,
+ 小七: 5pt,
+)
+
+#let 字体 = (
+ // 宋体,属于「有衬线字体」,一般可以等同于英文中的 Serif Font
+ 宋体: ("Times New Roman", "SimSun"),
+ // 黑体,属于「无衬线字体」,一般可以等同于英文中的 Sans Serif Font
+ 黑体: ("Arial", "SimHei" ),
+ // 等宽字体,用于代码块环境,一般可以等同于英文中的 Monospaced Font
+ 等宽: ("Consolas", "FangSong"),
+ 楷体: ("Times New Roman", "KaiTi"),
+ 仿宋: ("Times New Roman", "FangSong"),
+)
+
+//「新罗马体(有衬线英文字体)」、「思源宋体(简体)」、「思源宋体」、「宋体(Windows)」、「宋体(MacOS)」
+// "Times New Roman", "Source Han Serif SC", "Source Han Serif", "Noto Serif CJK SC", "SimSun", "Songti SC", "STSongti"
+
+// 「Arial(无衬线英文字体)」、「思源黑体(简体)」、「思源黑体」、「黑体(Windows)」、「黑体(MacOS)」
+// "Arial", "Source Han Sans SC", "Source Han Sans", "Noto Sans CJK SC", "SimHei", "Heiti SC", "STHeiti"
+
+// 「Courier New(Windows 等宽英文字体)」、「思源等宽黑体(简体)」、「思源等宽黑体」、「黑体(Windows)」、「黑体(MacOS)」
+
+// "FangSong SC", "STFangSong", "FZFangSong-Z02S", "Noto Serif CJK SC"
+
+// "Kaiti SC", "STKaiti", "FZKai-Z03S", "Noto Serif CJK SC"
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/acknowledgement.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/acknowledgement.typ
new file mode 100644
index 000000000..28f2ba2b4
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/acknowledgement.typ
@@ -0,0 +1,19 @@
+// 致谢页
+#let acknowledgement(
+ // documentclass 传入参数
+ anonymous: false,
+ twoside: false,
+ // 其他参数
+ title: "致谢",
+ outlined: true,
+ body,
+) = {
+ if (not anonymous) {
+ pagebreak(weak: true, to: if twoside { "odd" })
+ [
+ #heading(level: 1, numbering: none, outlined: outlined, title)
+
+ #body
+ ]
+ }
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-abstract-en.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-abstract-en.typ
new file mode 100644
index 000000000..ab59dcaff
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-abstract-en.typ
@@ -0,0 +1,92 @@
+#import "../utils/custom-cuti.typ": fakebold
+#import "../utils/style.typ": 字号, 字体
+#import "../utils/indent.typ": fake-par
+#import "../utils/double-underline.typ": double-underline
+#import "../utils/invisible-heading.typ": invisible-heading
+
+// 本科生英文摘要页
+#let bachelor-abstract-en(
+ // documentclass 传入的参数
+ anonymous: false,
+ twoside: false,
+ fonts: (:),
+ info: (:),
+ // 其他参数
+ keywords: (),
+ outline-title: "ABSTRACT",
+ outlined: false,
+ anonymous-info-keys: ("author-en", "supervisor-en", "supervisor-ii-en"),
+ leading: 1.28em,
+ spacing: 1.38em,
+ body,
+) = {
+ // 1. 默认参数
+ fonts = 字体 + fonts
+ info = (
+ title-en: "NJU Thesis Template for Typst",
+ author-en: "Zhang San",
+ department-en: "XX Department",
+ major-en: "XX Major",
+ supervisor-en: "Professor Li Si",
+ ) + info
+
+ // 2. 对参数进行处理
+ // 2.1 如果是字符串,则使用换行符将标题分隔为列表
+ if type(info.title-en) == str {
+ info.title-en = info.title-en.split("\n")
+ }
+
+ // 3. 内置辅助函数
+ let info-value(key, body) = {
+ if (not anonymous or (key not in anonymous-info-keys)) {
+ body
+ }
+ }
+
+ // 4. 正式渲染
+ [
+ #pagebreak(weak: true, to: if twoside { "odd" })
+
+ #set text(font: fonts.楷体, size: 字号.小四)
+ #set par(leading: leading, justify: true, spacing: spacing) // 修改这里
+
+ // 标记一个不可见的标题用于目录生成
+ #invisible-heading(level: 1, outlined: outlined, outline-title)
+
+ #align(center)[
+ #set text(size: 字号.小二, weight: "bold")
+
+ #v(1em)
+
+ #double-underline[#fakebold[重庆理工大学本科生毕业论文(设计、作品)英文摘要]]
+ ]
+
+ #v(2pt)
+
+ // THESIS: #info-value("title-en", (("",)+ info.title-en).sum())
+
+ // DEPARTMENT: #info-value("department-en", info.department-en)
+
+ // SPECIALIZATION: #info-value("major-en", info.major-en)
+
+ // UNDERGRADUATE: #info-value("author-en", info.author-en)
+
+ // MENTOR: #info-value("supervisor-en", info.supervisor-en) #(if info.supervisor-ii-en != "" [#h(1em) #info-value("supervisor-ii-en", info.supervisor-ii-en)])
+
+
+ #align(center)[
+ #set text(size: 字号.小二, weight: "bold")
+
+ #v(1em)
+
+ ABSTRACT
+
+ ]
+
+ #body
+
+ #v(1em)
+
+ #fakebold[KEYWORDS]: #(("",)+ keywords.intersperse("; ")).sum()
+ ]
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-abstract.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-abstract.typ
new file mode 100644
index 000000000..49344682d
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-abstract.typ
@@ -0,0 +1,96 @@
+#import "../utils/custom-cuti.typ": fakebold
+#import "../utils/style.typ": 字号, 字体
+#import "../utils/indent.typ": fake-par
+#import "../utils/double-underline.typ": double-underline
+#import "../utils/invisible-heading.typ": invisible-heading
+
+// 本科生中文摘要页
+#let bachelor-abstract(
+ // documentclass 传入的参数
+ anonymous: false,
+ twoside: false,
+ fonts: (:),
+ info: (:),
+ // 其他参数
+ keywords: (),
+ outline-title: "中文摘要",
+ outlined: false,
+ anonymous-info-keys: ("author", "supervisor", "supervisor-ii"),
+ leading: 1.28em,
+ spacing: 1.28em,
+ body,
+) = {
+ // 1. 默认参数
+ fonts = 字体 + fonts
+ info = (
+ title: ("基于 Typst 的", "重庆理工大学学位论文"),
+ author: "张三",
+ department: "某学院",
+ major: "某专业",
+ supervisor: ("李四", "教授"),
+ ) + info
+
+ // 2. 对参数进行处理
+ // 2.1 如果是字符串,则使用换行符将标题分隔为列表
+ if type(info.title) == str {
+ info.title = info.title.split("\n")
+ }
+
+ // 3. 内置辅助函数
+ let info-value(key, body) = {
+ if (not anonymous or (key not in anonymous-info-keys)) {
+ body
+ }
+ }
+
+ // 4. 正式渲染
+ pagebreak(weak: true, to: if twoside { "odd" })
+
+// 4. 正式渲染
+pagebreak(weak: true, to: if twoside { "odd" })
+
+ [
+ #set text(font: fonts.楷体, size: 字号.小四)
+ #set par(leading: leading, justify: true, spacing: spacing) // 修改为 set par 并直接设定 spacing
+
+ // 标记一个不可见的标题用于目录生成
+ #invisible-heading(level: 1, outlined: outlined, outline-title)
+
+ #align(center)[
+ #set text(size: 字号.小二, weight: "bold")
+
+ #v(1em)
+
+ #double-underline[#fakebold[重庆理工大学本科生毕业论文(设计、作品)中文摘要]]
+ ]
+
+ // #fakebold[题目:]#info-value("title", (("",)+ info.title).sum())
+
+ // #fakebold[院系:]#info-value("department", info.department)
+
+ // #fakebold[专业:]#info-value("major", info.major)
+
+ // #fakebold[本科生姓名:]#info-value("author", info.author)
+
+ // #fakebold[指导教师(姓名、职称):]#info-value("supervisor", info.supervisor.at(0) + info.supervisor.at(1)) #(if info.supervisor-ii != () [#h(1em) #info-value("supervisor-ii", info.supervisor-ii.at(0) + info.supervisor-ii.at(1))])
+
+ #align(center)[
+ #set text(size: 字号.小二, weight: "bold")
+
+ #v(1em)
+
+ #fakebold[摘 要]
+
+ ]
+
+ #[
+ #set par(first-line-indent: 2em) // 使用 set par 设置首行缩进
+ #fake-par
+ #body
+ ]
+
+ #v(1em)
+
+ #fakebold[关键词:]#(("",)+ keywords.intersperse(";")).sum()
+ ]
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-cover.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-cover.typ
new file mode 100644
index 000000000..56b990786
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-cover.typ
@@ -0,0 +1,165 @@
+#import "../utils/datetime-display.typ": datetime-display
+#import "../utils/style.typ": 字号, 字体
+
+// 本科生封面
+#let bachelor-cover(
+ // documentclass 传入的参数
+ anonymous: false,
+ twoside: false,
+ fonts: (:),
+ info: (:),
+ // 其他参数
+ stoke-width: 0.5pt,
+ min-title-lines: 2,
+ info-inset: (x: 0pt, bottom: 1pt),
+ info-key-width: 72pt,
+ info-key-font: "楷体",
+ info-value-font: "楷体",
+ column-gutter: -3pt,
+ row-gutter: 11.5pt,
+ anonymous-info-keys: ("grade", "student-id", "author", "supervisor", "supervisor-ii"),
+ bold-info-keys: ("title",),
+ bold-level: "bold",
+ datetime-display: datetime-display,
+) = {
+ // 1. 默认参数
+ fonts = 字体 + fonts
+ info = (
+ title: ("基于 Typst 的", "重庆理工大学学位论文"),
+ grade: "20XX",
+ student-id: "1234567890",
+ author: "张三",
+ department: "某学院",
+ major: "某专业",
+ supervisor: ("李四", "教授"),
+ submit-date: datetime.today(),
+ ) + info
+
+ // 2. 对参数进行处理
+ // 2.1 如果是字符串,则使用换行符将标题分隔为列表
+ if type(info.title) == str {
+ info.title = info.title.split("\n")
+ }
+ // 2.2 根据 min-title-lines 填充标题
+ info.title = info.title + range(min-title-lines - info.title.len()).map((it) => " ")
+ // 2.3 处理提交日期
+ if type(info.submit-date) == datetime {
+ info.submit-date = datetime-display(info.submit-date)
+ }
+
+ // 3. 内置辅助函数
+ let info-key(body) = {
+ rect(
+ width: 100%,
+ inset: info-inset,
+ stroke: none,
+ text(
+ font: fonts.at(info-key-font, default: "楷体"),
+ size: 字号.三号,
+ body
+ ),
+ )
+ }
+
+ let info-value(key, body) = {
+ set align(center)
+ rect(
+ width: 100%,
+ inset: info-inset,
+ stroke: (bottom: stoke-width + black),
+ text(
+ font: fonts.at(info-value-font, default: "宋体"),
+ size: 字号.三号,
+ weight: if (key in bold-info-keys) { bold-level } else { "regular" },
+ bottom-edge: "descender",
+ body,
+ ),
+ )
+ }
+
+ let info-long-value(key, body) = {
+ grid.cell(colspan: 3,
+ info-value(
+ key,
+ if anonymous and (key in anonymous-info-keys) {
+ "██████████"
+ } else {
+ body
+ }
+ )
+ )
+ }
+
+ let info-short-value(key, body) = {
+ info-value(
+ key,
+ if anonymous and (key in anonymous-info-keys) {
+ "█████"
+ } else {
+ body
+ }
+ )
+ }
+
+
+ // 4. 正式渲染
+
+ pagebreak(weak: true, to: if twoside { "odd" })
+
+ // 居中对齐
+ set align(center)
+
+ // 匿名化处理去掉封面标识
+ if anonymous {
+ v(52pt)
+ } else {
+ // 封面图标
+
+ v(6pt)
+
+ image("../logos/3.svg", width: 14cm)
+
+ v(22pt)
+
+ v(2pt)
+ }
+
+ // 将中文之间的空格间隙从 0.25 em 调整到 0.5 em
+ text(size: 字号.小初, font: fonts.黑体, spacing: 200%, weight: "bold")[本 科 毕 业 论 文]
+
+ if anonymous {
+ v(310pt)
+ } else {
+ v(134pt)
+ }
+
+ block(width: 318pt, grid(
+ columns: (info-key-width, 1fr, info-key-width, 1fr),
+ column-gutter: column-gutter,
+ row-gutter: row-gutter,
+ info-key("院 系"),
+ info-long-value("department", info.department),
+ info-key("专 业"),
+ info-long-value("major", info.major),
+ info-key("题 目"),
+ ..info.title.map((s) => info-long-value("title", s)).intersperse(info-key(" ")),
+ info-key("年 级"),
+ info-short-value("grade", info.grade),
+ info-key("学 号"),
+ info-short-value("student-id", info.student-id),
+ info-key("学生姓名"),
+ info-long-value("author", info.author),
+ info-key("指导教师"),
+ info-short-value("supervisor", info.supervisor.at(0)),
+ info-key("职 称"),
+ info-short-value("supervisor", info.supervisor.at(1)),
+ ..(if info.supervisor-ii != () {(
+ info-key("第二导师"),
+ info-short-value("supervisor-ii", info.supervisor-ii.at(0)),
+ info-key("职 称"),
+ info-short-value("supervisor-ii", info.supervisor-ii.at(1)),
+ )} else {()}),
+ info-key("提交日期"),
+ info-long-value("submit-date", info.submit-date),
+ ))
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-decl-page.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-decl-page.typ
new file mode 100644
index 000000000..00d3f51f9
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-decl-page.typ
@@ -0,0 +1,72 @@
+#import "../utils/indent.typ": indent
+#import "../utils/style.typ": 字号, 字体
+
+// 本科生声明页
+#let bachelor-decl-page(
+ anonymous: false,
+ twoside: false,
+ fonts: (:),
+ info: (:),
+) = {
+ // 0. 如果需要匿名则短路返回
+ if anonymous {
+ return
+ }
+
+ // 1. 默认参数
+ fonts = 字体 + fonts
+ info = (
+ title: ("基于 Typst 的", "重庆理工大学学位论文"),
+ ) + info
+
+ // 2. 对参数进行处理
+ // 2.1 如果是字符串,则使用换行符将标题分隔为列表
+ if type(info.title) == str {
+ info.title = info.title.split("\n")
+ }
+
+
+ // 3. 正式渲染
+ pagebreak(weak: true, to: if twoside { "odd" })
+
+ v(6pt)
+
+ align(center, image("../logos/1.svg", width: 1.95cm))
+
+ v(-12pt)
+
+ align(
+ center,
+ text(
+ font: fonts.黑体,
+ size: 字号.小一,
+ weight: "bold",
+ "重庆理工大学本科毕业论文(设计)\n诚信承诺书",
+ ),
+ )
+
+ v(48pt)
+
+ block[
+ #set text(font: fonts.宋体, size: 字号.小三)
+ #set par(justify: true, first-line-indent: 2em, leading: 2.42em)
+
+ #indent 本人郑重承诺:所呈交的毕业论文(设计)(题目:#info.title.sum())是在指导教师的指导下严格按照学校和院系有关规定由本人独立完成的。本毕业论文(设计)中引用他人观点及参考资源的内容均已标注引用,如出现侵犯他人知识产权的行为,由本人承担相应法律责任。本人承诺不存在抄袭、伪造、篡改、代写、买卖毕业论文(设计)等违纪行为。
+ ]
+
+ v(76pt)
+
+ grid(
+ columns: (1fr, 150pt),
+ [],
+ align(left)[
+ #set text(font: fonts.黑体, size: 字号.小三)
+
+ 作者签名:
+
+ 学号:
+
+ 日期:
+ ]
+ )
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-outline-page.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-outline-page.typ
new file mode 100644
index 000000000..b0064d072
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/bachelor-outline-page.typ
@@ -0,0 +1,80 @@
+#import "@preview/outrageous:0.3.0"
+#import "../utils/invisible-heading.typ": invisible-heading
+#import "../utils/style.typ": 字号, 字体
+
+// 本科生目录生成
+#let bachelor-outline-page(
+ // documentclass 传入参数
+ twoside: false,
+ fonts: (:),
+ // 其他参数
+ depth: 4,
+ title: "目 录",
+ outlined: false,
+ title-vspace: 0pt,
+ title-text-args: auto,
+ // 引用页数的字体,这里用于显示 Times New Roman
+ reference-font: auto,
+ reference-size: 字号.小四,
+ // 字体与字号
+ font: auto,
+ size: (字号.四号, 字号.小四),
+ // 垂直间距
+ vspace: (25pt, 14pt),
+ indent: (0pt, 18pt, 28pt),
+ // 全都显示点号
+ fill: (auto,),
+ ..args,
+) = {
+ // 1. 默认参数
+ fonts = 字体 + fonts
+ if (title-text-args == auto) {
+ title-text-args = (font: fonts.宋体, size: 字号.三号, weight: "bold")
+ }
+ // 引用页数的字体,这里用于显示 Times New Roman
+ if (reference-font == auto) {
+ reference-font = fonts.宋体
+ }
+ // 字体与字号
+ if (font == auto) {
+ font = (fonts.黑体, fonts.宋体)
+ }
+
+ // 2. 正式渲染
+ pagebreak(weak: true, to: if twoside { "odd" })
+
+ // 默认显示的字体
+ set text(font: reference-font, size: reference-size)
+
+ {
+ set align(center)
+ text(..title-text-args, title)
+ // 标记一个不可见的标题用于目录生成
+ invisible-heading(level: 1, outlined: outlined, title)
+ }
+
+ v(title-vspace)
+
+ show outline.entry: outrageous.show-entry.with(
+ // 保留 Typst 基础样式
+ ..outrageous.presets.typst,
+ body-transform: (level, it) => {
+ // 设置字体和字号
+ set text(
+ font: font.at(calc.min(level, font.len()) - 1),
+ size: size.at(calc.min(level, size.len()) - 1),
+ )
+ // 计算缩进
+ let indent-list = indent + range(level - indent.len()).map((it) => indent.last())
+ let indent-length = indent-list.slice(0, count: level).sum()
+ h(indent-length) + it
+ },
+ vspace: vspace,
+ fill: fill,
+ ..args,
+ )
+
+ // 显示目录
+ outline(title: none, depth: depth)
+
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/design-cover.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/design-cover.typ
new file mode 100644
index 000000000..49deccef0
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/design-cover.typ
@@ -0,0 +1,165 @@
+#import "../utils/style.typ": 字号, 字体
+#import "../utils/datetime-display.typ": datetime-display
+
+#let design-cover(
+ anonymous: false,
+ twoside: false,
+ fonts: (:),
+ info: (:),
+ stoke-width: 0.5pt,
+ info-inset: (x: 0pt, bottom: 1pt),
+ info-key-width: 72pt,
+ info-key-font: "宋体",
+ info-value-font: "宋体",
+ column-gutter: -3pt,
+ row-gutter: 22pt,
+ anonymous-info-keys: ("grade", "student-id", "author", "supervisor", "supervisor-ii", "class"),
+ bold-info-keys: (),
+ bold-level: "bold",
+) = {
+ fonts = 字体 + fonts
+ info = (
+ title: "课程论文标题",
+ grade: "2022",
+ student-id: "12115990136",
+ author: "刘抗非",
+ department: "化学化工学院",
+ major: "化学工程与工艺",
+ class: "150103",
+ supervisor: ("李四", "教授"),
+ submit-date: datetime.today(),
+ ) + info
+
+ // 移除 title 的元组转换
+ // if type(info.title) == str {
+ // info.title = (info.title,)
+ // }
+
+ info.submit-date = datetime-display(info.submit-date)
+
+ let info-key(body) = {
+ rect(
+ width: 100%,
+ inset: info-inset,
+ stroke: none,
+ text(
+ font: fonts.at(info-key-font, default: "宋体"),
+ size: 字号.三号,
+ body
+ ),
+ )
+ }
+
+ let info-value(key, body) = {
+ set align(center)
+ rect(
+ width: 100%,
+ inset: info-inset,
+ stroke: (bottom: stoke-width + black),
+ text(
+ font: fonts.at(info-value-font, default: "宋体"),
+ size: 字号.三号,
+ weight: if (key in bold-info-keys) { bold-level } else { "regular" },
+ bottom-edge: "descender",
+ {
+ if type(body) == array {
+ body.map(v => {
+ if type(v) == str { [#v] }
+ else if type(v) == content { v }
+ else { [#repr(v)] }
+ }).join([#"\n"])
+ } else if type(body) == str {
+ [#body]
+ } else if type(body) == content {
+ body
+ } else {
+ [#repr(body)]
+ }
+ }
+ )
+ )
+ }
+
+ let info-long-value(key, body) = {
+ grid.cell(colspan: 3,
+ info-value(
+ key,
+ if anonymous and (key in anonymous-info-keys) {
+ "██████████"
+ } else {
+ body
+ }
+ )
+ )
+ }
+
+ let info-short-value(key, body) = {
+ info-value(
+ key,
+ if anonymous and (key in anonymous-info-keys) {
+ "█████"
+ } else {
+ body
+ }
+ )
+ }
+
+ pagebreak(weak: true, to: if twoside { "odd" })
+
+ set align(center)
+
+ if anonymous {
+ v(52pt)
+ } else {
+ v(25pt)
+ image("../logos/3.svg", width: 14cm)
+ }
+
+ text(size: 字号.小初, font: fonts.黑体, spacing: 200%, weight: "bold")[课程论文]
+
+ // 题目栏
+ block(width: 400pt, {
+ grid(
+ columns: (55pt, 1fr),
+ gutter: 0pt,
+ align(left + bottom, text(font: fonts.at(info-key-font, default: "宋体"), size: 字号.一号)[题目]),
+ align(bottom, info-value("title", info.title)
+ ))
+ })
+
+ if anonymous {
+ v(155pt)
+ } else {
+ v(85pt)
+ }
+
+ block(width: 300pt, grid(
+ columns: (info-key-width, 1fr, info-key-width, 1fr),
+ column-gutter: column-gutter,
+ row-gutter: row-gutter,
+ info-key("院 系"),
+ info-long-value("department", info.department),
+ info-key("专 业"),
+ info-long-value("major", info.major),
+ info-key("班 级"),
+ info-long-value("class", info.class),
+ info-key("年 级"),
+ info-short-value("grade", info.grade),
+ info-key("学 号"),
+ info-short-value("student-id", info.student-id),
+ info-key("学生姓名"),
+ info-long-value("author", info.author),
+ info-key("指导教师"),
+ info-short-value("supervisor", if type(info.supervisor) == array { info.supervisor.at(0, default: "") } else { info.supervisor }),
+ info-key("职 称"),
+ info-short-value("supervisor", if type(info.supervisor) == array and info.supervisor.len() > 1 { info.supervisor.at(1) } else { "" }),
+ ..(if "supervisor-ii" in info and type(info.supervisor-ii) == array and info.supervisor-ii.len() > 0 {(
+ info-key("第二导师"),
+ info-short-value("supervisor-ii", info.supervisor-ii.at(0, default: "")),
+ info-key("职 称"),
+ info-short-value("supervisor-ii", info.supervisor-ii.at(1, default: "")),
+ )} else {()}),
+ info-key("提交日期"),
+ info-long-value("submit-date", info.submit-date),
+ ))
+}
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/fonts-display-page.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/fonts-display-page.typ
new file mode 100644
index 000000000..3c002d03f
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/fonts-display-page.typ
@@ -0,0 +1,54 @@
+#import "../utils/style.typ": 字号, 字体
+#import "../utils/hline.typ": hline
+
+// 字体显示测试页
+#let fonts-display-page(
+ twoside: false,
+ fonts: (:),
+ size: 字号.小四,
+ lang: "zh",
+) = {
+ // 1. 默认参数
+ fonts = 字体 + fonts
+
+ // 2. 辅助函数
+ let display-font(cjk-name, latin-name) = [
+ #set text(font: fonts.at(cjk-name))
+
+ #cjk-name (#latin-name CJK Regular): 落霞与孤鹜齐飞,秋水共长天一色。
+
+ #cjk-name (#latin-name Latin Regular): The fanfare of birds announces the morning.
+
+ *#cjk-name (#latin-name CJK Bold): 落霞与孤鹜齐飞,秋水共长天一色。*
+
+ *#cjk-name (#latin-name Latin Bold): The fanfare of birds announces the morning.*
+ ]
+
+ // 3. 正式渲染
+ pagebreak(weak: true, to: if twoside { "odd" })
+ set text(size: size, lang: lang)
+
+ [
+ *Fonts Display Page:*
+
+ #hline()
+
+ #display-font("宋体", "SongTi")
+
+ #hline()
+
+ #display-font("黑体", "HeiTi")
+
+ #hline()
+
+ #display-font("楷体", "KaiTi")
+
+ #hline()
+
+ #display-font("仿宋", "FangSong")
+
+ #hline()
+
+ #display-font("等宽", "Mono")
+ ]
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/list-of-figures.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/list-of-figures.typ
new file mode 100644
index 000000000..295c99bfe
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/list-of-figures.typ
@@ -0,0 +1,74 @@
+#import "@preview/i-figured:0.2.4"
+#import "@preview/outrageous:0.1.0"
+#import "../utils/invisible-heading.typ": invisible-heading
+#import "../utils/style.typ": 字号, 字体
+
+// 表格目录生成
+#let list-of-figures(
+ // documentclass 传入参数
+ twoside: false,
+ fonts: (:),
+ // 其他参数
+ title: "插图目录",
+ outlined: false,
+ title-vspace: 32pt,
+ title-text-args: auto,
+ // caption 的 separator
+ separator: " ",
+ // 字体与字号
+ font: auto,
+ size: 字号.小四,
+ // 垂直间距
+ vspace: 14pt,
+ // 是否显示点号
+ fill: auto,
+ ..args,
+) = {
+ // 1. 默认参数
+ fonts = 字体 + fonts
+ if (title-text-args == auto) {
+ title-text-args = (font: fonts.宋体, size: 字号.三号, weight: "bold")
+ }
+ // 字体与字号
+ if (font == auto) {
+ font = fonts.宋体
+ }
+
+ // 2. 正式渲染
+ pagebreak(weak: true, to: if twoside { "odd" })
+
+ // 默认显示的字体
+ set text(font: font, size: size)
+
+ {
+ set align(center)
+ text(..title-text-args, title)
+ // 标记一个不可见的标题用于目录生成
+ invisible-heading(level: 1, outlined: outlined, title)
+ }
+
+ v(title-vspace)
+
+ show outline.entry: outrageous.show-entry.with(
+ // 保留 Typst 基础样式
+ ..outrageous.presets.typst,
+ body-transform: (level, it) => {
+ // 因为好像没找到 separator 的参数,所以这里就手动寻找替换了
+ if (it.has("children") and it.children.at(3, default: none) == [#": "]) {
+ it.children.slice(0, 3).sum() + separator + it.children.slice(4).sum()
+ } else {
+ it
+ }
+ },
+ vspace: (vspace,),
+ fill: (fill,),
+ )
+
+ // 显示目录
+ i-figured.outline(target-kind: image, title: none)
+
+ // 手动分页
+ if (twoside) {
+ pagebreak() + " "
+ }
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/list-of-tables.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/list-of-tables.typ
new file mode 100644
index 000000000..9a75d5060
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/list-of-tables.typ
@@ -0,0 +1,74 @@
+#import "@preview/i-figured:0.1.0"
+#import "@preview/outrageous:0.3.0"
+#import "../utils/invisible-heading.typ": invisible-heading
+#import "../utils/style.typ": 字号, 字体
+
+// 表格目录生成
+#let list-of-tables(
+ // documentclass 传入参数
+ twoside: false,
+ fonts: (:),
+ // 其他参数
+ title: "表格目录",
+ outlined: false,
+ title-vspace: 32pt,
+ title-text-args: auto,
+ // caption 的 separator
+ separator: " ",
+ // 字体与字号
+ font: auto,
+ size: 字号.小四,
+ // 垂直间距
+ vspace: 14pt,
+ // 是否显示点号
+ fill: auto,
+ ..args,
+) = {
+ // 1. 默认参数
+ fonts = 字体 + fonts
+ if (title-text-args == auto) {
+ title-text-args = (font: fonts.宋体, size: 字号.三号, weight: "bold")
+ }
+ // 字体与字号
+ if (font == auto) {
+ font = fonts.宋体
+ }
+
+ // 2. 正式渲染
+ pagebreak(weak: true, to: if twoside { "odd" })
+
+ // 默认显示的字体
+ set text(font: font, size: size)
+
+ {
+ set align(center)
+ text(..title-text-args, title)
+ // 标记一个不可见的标题用于目录生成
+ invisible-heading(level: 1, outlined: outlined, title)
+ }
+
+ v(title-vspace)
+
+ show outline.entry: outrageous.show-entry.with(
+ // 保留 Typst 基础样式
+ ..outrageous.presets.typst,
+ body-transform: (level, it) => {
+ // 因为好像没找到 separator 的参数,所以这里就手动寻找替换了
+ if (it.has("children") and it.children.at(3, default: none) == [#": "]) {
+ it.children.slice(0, 3).sum() + separator + it.children.slice(4).sum()
+ } else {
+ it
+ }
+ },
+ vspace: (vspace,),
+ fill: (fill,),
+ )
+
+ // 显示目录
+ i-figured.outline(target-kind: table, title: none)
+
+ // 手动分页
+ if (twoside) {
+ pagebreak() + " "
+ }
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/master-abstract-en.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/master-abstract-en.typ
new file mode 100644
index 000000000..b30835c2f
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/master-abstract-en.typ
@@ -0,0 +1,138 @@
+#import "@preview/pinit:0.2.2": pin, pinit-place
+#import "../utils/style.typ": 字号, 字体
+#import "../utils/indent.typ": fake-par
+#import "../utils/double-underline.typ": double-underline
+#import "../utils/custom-tablex.typ": gridx, colspanx
+#import "../utils/invisible-heading.typ": invisible-heading
+
+// 研究生英文摘要页
+#let master-abstract-en(
+ // documentclass 传入的参数
+ doctype: "master",
+ degree: "academic",
+ anonymous: false,
+ twoside: false,
+ fonts: (:),
+ info: (:),
+ // 其他参数
+ keywords: (),
+ outline-title: "ABSTRACT",
+ outlined: true,
+ abstract-title-weight: "regular",
+ stoke-width: 0.5pt,
+ info-value-align: center,
+ info-inset: (x: 0pt, bottom: 0pt),
+ info-key-width: 74pt,
+ grid-inset: 0pt,
+ column-gutter: 2pt,
+ row-gutter: 10pt,
+ anonymous-info-keys: ("author-en", "supervisor-en", "supervisor-ii-en"),
+ leading: 1.27em,
+ spacing: 1.27em,
+ body,
+) = {
+ // 1. 默认参数
+ fonts = 字体 + fonts
+ info = (
+ title-en: "NJU Thesis Template for Typst",
+ author-en: "Zhang San",
+ department-en: "XX Department",
+ major-en: "XX Major",
+ supervisor-en: "Professor Li Si",
+ ) + info
+
+ // 2. 对参数进行处理
+ // 2.1 如果是字符串,则使用换行符将标题分隔为列表
+ if type(info.title-en) == str {
+ info.title-en = info.title-en.split("\n")
+ }
+
+ // 3. 内置辅助函数
+ let info-key(body) = {
+ rect(
+ inset: info-inset,
+ stroke: none,
+ text(font: fonts.楷体, size: 字号.四号, body),
+ )
+ }
+
+ let info-value(key, body) = {
+ set align(info-value-align)
+ rect(
+ width: 100%,
+ inset: info-inset,
+ stroke: (bottom: stoke-width + black),
+ text(
+ font: fonts.楷体,
+ size: 字号.四号,
+ bottom-edge: "descender",
+ if (anonymous and (key in anonymous-info-keys)) {
+ "█████"
+ } else {
+ body
+ },
+ ),
+ )
+ }
+
+ // 4. 正式渲染
+ pagebreak(weak: true, to: if twoside { "odd" })
+
+ [
+ #set text(font: fonts.楷体, size: 字号.四号)
+ #set par(leading: leading, justify: true)
+ #show par: set block(spacing: spacing)
+
+ // 标记一个不可见的标题用于目录生成
+ #invisible-heading(level: 1, outlined: outlined, outline-title)
+
+ #align(center)[
+ #set text(size: 字号.小二, weight: "bold")
+
+ #v(8pt)
+
+ #double-underline((if not anonymous { "重庆理工大学" }) + "研究生毕业论文英文摘要首页用纸")
+
+ #v(-5pt)
+ ]
+
+ #gridx(
+ columns: (56pt, auto, auto, 1fr),
+ inset: grid-inset,
+ column-gutter: column-gutter,
+ row-gutter: row-gutter,
+ info-key[#pin("title-en")THESIS:], colspanx(3, info-value("", " ")),
+ colspanx(4, info-value("", " ")),
+ colspanx(3, info-key[SPECIALIZATION:]), info-value("major-en", info.major-en),
+ colspanx(3, info-key[POSTGRADUATE:]), info-value("author-en", info.author-en),
+ colspanx(2, info-key[MENTOR:]), colspanx(2, info-value("supervisor-en", info.supervisor-en + if info.supervisor-ii-en != "" { h(1em) + info.supervisor-ii-en })),
+ )
+
+ // 用了很 hack 的方法来实现不规则表格长标题换行...
+ #pinit-place("title-en", {
+ set text(font: fonts.楷体, size: 字号.四号)
+ set par(leading: 1.3em)
+ h(58pt) + (("",)+ info.title-en).intersperse(" ").sum()
+ })
+
+ #v(3pt)
+
+ #align(center, text(font: fonts.黑体, size: 字号.小三, weight: abstract-title-weight, "ABSTRACT"))
+
+ #v(-5pt)
+
+ #set text(font: fonts.楷体, size: 字号.小四)
+
+ #[
+ #set par(first-line-indent: 2em)
+
+ #fake-par
+
+ #body
+ ]
+
+ #v(10pt)
+
+ KEYWORDS: #(("",)+ keywords.intersperse("; ")).sum()
+ ]
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/master-abstract.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/master-abstract.typ
new file mode 100644
index 000000000..0518011c8
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/master-abstract.typ
@@ -0,0 +1,139 @@
+#import "@preview/pinit:0.2.2": pin, pinit-place
+#import "../utils/style.typ": 字号, 字体
+#import "../utils/indent.typ": fake-par
+#import "../utils/double-underline.typ": double-underline
+#import "../utils/custom-tablex.typ": gridx, colspanx
+#import "../utils/invisible-heading.typ": invisible-heading
+
+// 研究生中文摘要页
+#let master-abstract(
+ // documentclass 传入的参数
+ doctype: "master",
+ degree: "academic",
+ anonymous: false,
+ twoside: false,
+ fonts: (:),
+ info: (:),
+ // 其他参数
+ keywords: (),
+ outline-title: "中文摘要",
+ outlined: true,
+ abstract-title-weight: "regular",
+ stoke-width: 0.5pt,
+ info-value-align: center,
+ info-inset: (x: 0pt, bottom: 0pt),
+ info-key-width: 74pt,
+ grid-inset: 0pt,
+ column-gutter: 0pt,
+ row-gutter: 10pt,
+ anonymous-info-keys: ("author", "grade", "supervisor", "supervisor-ii"),
+ leading: 1.27em,
+ spacing: 1.27em,
+ body,
+) = {
+ // 1. 默认参数
+ fonts = 字体 + fonts
+ info = (
+ title: ("基于 Typst 的", "重庆理工大学学位论文"),
+ author: "张三",
+ grade: "20XX",
+ department: "某学院",
+ major: "某专业",
+ supervisor: ("李四", "教授"),
+ ) + info
+
+ // 2. 对参数进行处理
+ // 2.1 如果是字符串,则使用换行符将标题分隔为列表
+ if type(info.title) == str {
+ info.title = info.title.split("\n")
+ }
+
+ // 3. 内置辅助函数
+ let info-key(body) = {
+ rect(
+ inset: info-inset,
+ stroke: none,
+ text(font: fonts.楷体, size: 字号.四号, body),
+ )
+ }
+
+ let info-value(key, body) = {
+ set align(info-value-align)
+ rect(
+ width: 100%,
+ inset: info-inset,
+ stroke: (bottom: stoke-width + black),
+ text(
+ font: fonts.楷体,
+ size: 字号.四号,
+ bottom-edge: "descender",
+ if (anonymous and (key in anonymous-info-keys)) {
+ "█████"
+ } else {
+ body
+ },
+ ),
+ )
+ }
+
+ // 4. 正式渲染
+ pagebreak(weak: true, to: if twoside { "odd" })
+
+ [
+ #set text(font: fonts.楷体, size: 字号.四号)
+ #set par(leading: leading, justify: true)
+ #show par: set block(spacing: spacing)
+
+ // 标记一个不可见的标题用于目录生成
+ #invisible-heading(level: 1, outlined: outlined, outline-title)
+
+ #align(center)[
+ #set text(size: 字号.小二, weight: "bold")
+
+ #v(8pt)
+
+ #double-underline((if not anonymous { "重庆理工大学" }) + "研究生毕业论文中文摘要首页用纸")
+
+ #v(-5pt)
+ ]
+
+ #gridx(
+ columns: (104pt, 1fr, auto, 1fr, auto, 1.5fr),
+ inset: grid-inset,
+ column-gutter: column-gutter,
+ row-gutter: row-gutter,
+ info-key[#pin("title")毕业论文题目:], colspanx(5, info-value("", " ")),
+ colspanx(6, info-value("", " ")),
+ colspanx(2, info-value("major", info.major)), info-key[专业],
+ info-value("grade", info.grade), info-key(if type == "doctor" { [级硕士生姓名:] } else { [级博士生姓名:] } ), info-value("author", info.author),
+ colspanx(2, info-key[指导教师(姓名、职称):]), colspanx(4, info-value("supervisor", info.supervisor.at(0) + " " + info.supervisor.at(1) + if info.supervisor-ii != () { h(1em) + info.supervisor-ii.at(0) + " " + info.supervisor-ii.at(1) })),
+ )
+
+ // 用了很 hack 的方法来实现不规则表格长标题换行...
+ #pinit-place("title", {
+ set text(font: fonts.楷体, size: 字号.四号)
+ set par(leading: 1.3em)
+ h(108pt) + (("",)+ info.title).sum()
+ })
+
+ #v(3pt)
+
+ #align(center, text(font: fonts.黑体, size: 字号.小三, weight: abstract-title-weight, "摘 要"))
+
+ #v(-5pt)
+
+ #set text(font: fonts.楷体, size: 字号.小四)
+
+ #[
+ #set par(first-line-indent: 2em)
+
+ #fake-par
+
+ #body
+ ]
+
+ #v(10pt)
+
+ *关键词*:#(("",)+ keywords.intersperse(";")).sum()
+ ]
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/master-cover.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/master-cover.typ
new file mode 100644
index 000000000..39e871e23
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/master-cover.typ
@@ -0,0 +1,307 @@
+#import "../utils/datetime-display.typ": datetime-display, datetime-en-display
+#import "../utils/justify-text.typ": justify-text
+#import "../utils/style.typ": 字号, 字体
+
+// 硕士研究生封面
+#let master-cover(
+ // documentclass 传入的参数
+ doctype: "master",
+ degree: "academic",
+ nl-cover: false,
+ anonymous: false,
+ twoside: false,
+ fonts: (:),
+ info: (:),
+ // 其他参数
+ stoke-width: 0.5pt,
+ min-title-lines: 2,
+ min-reviewer-lines: 5,
+ info-inset: (x: 0pt, bottom: 0.5pt),
+ info-key-width: 86pt,
+ info-column-gutter: 18pt,
+ info-row-gutter: 12pt,
+ meta-block-inset: (left: -15pt),
+ meta-info-inset: (x: 0pt, bottom: 2pt),
+ meta-info-key-width: 35pt,
+ meta-info-column-gutter: 10pt,
+ meta-info-row-gutter: 1pt,
+ defence-info-inset: (x: 0pt, bottom: 0pt),
+ defence-info-key-width: 110pt,
+ defence-info-column-gutter: 2pt,
+ defence-info-row-gutter: 12pt,
+ anonymous-info-keys: ("student-id", "author", "author-en", "supervisor", "supervisor-en", "supervisor-ii", "supervisor-ii-en", "chairman", "reviewer"),
+ datetime-display: datetime-display,
+ datetime-en-display: datetime-en-display,
+) = {
+ // 1. 默认参数
+ fonts = 字体 + fonts
+ info = (
+ title: ("基于 Typst 的", "重庆理工大学学位论文"),
+ grade: "20XX",
+ student-id: "1234567890",
+ author: "张三",
+ department: "某学院",
+ major: "某专业",
+ supervisor: ("李四", "教授"),
+ submit-date: datetime.today(),
+ ) + info
+
+ // 2. 对参数进行处理
+ // 2.1 如果是字符串,则使用换行符将标题分隔为列表
+ if type(info.title) == str {
+ info.title = info.title.split("\n")
+ }
+ if type(info.title-en) == str {
+ info.title-en = info.title-en.split("\n")
+ }
+ // 2.2 根据 min-title-lines 和 min-reviewer-lines 填充标题和评阅人
+ info.title = info.title + range(min-title-lines - info.title.len()).map((it) => " ")
+ info.reviewer = info.reviewer + range(min-reviewer-lines - info.reviewer.len()).map((it) => " ")
+ // 2.3 处理日期
+ assert(type(info.submit-date) == datetime, message: "submit-date must be datetime.")
+ if type(info.defend-date) == datetime {
+ info.defend-date = datetime-display(info.defend-date)
+ }
+ if type(info.confer-date) == datetime {
+ info.confer-date = datetime-display(info.confer-date)
+ }
+ if type(info.bottom-date) == datetime {
+ info.bottom-date = datetime-display(info.bottom-date)
+ }
+ // 2.4 处理 degree
+ if (info.degree == auto) {
+ if (doctype == "doctor") {
+ info.degree = "工程博士"
+ } else {
+ info.degree = "工程硕士"
+ }
+ }
+
+ // 3. 内置辅助函数
+ let info-key(body, info-inset: info-inset, is-meta: false) = {
+ set text(
+ font: if is-meta { fonts.宋体 } else { fonts.楷体 },
+ size: if is-meta { 字号.小五 } else { 字号.三号 },
+ weight: if is-meta { "regular" } else { "bold" },
+ )
+ rect(
+ width: 100%,
+ inset: info-inset,
+ stroke: none,
+ justify-text(with-tail: is-meta, body)
+ )
+ }
+
+ let info-value(key, body, info-inset: info-inset, is-meta: false, no-stroke: false) = {
+ set align(center)
+ rect(
+ width: 100%,
+ inset: info-inset,
+ stroke: if no-stroke { none } else { (bottom: stoke-width + black) },
+ text(
+ font: if is-meta { fonts.宋体 } else { fonts.楷体 },
+ size: if is-meta { 字号.小五 } else { 字号.三号 },
+ bottom-edge: "descender",
+ if (anonymous and (key in anonymous-info-keys)) {
+ if is-meta { "█████" } else { "██████████" }
+ } else {
+ body
+ },
+ ),
+ )
+ }
+
+ let anonymous-text(key, body) = {
+ if (anonymous and (key in anonymous-info-keys)) {
+ "██████████"
+ } else {
+ body
+ }
+ }
+
+ let meta-info-key = info-key.with(info-inset: meta-info-inset, is-meta: true)
+ let meta-info-value = info-value.with(info-inset: meta-info-inset, is-meta: true)
+ let defence-info-key = info-key.with(info-inset: defence-info-inset)
+ let defence-info-value = info-value.with(info-inset: defence-info-inset)
+
+
+ // 4. 正式渲染
+ pagebreak(weak: true, to: if twoside { "odd" })
+
+ block(width: 70pt, inset: meta-block-inset, grid(
+ columns: (meta-info-key-width, 1fr),
+ column-gutter: meta-info-column-gutter,
+ row-gutter: meta-info-row-gutter,
+ meta-info-key("学校代码"),
+ meta-info-value("school-code", info.school-code),
+ meta-info-key("分类号"),
+ meta-info-value("clc", info.clc),
+ meta-info-key("密级"),
+ meta-info-value("secret-level", info.secret-level),
+ meta-info-key("UDC"),
+ meta-info-value("udc", info.udc),
+ meta-info-key("学号"),
+ meta-info-value("student-id", info.student-id),
+ ))
+
+ // 居中对齐
+ set align(center)
+
+ // 匿名化处理去掉封面标识
+ if (anonymous) {
+ v(70pt)
+ } else {
+ // 封面图标
+
+ v(6pt)
+
+ image("../logos/3.svg", width: 14cm)
+
+ v(22pt)
+
+ v(2pt)
+ }
+
+ // 将中文之间的空格间隙从 0.25 em 调整到 0.5 em
+ text(size: 28pt, font: fonts.宋体, spacing: 200%, weight: "bold",
+ if doctype == "doctor" { "博 士 学 位 论 文" } else { "硕 士 学 位 论 文" },
+ )
+
+ if (anonymous) {
+ v(132pt)
+ } else {
+ v(30pt)
+ }
+
+ block(width: 294pt, grid(
+ columns: (info-key-width, 1fr),
+ column-gutter: info-column-gutter,
+ row-gutter: info-row-gutter,
+ info-key("论文题目"),
+ ..info.title.map((s) => info-value("title", s)).intersperse(info-key(" ")),
+ info-key("作者姓名"),
+ info-value("author", info.author),
+ ..(if degree == "professional" {(
+ {
+ set text(font: fonts.楷体, size: 字号.三号, weight: "bold")
+ move(dy: 0.3em, scale(x: 55%, box(width: 10em, "专业学位类别(领域)")))
+ },
+ info-value("major", info.degree + "(" + info.major + ")"),
+ )} else {(
+ info-key("专业名称"),
+ info-value("major", info.major),
+ )}),
+ info-key("研究方向"),
+ info-value("field", info.field),
+ info-key("导师姓名"),
+ info-value("supervisor", info.supervisor.intersperse(" ").sum()),
+ ..(if info.supervisor-ii != () {(
+ info-key(" "),
+ info-value("supervisor-ii", info.supervisor-ii.intersperse(" ").sum()),
+ )} else { () })
+ ))
+
+ v(50pt)
+
+ text(font: fonts.楷体, size: 字号.三号, datetime-display(info.submit-date))
+
+
+ // 第二页
+ pagebreak(weak: true)
+
+ v(161pt)
+
+ block(width: 284pt, grid(
+ columns: (defence-info-key-width, 1fr),
+ column-gutter: defence-info-column-gutter,
+ row-gutter: defence-info-row-gutter,
+ defence-info-key("答辩委员会主席"),
+ defence-info-value("chairman", info.chairman),
+ defence-info-key("评阅人"),
+ ..info.reviewer.map((s) => defence-info-value("reviewer", s)).intersperse(defence-info-key(" ")),
+ defence-info-key("论文答辩日期"),
+ defence-info-value("defend-date", info.defend-date, no-stroke: true),
+ ))
+
+ v(216pt)
+
+ align(left, box(width: 7.3em, text(font: fonts.楷体, size: 字号.三号, weight: "bold", justify-text(with-tail: true, "研究生签名"))))
+
+ v(7pt)
+
+ align(left, box(width: 7.3em, text(font: fonts.楷体, size: 字号.三号, weight: "bold", justify-text(with-tail: true, "导师签名"))))
+
+ // 第三页英文封面页
+ pagebreak(weak: true)
+
+ set text(font: fonts.楷体, size: 字号.小四)
+ set par(leading: 1.3em)
+
+ v(45pt)
+
+ text(font: fonts.黑体, size: 字号.二号, weight: "bold", info.title-en.intersperse("\n").sum())
+
+ v(36pt)
+
+ text(size: 字号.四号)[by]
+
+ v(-6pt)
+
+ text(font: fonts.黑体, size: 字号.四号, weight: "bold", anonymous-text("author-en", info.author-en))
+
+ v(11pt)
+
+ text(size: 字号.四号)[Supervised by]
+
+ v(-6pt)
+
+ text(font: fonts.黑体, size: 字号.四号, anonymous-text("supervisor-en", info.supervisor-en))
+
+ if info.supervisor-ii-en != "" {
+ v(-4pt)
+
+ text(font: fonts.黑体, size: 字号.四号, anonymous-text("supervisor-ii-en", info.supervisor-ii-en))
+
+ v(-9pt)
+ }
+
+ v(26pt)
+
+ [
+ A dissertation submitted to \
+ the graduate school of #(if not anonymous { "Chongqing University of Technology" }) \
+ in partial fulfilment of the requirements for the degree of \
+ ]
+
+ v(6pt)
+
+ smallcaps(if doctype == "doctor" { "Doctor of phlosophy" } else { "Master" })
+
+ v(6pt)
+
+ [in]
+
+ v(6pt)
+
+ info.major-en
+
+ v(46pt)
+
+ if not anonymous {
+ image("../logos/1.svg", width: 2.14cm)
+ }
+
+ v(28pt)
+
+ info.department-en
+
+ v(2pt)
+
+ if not anonymous {
+ [Chongqing University of Technology]
+ }
+
+ v(28pt)
+
+ datetime-en-display(info.submit-date)
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/master-decl-page.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/master-decl-page.typ
new file mode 100644
index 000000000..d4f90bf8f
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/master-decl-page.typ
@@ -0,0 +1,51 @@
+#import "../utils/indent.typ": indent
+#import "../utils/style.typ": 字号, 字体
+
+// 研究生声明页
+#let master-decl-page(
+ anonymous: false,
+ twoside: false,
+ fonts: (:),
+) = {
+ // 0. 如果需要匿名则短路返回
+ if anonymous {
+ return
+ }
+
+ // 1. 默认参数
+ fonts = 字体 + fonts
+
+ // 2. 正式渲染
+ pagebreak(weak: true, to: if twoside { "odd" })
+
+ v(25pt)
+
+ align(
+ center,
+ text(
+ font: fonts.黑体,
+ size: 字号.四号,
+ weight: "bold",
+ "重庆理工大学学位论文原创性声明",
+ ),
+ )
+
+ v(46pt)
+
+ block[
+ #set text(font: fonts.宋体, size: 字号.小四)
+ #set par(justify: true, first-line-indent: 2em, leading: 1.2em)
+
+ #indent 本人郑重声明,所提交的学位论文是本人在导师指导下独立进行科学研究工作所取得的成果。除本论文中已经注明引用的内容外,本论文不包含其他个人或集体已经发表或撰写过的研究成果,也不包含为获得重庆理工大学或其他教育机构的学位证书而使用过的材料。对本文的研究做出重要贡献的个人和集体,均已在论文的致谢部分明确标明。本人郑重申明愿承担本声明的法律责任。
+ ]
+
+ v(143pt)
+
+ align(right)[
+ #set text(font: fonts.黑体, size: 字号.小四)
+
+ 研究生签名:#h(5.8em)
+
+ 日期:#h(5.8em)
+ ]
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/pages/notation.typ b/packages/preview/modern-cqut-thesis/0.1.0/pages/notation.typ
new file mode 100644
index 000000000..2b8ac40b2
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/pages/notation.typ
@@ -0,0 +1,35 @@
+#let notation(
+ twoside: false,
+ title: "符号表",
+ outlined: true,
+ width: 350pt,
+ columns: (60pt, 1fr),
+ row-gutter: 16pt,
+ ..args,
+ body,
+) = {
+ heading(
+ level: 1,
+ numbering: none,
+ outlined: outlined,
+ title
+ )
+
+ align(center, block(width: width,
+ align(start, grid(
+ columns: columns,
+ row-gutter: row-gutter,
+ ..args,
+ // 解析 terms 内部结构以渲染到表格里
+ ..body.children
+ .filter(it => it.func() == terms.item)
+ .map(it => (it.term, it.description))
+ .flatten()
+ ))
+ ))
+
+ // 手动分页
+ if (twoside) {
+ pagebreak() + " "
+ }
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/template/logos/1.png b/packages/preview/modern-cqut-thesis/0.1.0/template/logos/1.png
new file mode 100644
index 000000000..321614098
Binary files /dev/null and b/packages/preview/modern-cqut-thesis/0.1.0/template/logos/1.png differ
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/template/logos/1.svg b/packages/preview/modern-cqut-thesis/0.1.0/template/logos/1.svg
new file mode 100644
index 000000000..df888fe45
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/template/logos/1.svg
@@ -0,0 +1,290 @@
+
+
+
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/template/logos/2.png b/packages/preview/modern-cqut-thesis/0.1.0/template/logos/2.png
new file mode 100644
index 000000000..0b1e63c83
Binary files /dev/null and b/packages/preview/modern-cqut-thesis/0.1.0/template/logos/2.png differ
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/template/logos/2.svg b/packages/preview/modern-cqut-thesis/0.1.0/template/logos/2.svg
new file mode 100644
index 000000000..b8036d115
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/template/logos/2.svg
@@ -0,0 +1,254 @@
+
+
+
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/template/logos/3.png b/packages/preview/modern-cqut-thesis/0.1.0/template/logos/3.png
new file mode 100644
index 000000000..618fb30f2
Binary files /dev/null and b/packages/preview/modern-cqut-thesis/0.1.0/template/logos/3.png differ
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/template/logos/3.svg b/packages/preview/modern-cqut-thesis/0.1.0/template/logos/3.svg
new file mode 100644
index 000000000..ec7057d20
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/template/logos/3.svg
@@ -0,0 +1,649 @@
+
+
+
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/template/thesis.bib b/packages/preview/modern-cqut-thesis/0.1.0/template/thesis.bib
new file mode 100644
index 000000000..ac49843ee
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/template/thesis.bib
@@ -0,0 +1,94 @@
+@book{蒋有绪1998,
+ title={中国森林群落分类及其群落学特征},
+ author={蒋有绪 and 郭泉水 and 马娟 and others},
+ year={1998},
+ publisher={科学出版社},
+ address={北京},
+ pages={11-12},
+}
+
+@inproceedings{中国力学学会1990,
+ title={第3届全国实验流体力学学术会议论文集},
+ author={中国力学学会},
+ year={1990},
+ address={天津},
+ publisher={**出版社},
+ pages={20-24}
+}
+
+@techreport{WHO1970,
+ title={World Health Organization. Factors Regulating the Immune Response: Report of WHO Scientific Group},
+ year={1970},
+ institution={WHO},
+ address={Geneva}
+}
+
+@phdthesis{张志祥1998,
+ author = {张志祥},
+ title = {间断动力系统的随机扰动及其在守恒律方程中的应用},
+ school = {北京大学数学学院},
+ address = {北京},
+ year = {1998},
+ pages = {50-55}
+}
+
+@patent{河北绿洲2001,
+ title={一种荒漠化地区生态植被综合培育种植方法:中国,01129210.5},
+ author={河北绿洲生态环境科技有限公司},
+ year={2001},
+ type={patent},
+ number={01129210.5},
+ note={2001-10-24[2002-05-28]},
+ url={http://211.152.9.47/sipoasp/zlijs/hyjs-yxnew. asp?recid=01129210.5&leixin}
+}
+
+@standard{GB/T2659-1986,
+ title = {世界各国和地区名称代码},
+ author = {国家标准局信息分类编码研究所},
+ year = {1986},
+ howpublished = {全国文献工作标准化技术委员会. 文献工作国家标准汇编:3.北京:中国标准出版社,1988:59-92.},
+ note = {GB/T 2659-1986}
+}
+
+
+@article{李炳穆2000,
+ title={理想的图书馆员和信息专家的素质与形象},
+ author={李炳穆},
+ journal={图书情报工作},
+ year={2000},
+ volume={2000},
+ number={2},
+ pages={5-8}
+}
+
+@article{丁文祥2000,
+ title={数字革命与竞争国际化},
+ author={丁文祥},
+ journal={中国青年报},
+ year={2000},
+ month={11-20},
+ number={15}
+}
+
+@article{江向东1999,
+ title={互联网环境下的信息处理与图书管理系统解决方案},
+ author={江向东},
+ journal={情报学报},
+ year={1999},
+ volume={18},
+ number={2},
+ pages={4},
+ note={2000-01-18},
+ url={http://www.chinainfo.gov.cn/periodical/gbxb/gbxb99/gbxb990203}
+}
+
+@article{CHRISTINE1998,
+ title={Plant physiology:plant biology in the Genome Era},
+ author={M CHRISTINE},
+ journal={Science},
+ year={1998},
+ volume={281},
+ pages={331-332},
+ note={1998-09-23},
+ url={http://www.sciencemag.org/cgi/collection/anatmorp}
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/template/thesis.typ b/packages/preview/modern-cqut-thesis/0.1.0/template/thesis.typ
new file mode 100644
index 000000000..2d3ad73bf
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/template/thesis.typ
@@ -0,0 +1,426 @@
+// 导入 preview 中的固定版本 modern-cqut-thesis:0.1.0 进行编译
+#import "@preview/modern-cqut-thesis:0.1.0": *
+
+// 从 lib.typ 导入并编译, 如果你要修改这个模板格式并编译请务必注释上方 @preview
+// 并导入下方 lib.typ 进行编译, 因默认优先级 @preview 更高, 直接从 typst 缓存目录(根目录进行编译)
+// #import "../lib.typ": *
+
+#let (
+ // 布局函数
+ twoside, doc, preface, mainmatter, mainmatter-end, appendix,
+ // 页面函数
+ fonts-display-page, cover, decl-page, abstract, abstract-en, bilingual-bibliography,
+ outline-page, list-of-figures, list-of-tables, notation, acknowledgement,
+) = documentclass(doctype: "bachelor",
+ // doctype: "bachelor", // "bachelor" | "master" | "doctor" | "postdoc", 文档类型,默认为本科生 bachelor
+ // degree: "academic", // "academic" | "professional", 学位类型,默认为学术型 academic
+ // anonymous: true, // 盲审模式
+ twoside: true, // 双面模式,会加入空白页,便于打印
+ // 可自定义字体,先英文字体后中文字体,应传入「宋体」、「黑体」、「楷体」、「仿宋」、「等宽」
+ // fonts: (楷体: ("Times New Roman", "FZKai-Z03S")),
+ nl-cover: false, // 国家图书馆封面
+ de-cover: false, // 设计封面
+ info: (
+ title: ("基于 Typst 的", "重庆理工大学学位论文"),
+ title-en: "My Title in English",
+ grade: "20XX",
+ student-id: "1234567890",
+ author: "张三",
+ author-en: "Ming Xing",
+ department: "某学院",
+ department-en: "School of Chemistry and Chemical Engineering",
+ major: "某专业",
+ major-en: "Chemistry",
+ supervisor: ("李四", "教授"),
+ supervisor-en: "Professor My Supervisor",
+ // supervisor-ii: ("王五", "副教授"),
+ // supervisor-ii-en: "Professor My Supervisor",
+ submit-date: datetime.today(),
+ ),
+ // 参考文献源
+ bibliography: bibliography.with("thesis.bib"),
+)
+
+// 文稿设置
+#show: doc
+
+
+// 一个别的引用样式,打印时应该注释掉
+#show cite: custom-cite
+
+
+// 封面页
+#cover()
+
+
+// // 字体展示测试页
+// #fonts-display-page()
+
+
+// 声明页
+#decl-page()
+
+
+// 前言
+#show: preface
+
+
+// 中文摘要
+#abstract(
+ keywords: ("关键词1", "关键词2", "关键词3", "关键词4")
+)[
+ 中文摘要
+]
+
+
+// 英文摘要
+#abstract-en(
+ keywords: ("Keyword1", "Keyword2", "Keyword3", "Keyword4")
+)[
+ English abstract
+]
+
+
+// 目录
+#outline-page()
+
+
+// 手动分页
+#if twoside {
+ pagebreak() + " "
+}
+
+
+// 插图目录
+// #list-of-figures()
+
+
+// 表格目录
+// #list-of-tables()
+
+
+// 正文
+#show: mainmatter
+
+
+// // 符号表
+// #notation[
+// / DFT: 密度泛函理论 (Density functional theory)
+// / DMRG: 密度矩阵重正化群密度矩阵重正化群密度矩阵重正化群 (Density-Matrix Reformation-Group)
+// ]
+
+
+
+// ------------------------------------------- //
+
+
+
+= 列 表
+
+== 无序列表
+
+- 无序列表项一
+- 无序列表项二
+ - 无序子列表项一
+ - 无序子列表项二
+
+== 有序列表
+
++ 有序列表项一
++ 有序列表项二
+ + 有序子列表项一
+ + 有序子列表项二
+
+== 术语列表
+
+/ 术语一: 术语解释
+/ 术语二: 术语解释
+
+
+// 手动分页
+#if twoside {
+ pagebreak() + " "
+}
+
+
+
+// ------------------------------------------- //
+
+
+
+= 图 表
+
+== 格式化的图标
+引用@tbl:timing,引用@tbl:timing-tlt,以及@fig:cqut-logo。引用图表时,表格和图片分别需要加上 `tbl:`和`fig:` 前缀才能正常显示编号。
+
+#align(center, (stack(dir: ltr)[
+ #figure(
+ table(
+ align: center + horizon,
+ columns: 4,
+ [t], [1], [2], [3],
+ [y], [0.3s], [0.4s], [0.8s],
+ ),
+ caption: [常规表],
+ )
+][
+ #h(50pt)
+][
+ #figure(
+ table(
+ columns: 4,
+ stroke: none,
+ table.hline(),
+ [t], [1], [2], [3],
+ table.hline(stroke: .5pt),
+ [y], [0.3s], [0.4s], [0.8s],
+ table.hline(),
+ ),
+ caption: [三线表],
+ )
+]))
+
+== 图片
+#figure(
+ image("logos/1.svg", width: 20%),
+ caption: [图片测试],
+)
+
+
+// 手动分页
+#if twoside {
+ pagebreak() + " "
+}
+
+
+
+
+// ------------------------------------------- //
+
+
+
+= 数 学
+
+可以像 Markdown 一样写行内公式 $x + y$,以及带编号的行间公式:
+
+$ phi.alt := (1 + sqrt(5)) / 2 $
+
+引用数学公式需要加上 `eqt:` 前缀,则由@eqt:ratio,我们有:
+
+$ F_n = floor(1 / sqrt(5) phi.alt^n) $
+
+我们也可以通过 `<->` 标签来标识该行间公式不需要编号
+
+$ y = integral_1^2 x^2 dif x $ <->
+
+而后续数学公式仍然能正常编号。
+
+$ F_n = floor(1 / sqrt(5) phi.alt^n) $
+
+== 参考文献
+
+可以像这样引用参考文献 @丁文祥2000:图书#[@蒋有绪1998]和会议#[@中国力学学会1990]。
+
+== 代码块
+
+代码块支持语法高亮。引用时需要加上 `lst:` @lst:code
+
+#figure(
+ ```py
+ def add(x, y):
+ return x + y
+ ```,
+ caption:[代码块],
+)
+
+
+// 手动分页
+#if twoside {
+ pagebreak() + " "
+}
+
+
+
+// ------------------------------------------- //
+
+
+
+= 化 学
+
+#align(center, (stack(dir: ttb)[
+ #figure(
+ table(
+ align: center + horizon,
+ columns: 2,
+ [化学式], [示例],
+ [$ #ca("H2O") $], [水],
+ [$ #ca("NH3") $], [氨],
+ [$ #ca("CO2") $], [二氧化碳],
+ [$ #ca("H+") $], [氢离子],
+ [$ #ca("Ca(H2PO4)2") $], [磷酸氢钙],
+ [$ #ca("NCl2") $], [二氯化氮],
+ [$ #ca("H^1") $], [氢同位素H-1],
+ [$ #ca("H^2") $], [氘H-2],
+ [$ #ca("H^3") $], [氚H-3],
+ [$ #ca("C^12") $], [碳-12],
+ [$ #ca("C^14") $], [碳-14],
+ [$ #ca("O^16") $], [氧-16],
+ [$ #ca("O^18") $], [氧-18],
+ ),
+ caption: [化学式示例表],
+ )
+][
+ #v(100pt)
+][
+ #figure(
+ table(
+ columns: 2,
+ stroke: none,
+ table.hline(),
+ [$ #cb("2KMnO4 = K2MnO4 + MnO2 + O2>", a: $Delta$) $], [氧化还原反应],
+ [$ #cb("N2 + 3H2 <=> 2NH3", a: "高温加热", b: "催化剂") $], [合成氨反应],
+ [$ #cb("2H2O <=> 2H2 + O2", a: "电解", b: "电流") $], [水的电解反应],
+ [$ #cb("H2O + D2O -> 2HDO", a: "同位素交换反应") $], [氘水反应],
+ [$ #cb("BaCl2 + Na2SO4 -> BaSO4(s)< + 2NaCl", a: "沉淀反应") $], [沉淀反应],
+ ),
+ caption: [化学方程式示例],
+ )
+]))
+
+
+
+// 手动分页
+#if twoside {
+ pagebreak() + " "
+}
+
+
+
+// ------------------------------------------- //
+
+
+
+= 定 理
+
+== 定理环境
+#show: thmrules.with(qed-symbol: $square$)
+
+#theorem("Euclid")[
+ There are infinitely many primes.
+]
+
+#definition[
+ A natural number is called a #highlight[_prime number_] if it is greater
+ than 1 and cannot be written as the product of two smaller natural numbers.
+]
+
+#example[
+ The numbers $2$, $3$, and $17$ are prime.
+ @cor_largest_prime shows that this list is not exhaustive!
+]
+
+#proof[
+ Suppose to the contrary that $p_1, p_2, dots, p_n$ is a finite enumeration
+ of all primes. Set $P = p_1 p_2 dots p_n$. Since $P + 1$ is not in our list,
+ it cannot be prime. Thus, some prime factor $p_j$ divides $P + 1$. Since
+ $p_j$ also divides $P$, it must divide the difference $(P + 1) - P = 1$, a
+ contradiction.
+]
+
+#corollary[
+ There is no largest prime number.
+]
+
+#corollary[
+ There are infinitely many composite numbers.
+]
+
+#theorem[
+ There are arbitrarily long stretches of composite numbers.
+]
+
+#proof[
+ For any $n > 2$, consider $
+ n! + 2, quad n! + 3, quad ..., quad n! + n
+ $
+]
+
+
+// // 手动分页
+// #if twoside {
+// pagebreak() + " "
+// }
+
+
+
+// ------------------------------------------- //
+
+
+
+// 中英双语参考文献
+// 默认使用 gb-7714-2015-numeric 样式
+#bilingual-bibliography(full: true)
+
+
+// 手动分页
+#if twoside {
+ pagebreak() + " "
+}
+
+
+// 一个别的引用样式
+// #bibliography(
+// "./ref.bib",
+// title: "References",
+// style: "ieee"
+// )
+
+
+
+// ------------------------------------------- //
+
+
+
+// 致谢
+#acknowledgement[
+ 感谢 XXX,感谢 XXX 模板。
+]
+
+
+// 手动分页
+#if twoside {
+ pagebreak() + " "
+}
+
+
+
+// ------------------------------------------- //
+
+
+
+// 附录
+#show: appendix
+
+= 附录
+
+== 附录子标题
+
+=== 附录子子标题
+
+附录内容,这里也可以加入图片,例如@fig:appendix-img。
+
+#figure(
+ image("logos/1.svg", width: 20%),
+ caption: [图片测试],
+)
+
+
+// 手动分页
+#if twoside {
+ pagebreak() + " "
+}
+
+
+// 正文结束标志,不可缺少
+// 这里放在附录后面,使得页码能正确计数
+#mainmatter-end()
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/thumbnail.png b/packages/preview/modern-cqut-thesis/0.1.0/thumbnail.png
new file mode 100644
index 000000000..c994e5e60
Binary files /dev/null and b/packages/preview/modern-cqut-thesis/0.1.0/thumbnail.png differ
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/typst.toml b/packages/preview/modern-cqut-thesis/0.1.0/typst.toml
new file mode 100644
index 000000000..f969acb0a
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/typst.toml
@@ -0,0 +1,16 @@
+[package]
+name = "modern-cqut-thesis"
+version = "0.1.0"
+entrypoint = "lib.typ"
+authors = ["aFei-CQUT"]
+license = "MIT"
+description = "重庆理工大学学位论文模板。 A Thesis Tamplate for CQUT."
+repository = "https://github.com/aFei-CQUT/modern-cqut-thesis"
+keywords = ["Chongqing University of Technology", "thesis"]
+categories = ["thesis"]
+exclude = []
+
+[template]
+path = "template"
+entrypoint = "thesis.typ"
+thumbnail = "thumbnail.png"
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/anti-matter.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/anti-matter.typ
new file mode 100644
index 000000000..e6517b928
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/anti-matter.typ
@@ -0,0 +1,204 @@
+// 导出 anti-matter 中的函数
+#let (
+ anti-front-end,
+ anti-inner-end,
+ anti-outer-counter,
+ anti-inner-counter,
+ anti-active-counter-at,
+ anti-page-at,
+ anti-page,
+ anti-header,
+ anti-thesis,
+ anti-matter,
+) = {
+ // TODO: 我认为可以移除spec,改用loc.page-numbering()
+
+ // 验证spec
+ let assert-spec-valid(spec) = {
+ if type(spec) != dictionary {
+ panic("spec必须是一个字典,而不是 " + type(spec))
+ }
+
+ if spec.len() != 3 {
+ panic("spec必须恰好包含3个元素,而不是 " + str(spec.len()))
+ }
+
+ if "front" not in spec { panic("缺少front键") }
+ if "inner" not in spec { panic("缺少inner键") }
+ if "back" not in spec { panic("缺少back键") }
+ }
+
+ let meta-label =
+ let key-front-end = "anti-matter:front-end"
+ let key-inner-end = "anti-matter:inner-end"
+
+ // 获取给定位置的事项和修正
+ let where-am-i(spec, loc) = {
+ let markers = query(meta-label)
+
+ assert.eq(
+ markers.len(),
+ 2,
+ message: "必须恰好有两个标记(不要使用 )"
+ )
+ assert.eq(markers.at(0).value, key-front-end, message: "第一个标记必须是前端标记")
+ assert.eq(markers.at(1).value, key-inner-end, message: "第二个标记必须是内部结束标记")
+
+ let front-matter = markers.first().location()
+ let inner-matter = markers.last().location()
+
+ let front-matter-end = counter(page).at(front-matter).at(0)
+ let inner-matter-end = counter(page).at(inner-matter).at(0)
+
+ if loc.page() <= front-matter.page() {
+ ("front", spec.front, 0)
+ } else if front-matter.page() < loc.page() and loc.page() <= inner-matter.page() {
+ ("inner", spec.inner, front-matter-end)
+ } else {
+ ("back", spec.back, inner-matter-end - front-matter-end)
+ }
+ }
+
+ /// 标记文档前端事项的结束,将其放在前端事项的最后一页。
+ /// 确保将其放在尾随的`pagebreaks`之前。
+ ///
+ /// -> content
+ let anti-front-end() = [#metadata(key-front-end) #meta-label]
+
+ /// 标记文档内部事项的结束,将其放在内部事项的最后一页。
+ /// 确保将其放在尾随的`pagebreaks`之前。
+ ///
+ /// -> content
+ let anti-inner-end() = [#metadata(key-inner-end) #meta-label]
+
+ /// 返回文档前端和后端事项的计数器。
+ ///
+ /// -> counter
+ let anti-outer-counter() = counter("anti-matter:outer")
+
+ /// 返回文档主要内容的计数器。
+ ///
+ /// -> counter
+ let anti-inner-counter() = counter("anti-matter:inner")
+
+ /// 返回给定位置的活动计数器。这可用于在特定位置设置页面计数器。
+ ///
+ /// - spec (dictionary): 文档的规格,参见 @@anti-matter
+ /// - loc (location): 获取活动计数器的位置
+ /// -> counter
+ let anti-active-counter-at(spec, loc) = {
+ let (matter, _, _) = where-am-i(spec, loc)
+
+ if matter == "inner" {
+ anti-inner-counter()
+ } else {
+ anti-outer-counter()
+ }
+ }
+
+ /// 使用默认规格,共享外部编号和计数器。
+ ///
+ /// 返回的字典简单地包含`front`、`inner`和`back`键的编号。
+ ///
+ /// - outer (string, function): 用于前端和后端事项的编号
+ /// - inner (string, function): 用于文档主要内容的编号
+ /// -> dictionary
+ let anti-thesis(outer: "I", inner: "1") = (
+ front: outer,
+ inner: inner,
+ back: outer,
+ )
+
+ /// 返回给定位置的页面编号,根据规格进行必要的调整和编号。
+ ///
+ /// - spec (dictionary): 文档的规格,参见 @@anti-matter
+ /// - loc (location): 评估编号的位置
+ /// -> content
+ let anti-page-at(spec, loc) = {
+ let (_, num, correction) = where-am-i(spec, loc)
+
+ let vals = counter(page).at(loc)
+ vals.at(0) = vals.at(0) - correction
+
+ numbering(num, ..vals)
+ }
+
+ /// 返回给定位置的格式化页码,根据规格进行必要的调整和编号。
+ ///
+ /// - spec (dictionary): 描述文档编号的规格,参见 @@anti-matter
+ /// -> content
+ let anti-page(spec) = context {
+ let loc = here()
+ anti-page-at(spec, loc)
+ }
+
+ /// 渲染页眉,同时维护anti-matter计数器步进。
+ ///
+ /// - spec (dictionary): 描述文档编号的规格,参见 @@anti-matter
+ /// - header (content): 要渲染的页眉
+ /// -> content
+ let anti-header(spec, header) = {
+ context {
+ let loc = here()
+ anti-active-counter-at(spec, loc).step()
+ }
+ header
+ }
+
+ /// 应用页面编号和outline.entry的show规则以修复其页面编号的模板函数。
+ /// 如果需要更细粒度地控制大纲条目和页眉,请参阅库文档。
+ /// 这可以用于show规则。参数会被验证。
+ ///
+ /// - spec (dictionary): 描述文档编号的规格,参见 @@anti-matter
+ /// - debug (bool): 在页眉中显示当前事项和相关信息
+ /// - body (content): 要使用anti-matter编号渲染的内容
+ /// -> content
+ let anti-matter(
+ spec: anti-thesis(),
+ debug: false,
+ body,
+ ) = {
+ assert-spec-valid(spec)
+
+ set page(
+ header: if debug {
+ context {
+ let loc = here()
+ anti-header(spec)[
+ #let (matter, numbering, correction) = where-am-i(spec, loc)
+ #(matter: matter, numbering: numbering, correction: correction)
+ ]
+ }
+ } else {
+ anti-header(spec, none)
+ },
+ numbering: (..args) => anti-page(spec),
+ )
+ show outline.entry: it => {
+ link(it.element.location(), it.body)
+ if it.fill != none {
+ [ ]
+ box(width: 1fr, it.fill)
+ [ ]
+ } else {
+ h(1fr)
+ }
+ link(it.element.location(), anti-page-at(spec, it.element.location()))
+ }
+
+ body
+ }
+
+ (
+ anti-front-end,
+ anti-inner-end,
+ anti-outer-counter,
+ anti-inner-counter,
+ anti-active-counter-at,
+ anti-page-at,
+ anti-page,
+ anti-header,
+ anti-thesis,
+ anti-matter,
+ )
+}
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/bilingual-bibliography.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/bilingual-bibliography.typ
new file mode 100644
index 000000000..0e71f32fb
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/bilingual-bibliography.typ
@@ -0,0 +1,144 @@
+// Authors: csimide, OrangeX4
+// Tested only on GB-7714-2015-Numeric
+#let bilingual-bibliography(
+ bibliography: none,
+ title: "参考文献",
+ full: false,
+ style: "gb-7714-2015-numeric",
+ mapping: (:),
+ extra-comma-before-et-al-trans: false,
+ // 用于控制多位译者时表现为 `et al. tran`(false) 还是 `et al., tran`(true)
+ allow-comma-in-name: false,
+ // 如果使用的 CSL 中,英文姓名中会出现逗号,请设置为 true
+) = {
+ assert(bibliography != none, message: "请传入带有 source 的 bibliography 函数。")
+
+ // Please fill in the remaining mapping table here
+ mapping = (
+ //"等": "et al",
+ "卷": "Vol.",
+ "册": "Bk.",
+ // "译": ", tran",
+ // "等译": "et al. tran",
+ // 注: 请见下方译者数量判断部分。
+ ) + mapping
+
+ let to-string(content) = {
+ if content.has("text") {
+ content.text
+ } else if content.has("children") {
+ content.children.map(to-string).join("")
+ } else if content.has("child") {
+ to-string(content.child)
+ } else if content.has("body") {
+ to-string(content.body)
+ } else if content == [ ] {
+ " "
+ }
+ }
+
+ show grid.cell.where(x: 1): it => {
+ // 后续的操作是对 string 进行的。
+ let ittext = to-string(it)
+ // 判断是否为中文文献:去除特定词组后,仍有至少两个连续汉字。
+ let pureittext = ittext.replace(regex("[等卷册和版本章期页篇译间者(不详)]"), "")
+ if pureittext.find(regex("\p{sc=Hani}{2,}")) != none {
+ ittext
+ } else {
+ // 若不是中文文献,进行替换
+ // 第xxx卷、第xxx册的情况:变为 Vol. XXX 或 Bk. XXX。
+ let reptext = ittext
+ reptext = reptext.replace(
+ regex("(第\s?)?\d+\s?[卷册]"),
+ itt => {
+ if itt.text.contains("卷") {
+ "Vol. "
+ } else {
+ "Bk. "
+ }
+ itt.text.find(regex("\d+"))
+ },
+ )
+
+ // 第xxx版/第xxx本的情况:变为 1st ed 格式。
+ reptext = reptext.replace(
+ regex("(第\s?)?\d+\s?[版本]"),
+ itt => {
+ let num = itt.text.find(regex("\d+"))
+ num
+ if num.clusters().len() == 2 and num.clusters().first() == "1" {
+ "th"
+ } else {
+ (
+ "1": "st",
+ "2": "nd",
+ "3": "rd",
+ ).at(num.clusters().last(), default: "th")
+ }
+ " ed"
+ },
+ )
+
+ // 译者数量判断:单数时需要用 trans,复数时需要用 tran 。
+ /*
+ 注:
+ 1. 目前判断译者数量的方法非常草率:有逗号就是多个作者。但是在部分 GB/T 7714-2015 方言中,姓名中可以含有逗号。如果使用的 CSL 是姓名中含有逗号的版本,请将 bilingual-bibliography 的 allow-comma-in-name 参数设为 true。
+ 2. 在 GB/T 7714-2015 原文中有 `等译`(P15 10.1.3 小节 示例 1-[1] 等),但未给出相应的英文缩写翻译。CSL 社区库内的 GB/T 7714-2015 会使用 `等, 译` 和 `et al., tran` 的写法。为使中英文与标准原文写法一致,本小工具会译作 `et al. tran`。若需要添加逗号,请将 bilingual-bibliography 的 extra-comma-before-et-al-trans 参数设为 true。
+ 3. GB/T 7714-2015 P8 7.2 小节规定:“译”前需加逗号。因此单个作者的情形,“译” 会被替换为 ", trans"。与“等”并用时的情况请见上一条注。
+ 如果工作不正常,可以考虑换为简单关键词替换,即注释这段情况,取消 13 行 mapping 内 `译` 条目的注释。
+ */
+ reptext = reptext.replace(regex("\].+?译"), itt => {
+ // 我想让上面这一行匹配变成非贪婪的,但加问号后没啥效果?
+ let comma-in-itt = itt.text.replace(regex(",?\s?译"), "").matches(",")
+ if (
+ type(comma-in-itt) == array and
+ comma-in-itt.len() >= (
+ if allow-comma-in-name {2} else {1}
+ )
+ ) {
+ if extra-comma-before-et-al-trans {
+ itt.text.replace(regex(",?\s?译"), ", tran")
+ } else {
+ itt.text.replace(regex(",?\s?译"), " tran")
+ }
+ } else {
+ itt.text.replace(regex(",?\s?译"), ", trans")
+ }
+ })
+
+ // `等` 特殊处理:`等`后方接内容也需要译作 `et al.`,如 `等译` 需要翻译为 `et al. trans`
+ reptext = reptext.replace(
+ regex("等."),
+ itt => {
+ "et al."
+ // 如果原文就是 `等.`,则仅需简单替换,不需要额外处理
+ // 如果原文 `等` 后没有跟随英文标点,则需要补充一个空格
+ if not itt.text.last() in (".", ",", ";", ":", "[", "]", "/", "\\", "<", ">", "?", "(", ")", " ", "\"", "'") {
+ " "
+ }
+ // 原文有英文句号时不需要重复句号,否则需要将匹配到的最后一个字符吐回来
+ if not itt.text.last() == "." {
+ itt.text.last()
+ }
+ },
+ )
+
+ // 其他情况:直接替换
+ reptext = reptext.replace(
+ regex("\p{sc=Hani}+"),
+ itt => {
+ mapping.at(itt.text, default: itt.text)
+ // 注意:若替换功能工作良好,应该不会出现 `default` 情形
+ },
+ )
+ reptext
+ }
+ }
+
+ set text(lang: "zh")
+ bibliography(
+ title: title,
+ full: full,
+ style: style,
+ )
+}
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/chem-for.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/chem-for.typ
new file mode 100644
index 000000000..62d3ae28c
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/chem-for.typ
@@ -0,0 +1,88 @@
+#import "../utils/style.typ": 字体, 字号
+
+// 判断是否为英文字符
+#let isAlpha = (c) => {
+ return c >= "a" and c <= "z" or c >= "A" and c <= "Z"
+}
+
+// 判断是否为数字字符
+#let isDigit = (c) => {
+ return c >= "0" and c <= "9"
+}
+
+// 化学式显示
+#let ca = (s) => {
+ set text(font: "Libertinus Serif") // 设置化学式字体
+ let res = [] // 存储结果的数组
+ let f = false // 标记是否为上标
+ let p = false // 标记是否为元素符号的开始
+ for c in s { // 遍历字符串中的每个字符
+ if c == " " {
+ f = false
+ res += [#h(0.5em)] // 遇到空格则重置上标标记,并在结果中插入空白占位
+ continue
+ } else if c == "^" {
+ f = true // '^' 用于标记之后字符为上标显示
+ continue
+ }
+
+ if not p { // 如果还没有识别到元素符号的开始
+ if isAlpha(c) {
+ p = true // 碰到字母时认为开始输入元素符号
+ } else {
+ res += [#c] // 若非字母,则直接添加该字符到结果中
+ continue
+ }
+ }
+
+ // 若 f 为 true,表示当前字符应以上标形式显示
+ if f {
+ res += [#super[#c]]
+ } else {
+ // 当不需要上标时,对字符进行进一步判断和处理
+ if c == "<" {
+ res += [$arrow.b$] // 将 '<' 转换为特定箭头符号
+ } else if c == ">" {
+ res += [$arrow.t$] // 将 '>' 转换为特定箭头符号
+ } else if c == "." {
+ res += [$dot$] // '.' 转换为点号
+ } else if c == "+" or c == "-" {
+ res += [#super[#c]] // 电荷符号以上标形式显示
+ } else if isDigit(c) {
+ res += [#sub[#c]] // 数字用下标显示
+ } else if not isAlpha(c) and not isDigit(c) {
+ res += [#text(font: 字体.宋体)[#c]] // 非字母和数字字符,使用宋体
+ } else {
+ res += [#c] // 普通字母直接添加
+ }
+ }
+ }
+ res // 返回处理后的结果数组
+}
+
+// 化学方程式显示
+#let cb = (s, a: none, b: none) => {
+ let ss = s.split(" ") // 将字符串按空格分割
+ let sym = $=$ // 默认符号为 '='
+ if "->" in s {
+ sym = $arrow.r.long$ // 若出现 '->' 则用长箭头表示
+ } else if "<=>" in s {
+ sym = $harpoons.rtlb$ // 若出现 '<=>' 则用双向箭头表示
+ }
+ let res = []
+ for sa in ss {
+ if sa == "=" or sa == "->" or sa == "<=>" {
+ // 对方程式的连接符号进行特殊处理
+ if a != none and b != none {
+ res += [$#sym^(#text(font: 字体.宋体)[#a])_(#text(font: 字体.宋体)[#b])$]
+ } else if a != none {
+ res += [$#sym^scripts(#text(font: 字体.宋体)[#a])$]
+ } else {
+ res += [$#sym$] // 没有额外标记时,直接添加符号
+ }
+ } else {
+ res += [#ca(sa)] // 使用 ca 函数处理一般的化学式部分
+ }
+ }
+ res // 返回最终结果
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/cite-style.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/cite-style.typ
new file mode 100644
index 000000000..3166b3f43
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/cite-style.typ
@@ -0,0 +1,11 @@
+// 引用样式
+#let custom-cite = (it) => {
+ box(
+ width: auto,
+ height: auto,
+ fill: none,
+ stroke: 1.0pt + black,
+ inset: 2pt,
+ text(fill: green, it)
+ )
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/custom-cuti.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/custom-cuti.typ
new file mode 100644
index 000000000..2addc088a
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/custom-cuti.typ
@@ -0,0 +1 @@
+#import "@preview/cuti:0.2.1": *
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/custom-heading.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/custom-heading.typ
new file mode 100644
index 000000000..02eb87f30
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/custom-heading.typ
@@ -0,0 +1,50 @@
+// 展示一个标题
+#let heading-display(it) = {
+ if it != none {
+ if it.has("numbering") and it.numbering != none {
+ numbering(it.numbering, ..counter(heading).at(it.location()))
+ [ ]
+ }
+ it.body
+ } else {
+ ""
+ }
+}
+
+// 获取当前激活的 heading,参数 prev 用于标志优先使用之前页面的 heading
+#let active-heading(level: 1, prev: true, loc) = {
+ // 之前页面的标题
+ let prev-headings = query(selector(heading.where(level: level)).before(loc), loc)
+ // 当前页面的标题
+ let cur-headings = query(selector(heading.where(level: level)).after(loc), loc)
+ .filter(it => it.location().page() == loc.page())
+ if prev-headings.len() == 0 and cur-headings.len() == 0 {
+ return none
+ } else {
+ if prev {
+ if prev-headings.len() != 0 {
+ return prev-headings.last()
+ } else {
+ return cur-headings.first()
+ }
+ } else {
+ if cur-headings.len() != 0 {
+ return cur-headings.first()
+ } else {
+ return prev-headings.last()
+ }
+ }
+ }
+}
+
+// 获取当前页面的标题
+#let current-heading(level: 1, loc) = {
+ // 当前页面的标题
+ let cur-headings = query(selector(heading.where(level: level)).after(loc), loc)
+ .filter(it => it.location().page() == loc.page())
+ if cur-headings.len() != 0 {
+ return cur-headings.first()
+ } else {
+ return none
+ }
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/custom-numbering.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/custom-numbering.typ
new file mode 100644
index 000000000..a5c88476a
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/custom-numbering.typ
@@ -0,0 +1,30 @@
+// 一个简单的自定义 Numbering
+// 用法也简单,可以特殊设置一级等标题的样式,以及一个缺省值
+#let custom-numbering(base: 1, depth: 5, first-level: auto, second-level: auto, third-level: auto, format, ..args) = {
+ if (args.pos().len() > depth) {
+ return
+ }
+ if (first-level != auto and args.pos().len() == 1) {
+ if (first-level != "") {
+ numbering(first-level, ..args)
+ }
+ return
+ }
+ if (second-level != auto and args.pos().len() == 2) {
+ if (second-level != "") {
+ numbering(second-level, ..args)
+ }
+ return
+ }
+ if (third-level != auto and args.pos().len() == 3) {
+ if (third-level != "") {
+ numbering(third-level, ..args)
+ }
+ return
+ }
+ // default
+ if (args.pos().len() >= base) {
+ numbering(format, ..(args.pos().slice(base - 1)))
+ return
+ }
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/custom-tablex.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/custom-tablex.typ
new file mode 100644
index 000000000..29fe03bb0
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/custom-tablex.typ
@@ -0,0 +1 @@
+#import "@preview/tablex:0.0.8": *
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/datetime-display.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/datetime-display.typ
new file mode 100644
index 000000000..201203395
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/datetime-display.typ
@@ -0,0 +1,9 @@
+// 显示中文日期
+#let datetime-display(date) = {
+ date.display("[year] 年 [month] 月 [day] 日")
+}
+
+// 显示英文日期
+#let datetime-en-display(date) = {
+ date.display("[month repr:short] [day], [year]")
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/double-underline.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/double-underline.typ
new file mode 100644
index 000000000..6a0cd5bb2
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/double-underline.typ
@@ -0,0 +1,11 @@
+// 双下划线
+#let double-underline(body) = context {
+ let size = measure(body)
+ stack(
+ body,
+ v(3pt),
+ line(length: size.width),
+ v(2pt),
+ line(length: size.width),
+ )
+}
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/hline.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/hline.typ
new file mode 100644
index 000000000..afd563c66
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/hline.typ
@@ -0,0 +1,4 @@
+// 一条水平横线
+#let hline() = {
+ line(length: 100%)
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/indent.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/indent.typ
new file mode 100644
index 000000000..427bc09a1
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/indent.typ
@@ -0,0 +1,6 @@
+// 中文缩进
+#let indent = h(2em)
+
+// 假段落,附着于 heading 之后可以实现首行缩进
+#let empty-par = par[#box()]
+#let fake-par = context empty-par + v(-measure(empty-par + empty-par).height)
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/invisible-heading.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/invisible-heading.typ
new file mode 100644
index 000000000..f16fa8081
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/invisible-heading.typ
@@ -0,0 +1,5 @@
+// 用于创建一个不可见的标题,用于给 outline 加上短标题
+#let invisible-heading(..args) = {
+ set text(size: 0pt, fill: white)
+ heading(numbering: none, ..args)
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/justify-text.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/justify-text.typ
new file mode 100644
index 000000000..318027d13
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/justify-text.typ
@@ -0,0 +1,9 @@
+// 双端对其一段小文本,常用于表格的中文 key
+#let justify-text(with-tail: false, tail: ":", body) = {
+ if with-tail and tail != "" {
+ stack(dir: ltr, stack(dir: ltr, spacing: 1fr, ..body.split("").filter(it => it != "")), tail)
+ } else {
+ stack(dir: ltr, spacing: 1fr, ..body.split("").filter(it => it != ""))
+ }
+}
+
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/style.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/style.typ
new file mode 100644
index 000000000..dcdc41812
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/style.typ
@@ -0,0 +1,42 @@
+#let 字号 = (
+ 初号: 42pt,
+ 小初: 36pt,
+ 一号: 26pt,
+ 小一: 24pt,
+ 二号: 22pt,
+ 小二: 18pt,
+ 三号: 16pt,
+ 小三: 15pt,
+ 四号: 14pt,
+ 中四: 13pt,
+ 小四: 12pt,
+ 五号: 10.5pt,
+ 小五: 9pt,
+ 六号: 7.5pt,
+ 小六: 6.5pt,
+ 七号: 5.5pt,
+ 小七: 5pt,
+)
+
+#let 字体 = (
+ // 宋体,属于「有衬线字体」,一般可以等同于英文中的 Serif Font
+ 宋体: ("Times New Roman", "SimSun"),
+ // 黑体,属于「无衬线字体」,一般可以等同于英文中的 Sans Serif Font
+ 黑体: ("Arial", "SimHei" ),
+ // 等宽字体,用于代码块环境,一般可以等同于英文中的 Monospaced Font
+ 等宽: ("Consolas", "FangSong"),
+ 楷体: ("Times New Roman", "KaiTi"),
+ 仿宋: ("Times New Roman", "FangSong"),
+)
+
+//「新罗马体(有衬线英文字体)」、「思源宋体(简体)」、「思源宋体」、「宋体(Windows)」、「宋体(MacOS)」
+// "Times New Roman", "Source Han Serif SC", "Source Han Serif", "Noto Serif CJK SC", "SimSun", "Songti SC", "STSongti"
+
+// 「Arial(无衬线英文字体)」、「思源黑体(简体)」、「思源黑体」、「黑体(Windows)」、「黑体(MacOS)」
+// "Arial", "Source Han Sans SC", "Source Han Sans", "Noto Sans CJK SC", "SimHei", "Heiti SC", "STHeiti"
+
+// 「Courier New(Windows 等宽英文字体)」、「思源等宽黑体(简体)」、「思源等宽黑体」、「黑体(Windows)」、「黑体(MacOS)」
+
+// "FangSong SC", "STFangSong", "FZFangSong-Z02S", "Noto Serif CJK SC"
+
+// "Kaiti SC", "STKaiti", "FZKai-Z03S", "Noto Serif CJK SC"
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/theorem.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/theorem.typ
new file mode 100644
index 000000000..5ad5c1b63
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/theorem.typ
@@ -0,0 +1,165 @@
+#import "@preview/ctheorems:1.1.3": *
+#import "@preview/showybox:2.0.3": showybox
+#import "../utils/style.typ": 字号, 字体
+
+#let colors = (
+ rgb("#9E9E9E"),
+ rgb("#F44336"),
+ rgb("#E91E63"),
+ rgb("#9C27B0"),
+ rgb("#673AB7"),
+ rgb("#3F51B5"),
+ rgb("#2196F3"),
+ rgb("#03A9F4"),
+ rgb("#00BCD4"),
+ rgb("#009688"),
+ rgb("#4CAF50"),
+ rgb("#8BC34A"),
+ rgb("#CDDC39"),
+ rgb("#FFEB3B"),
+ rgb("#FFC107"),
+ rgb("#FF9800"),
+ rgb("#FF5722"),
+ rgb("#795548"),
+ rgb("#9E9E9E"),
+)
+
+
+#show: thmrules
+
+
+
+#show math.equation: set text(weight: 400)
+
+#let thmtitle(t, color: rgb("#000000")) = {
+ return text(font: 字体.黑体, weight: "semibold", fill: color)[#t]
+}
+#let thmname(t, color: rgb("#000000")) = {
+ return text(font: 字体.黑体, fill: color)[(#t)]
+}
+
+#let thmtext(t, color: rgb("#000000")) = {
+ let a = t.children
+ if (a.at(0) == [ ]) {
+ a.remove(0)
+ }
+ t = a.join()
+
+ return text(font: 字体.宋体, fill: color)[#t]
+}
+
+#let thmbase(
+ identifier,
+ head,
+ ..blockargs,
+ supplement: auto,
+ padding: (top: 0.5em, bottom: 0.5em),
+ namefmt: x => [(#x)],
+ titlefmt: strong,
+ bodyfmt: x => x,
+ separator: [#h(0.1em)\ ],
+ base: "heading",
+ base-level: none,
+) = {
+ if supplement == auto {
+ supplement = head
+ }
+ let boxfmt(name, number, body, title: auto, ..blockargs_individual) = {
+ if not name == none {
+ name = [ #namefmt(name)]
+ } else {
+ name = []
+ }
+ if title == auto {
+ title = head
+ }
+ if not number == none {
+ title += " " + number
+ }
+ title = titlefmt(title)
+ body = bodyfmt(body)
+ pad(
+ ..padding,
+ showybox(
+ width: 100%,
+ radius: 0.3em,
+ breakable: true,
+ padding: (top: 0em, bottom: 0em),
+ ..blockargs.named(),
+ ..blockargs_individual.named(),
+ [#title#name#titlefmt(separator)#body],
+ ),
+ )
+ }
+
+ let auxthmenv = thmenv(
+ identifier,
+ base,
+ base-level,
+ boxfmt,
+ ).with(supplement: supplement)
+
+ return auxthmenv.with(numbering: "1.1")
+}
+
+#let styled-thmbase = thmbase.with(titlefmt: thmtitle, namefmt: thmname, bodyfmt: thmtext)
+
+#let builder-thmbox(color: rgb("#000000"), ..builderargs) = styled-thmbase.with(
+ titlefmt: thmtitle.with(color: color.darken(30%)),
+ bodyfmt: thmtext.with(color: color.darken(70%)),
+ namefmt: thmname.with(color: color.darken(30%)),
+ frame: (
+ body-color: color.lighten(92%),
+ border-color: color.darken(10%),
+ thickness: 1.5pt,
+ inset: 1.2em,
+ radius: 0.3em,
+ ),
+ ..builderargs,
+)
+
+#let builder-thmline(color: rgb("#000000"), ..builderargs) = styled-thmbase.with(
+ titlefmt: thmtitle.with(color: color.darken(30%)),
+ bodyfmt: thmtext.with(color: color.darken(70%)),
+ namefmt: thmname.with(color: color.darken(30%)),
+ frame: (
+ body-color: color.lighten(92%),
+ border-color: color.darken(10%),
+ thickness: (left: 2pt),
+ inset: 1.2em,
+ radius: 0em,
+ ),
+ ..builderargs,
+)
+
+#let problem-style = builder-thmbox(color: colors.at(16), shadow: (offset: (x: 0pt, y: 0pt), color: luma(70%)))
+
+#let problem = problem-style("problem", "例题")
+
+#let theorem-style = builder-thmbox(color: colors.at(6), shadow: (offset: (x: 0pt, y: 0pt), color: luma(70%)))
+
+#let theorem = theorem-style("theorem", "定理")
+#let lemma = theorem-style("lemma", "引理")
+#let corollary = theorem-style("corollary", "推论")
+
+#let definition-style = builder-thmline(color: colors.at(8))
+
+#let definition = definition-style("definition", "定义")
+#let proposition = definition-style("proposition", "命题")
+#let remark = definition-style("remark", "结论")
+#let observation = definition-style("observation", "易知")
+
+#let example-style = builder-thmline(color: colors.at(16))
+
+#let example = example-style("example", "例题")
+
+#let proof(body, name: none) = {
+ thmtitle[证明]
+ if name != none {
+ [ #thmname[#name]]
+ }
+ thmtitle[:]
+ body
+ h(1fr)
+ // $square$
+}
\ No newline at end of file
diff --git a/packages/preview/modern-cqut-thesis/0.1.0/utils/unpairs.typ b/packages/preview/modern-cqut-thesis/0.1.0/utils/unpairs.typ
new file mode 100644
index 000000000..6931e95bd
--- /dev/null
+++ b/packages/preview/modern-cqut-thesis/0.1.0/utils/unpairs.typ
@@ -0,0 +1,8 @@
+// 将 pairs 数组转成 dict 字典
+#let unpairs(pairs) = {
+ let dict = (:)
+ for pair in pairs {
+ dict.insert(..pair)
+ }
+ dict
+}
\ No newline at end of file