Skip to content

Commit

Permalink
feat: add word counter, optimize bachelor thesis format.
Browse files Browse the repository at this point in the history
Signed-off-by: Juntong Chen <[email protected]>
  • Loading branch information
jtchen2k committed Jan 12, 2025
1 parent 9489f93 commit f6909dd
Show file tree
Hide file tree
Showing 22 changed files with 489 additions and 54 deletions.
51 changes: 46 additions & 5 deletions packages/preview/modern-ecnu-thesis/0.1.0/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,24 @@
- 优化段落缩进
- 优化对多行标题 / 院系的处理逻辑
- 优化开启 `twoside` 参数后的页码逻辑
- 增加字数统计功能

对于研究生,我们参考华东师范大研究生院于 2023 年发布的[华东师范大学博士、硕士学位论文基本格式要求](https://yjsy.ecnu.edu.cn/8e/62/c42090a429666/page.htm);对于本科生,我们参考华东师范大学教务处于 2021 年更新的[华东师范大学本科生毕业论文(设计)格式要求](http://www.jwc.ecnu.edu.cn/d4/be/c40573a513214/page.htm)。格式适配于 2025 年初,后续使用的同学请留意参考校方的最新通知。

![1736471485839](https://jtchen.s3.ap-northeast-1.amazonaws.com/v1/img/2025/01/09/1736471485839.png)
![1736643710702](https://jtchen.s3.ap-northeast-1.amazonaws.com/v1/img/2025/01/11/1736643710702.png)

在这里可以找到硕士学位论文的示例文档:[thesis.pdf](https://github.com/jtchen2k/modern-ecnu-thesis/releases/download/0.1.0/thesis.pdf)
示例文档:
- 本科学位论文 [modern-ecnu-thesis-bachelor.pdf](https://github.com/jtchen2k/modern-ecnu-thesis/releases/latest/download/modern-ecnu-thesis-bachelor.pdf)
- 硕士学位论文,学术学位 [modern-ecnu-thesis-master-academic.pdf](https://github.com/jtchen2k/modern-ecnu-thesis/releases/latest/download/modern-ecnu-thesis-master-academic.pdf)
- 硕士学位论文,专业学位 [modern-ecnu-thesis-master-professional.pdf](https://github.com/jtchen2k/modern-ecnu-thesis/releases/latest/download/modern-ecnu-thesis-master-professional.pdf)
- 博士学位论文,学术学位 [modern-ecnu-thesis-doctor-academic.pdf](https://github.com/jtchen2k/modern-ecnu-thesis/releases/latest/download/modern-ecnu-thesis-doctor-academic.pdf)
- 博士学位论文,专业学位 [modern-ecnu-thesis-doctor-professional.pdf](https://github.com/jtchen2k/modern-ecnu-thesis/releases/latest/download/modern-ecnu-thesis-doctor-professional.pdf)

## Why Typst

> 天下苦 LaTeX 久矣。
Typst 是一个基于 Rust 的现代化的排版引擎。它具备类似 Markdown 的简洁语法、清晰的错误提示、实时预览级的编译性能,又同时具备和 LaTeX 一样精准的排版控制和图灵完备的脚本能力。自 2023 年 4 月开源发布以来,已获得 ![](https://img.shields.io/github/stars/typst/typst?style=flat)。现代化的 Typst 可以让你更加专注于论文内容本身,而不被 LaTeX 漫长的编译时间与难以阅读的输出日志困扰。

## Usage

Expand Down Expand Up @@ -66,16 +78,45 @@ ln -s </path/to/modern-ecnu-thesis> $DATA_DIR/typst/packages/preview/modern-ecnu

## Tips

默认模板有一些示例代码,清空前请留意。

### 字数统计

模板内置了字数统计功能。统计时会除去标题与标点符号,默认包括了正文与附录的所有内容。一个英语单词或一个 CJK 汉字将会被统计为一个 word,一个任意字符会被统计为一个 char。默认的统计范围为正文 + 附录,这取决于文中 `#show: word-count-cjk` 的位置。如果希望包括摘要、目录等能容,将这一行移动到 `#show: preface` 的下一行即可。

如需统计字数,可以使用 `make count` 命令,你会得到类似如下的输出:

```
#word: 100
#char: 200
```

具体而言,该命令使用 `typst query` 命令来查询嵌入在 `mainmatter.typ` 里的包含字数信息的 `metadata`。你也可以在正文中使用 `total-words-cjk``total-characters` 或使用以下代码来显示总字数 / 字符数:

```typst
context state("total-words-cjk").final()
context state("total-characters").final()
```

### 从 LaTeX 到 Typst

- Typst 支持的图片格式包括 png, jpeg, gif 与 svg,不支持 pdf 与 eps。你可以使用 InkSpace 或 [pdf2svg](https://github.com/dawbarton/pdf2svg) 等工具将 pdf 转换为 svg 格式:

```bash
pdf2svg input.pdf output.svg
```

- Typst 现在已经支持图片的浮动排版了。你可以使用 `figure``placement` 属性来控制图片位置。
- Typst 有一套自己的公式语法,与 LaTeX 大同小异且更加简洁。如果你已经十分熟悉 LaTeX 的语法并希望使用,可以使用 [MiTeX](https://github.com/mitex-rs/mitex),它将允许你在 Typst 中使用 LaTeX 数学语法。
- Typst 现在已经支持图片的浮动排版了。你可以使用 `figure``placement` 属性来控制图片位置,可以实现类似 LaTeX 的 `[htbp]` 功能:

```typst
figure {
placement: "top";
caption: "image caption";
...
}[#image("...)] <label>
```
- Typst 有一套自己的公式语法,与 LaTeX 大同小异且更加简洁。如果你已经十分熟悉 LaTeX 的语法并希望继续使用,可以引入 [MiTeX](https://github.com/mitex-rs/mitex),它将允许你在 Typst 中使用 LaTeX 数学语法。
- Typst 原生兼容了 biblatex 引用格式,直接修改 ref.bib 即可。
- 默认模板有一些示例代码,清空前请留意。
更多 Typst 的介绍、学习资料与项目背景可参考[上游项目](https://github.com/nju-lug/modern-nju-thesis)的 README。
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
#import "@preview/i-figured:0.2.4"
#import "../utils/custom-numbering.typ": custom-numbering
#import "../utils/style.typ": 字号, 字体
#import "../utils/invisible-heading.typ": invisible-heading

// 后记,重置 heading 计数器
#let appendix(
doctype: "master",
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,
fonts: (:),
it,
) = {
set heading(numbering: numbering)
Expand All @@ -20,5 +24,6 @@
show figure: show-figure
// 设置 equation 的编号
show math.equation.where(block: true): show-equation

it
}
27 changes: 22 additions & 5 deletions packages/preview/modern-ecnu-thesis/0.1.0/layouts/mainmatter.typ
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#import "../utils/indent.typ": fake-par
#import "../utils/unpairs.typ": unpairs
#import "../utils/pagebreak-from-odd.typ": pagebreak-from-odd
#import "../utils/word-counter.typ": *

#let mainmatter(
// documentclass 传入参数
Expand Down Expand Up @@ -46,6 +47,8 @@
show-figure: i-figured.show-figure,
// equation 计数
show-equation: i-figured.show-equation,
// heading 文字(本科生论文需要)
heading-extra: "华东师范大学本科毕业论文",
..args,
it,
) = {
Expand Down Expand Up @@ -154,10 +157,14 @@
// 4.1 设置标题的 Numbering
set heading(numbering: numbering)
// 4.2 设置字体字号并加入假段落模拟首行缩进
show heading: it => {
show heading: it => context {
set text(
font: array-at(heading-font, it.level),
size: array-at(heading-size, it.level),
size: if it.level == 1 {
if state("in-mainmatter").get() { array-at(heading-size, it.level) } else {
if doctype == "bachelor" { 字号.小三 } else { 字号.三号 }
}
} else { 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))))
Expand All @@ -170,15 +177,15 @@
fake-par
}
// 4.3 标题居中与自动换页
show heading: it => {
show heading: it => context {
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))
set align(if state("in-mainmatter").get() { array-at(heading-align, it.level) } else { center })
it
} else {
it
Expand Down Expand Up @@ -215,8 +222,18 @@
)
}))

it
// 字数统计(正文 + 附录)
// typst query main.typ '<total-words>' 2>/dev/null --field value --one

context [
#metadata(state("total-words-cjk").final()) <total-words>
#metadata(state("total-characters").final()) <total-chars>
]

let s = state("in-mainmatter", true)
context s.update(true)

it
// 正文结束标志,不可缺少
// 这里放在附录后面,使得页码能正确计数
fence()
Expand Down
49 changes: 39 additions & 10 deletions packages/preview/modern-ecnu-thesis/0.1.0/lib.typ
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* @project: modern-ecnu-thesis
* @author: OrangeX4, Juntong Chen ([email protected])
* @created: 2025-01-06 22:37:34
* @modified: 2025-01-10 01:58:02
* @modified: 2025-01-11 16:46:35
*
* 华东师范大学学位论文模板
* Repo: https://github.com/jtchen2k/modern-ecnu-thesis
Expand Down Expand Up @@ -39,6 +39,7 @@
#import "utils/custom-heading.typ": heading-display, active-heading, current-heading
#import "utils/indent.typ": indent, fake-par, no-indent
#import "utils/panic-page.typ": panic-page
#import "utils/word-counter.typ": *
#import "@preview/i-figured:0.2.4": show-figure, show-equation
#import "utils/style.typ": 字体, 字号

Expand All @@ -53,6 +54,15 @@
fonts: (:), // 字体,应传入「宋体」、「黑体」、「楷体」、「仿宋」、「等宽」
info: (:),
) = {

// 开发用,用 sys input 覆盖 doctype 以方便编译多种类型的文档
if "doctype" in sys.inputs {
doctype = sys.inputs.at("doctype")
}
if "degree" in sys.inputs {
degree = sys.inputs.at("degree")
}

// 默认参数
fonts = 字体 + fonts
info = (
Expand Down Expand Up @@ -104,13 +114,32 @@
preface(doctype: doctype, twoside: twoside, ..args)
},
mainmatter: (..args) => {
mainmatter(doctype: doctype, twoside: twoside, display-header: true, ..args, fonts: fonts + args.named().at("fonts", default: (:)))
if doctype == "bachelor" {
mainmatter(doctype: doctype, twoside: twoside, display-header: true,
heading-size: (字号.小四, 字号.小四,),
numbering: custom-numbering.with(first-level: "1. ", depth: 4, "1.1 "),
heading-align: (left, auto),
heading-above: (0em, 1.8em),
heading-below: (1.8em, 1.5em),
..args, fonts: fonts + args.named().at("fonts", default: (:)))
} else {
mainmatter(doctype: doctype, twoside: twoside, display-header: true, ..args, fonts: fonts + args.named().at("fonts", default: (:)))
}
},
mainmatter-end: (..args) => {
mainmatter-end(..args)
},
appendix: (..args) => {
appendix(..args)
if doctype == "bachelor" {
appendix(
doctype: doctype,
numbering: custom-numbering.with(first-level: "", depth: 4, "1.1 "),
..args,
fonts: fonts + args.named().at("fonts", default: (:))
)
} else {
appendix(doctype: doctype, ..args)
}
},
// 字体展示页
fonts-display-page: (..args) => {
Expand Down Expand Up @@ -227,12 +256,12 @@
doctype: doctype,
twoside: twoside,
size: (字号.小四, 字号.小四),
font: (fonts.黑体, fonts.宋体),
font: (fonts.宋体, fonts.宋体),
weight: ("bold", "regular"),
title-text-args: (font: 字体.黑体, size: 字号.三号, weight: "bold"),
title-text-args: (font: 字体.黑体, size: 字号.小三, weight: "bold"),
show-heading: true,
vspace: (1.2em, 1em),
indent: (0em, 2.38em, 2em, 2.8em),
indent: (0em, 1.4em, 2em, 2.8em),
..args,
fonts: fonts + args.named().at("fonts", default: (:)),
)
Expand All @@ -256,7 +285,7 @@
list-of-figures(
twoside: twoside,
show-heading: true,
title-text-args: (font: 字体.黑体, size: 字号.三号, weight: "bold"),
title-text-args: (font: 字体.黑体, size: if doctype == "master" { 字号.三号 } else { 字号.小三 } , weight: "bold"),
doctype: doctype,
..args,
fonts: fonts + args.named().at("fonts", default: (:)),
Expand All @@ -269,7 +298,7 @@
twoside: twoside,
doctype: doctype,
show-heading: true,
title-text-args: (font: 字体.黑体, size: 字号.三号, weight: "bold"),
title-text-args: (font: 字体.黑体, size: if doctype == "master" { 字号.三号 } else { 字号.小三 } , weight: "bold"),
..args,
fonts: fonts + args.named().at("fonts", default: (:)),
)
Expand All @@ -280,8 +309,8 @@
notation(
twoside: twoside,
show-heading: true,
title-text-args: (font: 字体.黑体, size: 字号.三号, weight: "bold"),
doctype: doctype,
title-text-args: (font: 字体.黑体, size: if doctype == "master" { 字号.三号 } else { 字号.小三 } , weight: "bold"),
doctype: doctype,
..args,
fonts: fonts + args.named().at("fonts", default: (:)),
)
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
// 其他参数
keywords: (),
outline-title: "Abstract",
outlined: false,
outlined: true,
anonymous-info-keys: ("author-en", "supervisor-en", "supervisor-ii-en"),
leading: 1.28em,
spacing: 1.38em,
leading: 1.08em,
spacing: 1.25em,
body,
) = {
// 1. 默认参数
Expand Down Expand Up @@ -61,14 +61,12 @@
#invisible-heading(level: 1, outlined: outlined, outline-title)

#align(center)[
#set text(font: fonts.黑体, size: 字号.三号)
#context s.get()
#set text(font: fonts.黑体, size: 字号.小三)
Abstract
]

#v(1em)

*Abstract:*

#set text(font: fonts.宋体)

#[
Expand All @@ -77,8 +75,8 @@
#body
]

#v(1em)
#v(2.5em)

*Keywords: *_#(("",) + keywords.intersperse(", ")).sum()_
*Keywords: *#h(0.25em)#(("",) + keywords.intersperse(", ")).sum()
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
outline-title: "摘要",
outlined: true,
anonymous-info-keys: ("author", "supervisor", "supervisor-ii"),
leading: 1.28em,
spacing: 1.28em,
leading: 1.25em,
spacing: 1.25em,
body,
) = {
// 1. 默认参数
Expand Down Expand Up @@ -57,22 +57,20 @@
#invisible-heading(level: 1, outlined: outlined, outline-title)

#align(center)[
#set text(font: fonts.黑体, size: 字号.三号)
#context s.get()
#set text(font: fonts.黑体, size: 字号.小三)
摘要
]

#v(1em)
#text(font: fonts.黑体)[摘要:]

#set text(font: fonts.宋体)
#set text(font: fonts.宋体, size: 字号.五号)

#[
#set par(first-line-indent: 2em)
#fake-par
#body
]

#v(1em)
#v(2.5em)

#text(font: fonts.黑体)[关键词:]#(("",)+ keywords.intersperse("")).sum()
]
Expand Down
Loading

0 comments on commit f6909dd

Please sign in to comment.