Newer
Older
% \newblock \textit{\textsc{ThuThesis}:清华大学学位论文模板} [EB/OL].
% \newblock version 7.2.3,
% \newblock (2021-05-31)
% \urlprefix\url{https://ctan.org/pkg/thuthesis}
% \urlprefix\CTANurl[文档及源代码:]{macros/latex/contrib/thuthesis/thuthesis.pdf}
%
%
% \emph{以下模版现已停止更新。}
%
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
% \bibitem{wenboyang2013}
% 杨文博.
% \newblock \textit{南京大学学位论文 \hologo{LaTeX} 模板} [EB/OL].
% \newblock (2018-06-23)
% \urlprefix\url{https://github.com/solrex/njuthesis}
%
% \bibitem{fireblue2013}
% \textsc{fireblue}.
% \newblock \textit{南京大学学位论文 \hologo{LaTeX} 模板} [EB/OL].
% \newblock (2013-04-13)
% \urlprefix\url{https://github.com/fireblue/NJUThesis}
%
% \bibitem{wenhai-zheng2013}
% \textsc{wenhai-zheng}.
% \newblock \textit{南京大学本科毕业论文 \hologo{LaTeX} 模板} [EB/OL].
% \newblock (2013-08-12)
% \urlprefix\url{https://github.com/wenhai-zheng/NJUThesis}
%
% \bibitem{zenglecao2013}
% 曹增乐.
% \newblock \textit{南京大学本科毕业论文(设计) \hologo{LaTeX} 模板} [EB/OL].
% \newblock (2019-06-26)
% \urlprefix\url{https://github.com/ZLCao/NJUBachelor}
%
% \bibitem{haixinghu2013}
% 胡海星.
% \newblock \textit{南京大学学位论文 \hologo{XeLaTeX} 模板} [EB/OL].
% \newblock (2018-08-08)
% \urlprefix\url{https://github.com/Haixing-Hu/nju-thesis}
%
% \bibitem{chuhengzhang2016}
% 张楚珩.
% \newblock \textit{南京大学本科生毕业论文 \hologo{LaTeX} 模板} [EB/OL].
% \newblock (2016-06-01)
% \urlprefix\url{https://github.com/zhangchuheng123/NJUThesis}
%
% \bibitem{yanyanjiang2017}
% 蒋炎岩.
% \newblock \textit{南京大学山寨 \hologo{LyX} 研究生毕业论文模板} [EB/OL].
% \newblock (2019-01-16)
% \urlprefix\url{https://github.com/jiangyy/njuthesis}
%
% \bibitem{njuHan2018}
% \textsc{njuHan}.
% \newblock \textit{南京大学学位论文(本科/硕士/博士),毕业论文 \hologo{LaTeX} 模板} [EB/OL].
% \newblock (2021-06-15)
% \urlprefix\url{https://github.com/njuHan/njuthesis-nju-thesis-template}
%
% \bibitem{anyirao2018}
% 饶安逸.
% \newblock \textit{南京大学本科生毕业论文 \hologo{LaTeX} 模板 2018 新版} [EB/OL].
% \newblock (2018-06-24)
% \urlprefix\url{https://github.com/AnyiRao/NJUThesis2018}
%
% \bibitem{yichenzhao2021}
% 赵懿晨.
% \newblock \textit{南京大学本科生毕业论文 \hologo{LaTeX} 模板(2021版)} [EB/OL].
% \newblock (2021-09-23)
% \urlprefix\url{https://github.com/FengChendian/NJUThesis2021}
%
%
% 本模板使用 \hologo{LaTeX3} 语法编写,依赖 \pkg{expl3} 环境,
% 并需调用 \pkg{l3packages} 中的相关宏包。
%
% 以下代码中有一些形如 \agrd{*class} 的标记,
% 这是 \pkg{DocStrip} 中的“guard”,用来选择性地提取文件。
% “|*|”和“|/|”分别表示该部分的开始和结束。不含
% “|*|”和“|/|”的 guard 出现在行号右侧,它们用来确定
% 单独一行代码的归属。这些 guard 的颜色深浅不一,用以明确嵌套关系。
%
% \changes{v0.12}{2021/12/03}{放宽对于 \pkg{l3packages} 的版本要求。}
Please~ update~ an~ up-to-date~ version~ of~ the~
bundles~ "l3kernel"~ and~ "l3packages"~ using~
your~ TeX~ package~ manager~ or~ from~ CTAN.
{ } { \msg_error:nnn { njuthesis } { l3-too-old } {#1} }
}
% \end{macrocode}
%
% \begin{macrocode}
\msg_new:nnn { njuthesis } { unsupported-engine }
{
\bool_lazy_or:nnF
{ \sys_if_engine_xetex_p: }
{ \sys_if_engine_luatex_p: }
{ \msg_fatal:nnx { njuthesis } { unsupported-engine } { \c_sys_engine_str } }
% \begin{variable}{\g_@@_info_degree_int,
% \l_@@_info_diploma_int,\g_@@_info_type_int}
% \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_info_degree_tl,\l_@@_info_diploma_tl,
% \l_@@_info_type_tl}
% 用于存储学位名称的变量。
% \begin{macrocode}
\tl_new:N \l_@@_info_degree_tl
\tl_new:N \l_@@_info_diploma_tl
% \begin{variable}{\g_@@_twoside_bool}
% 定义用于判断是否使用双面模式的变量,初始值为使用双面模式。
% \begin{macrocode}
\bool_new:N \g_@@_twoside_bool
\bool_set_true:N \g_@@_twoside_bool
% \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_second_supv_bool}
% 定义用于判断是否有第二导师的变量。
% \begin{macrocode}
\bool_new:N \l_@@_second_supv_bool
% \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_info_supv_full_tl,\l_@@_info_supv_full_en_tl}
% 用于存储导师姓名加职称的变量。
\tl_new:N \l_@@_info_supv_full_tl
\tl_new:N \l_@@_info_supv_full_en_tl
% \begin{variable}{\g_@@_latin_font_tl,\g_@@_cjk_font_tl}
\tl_new:N \g_@@_latin_font_tl
\tl_new:N \g_@@_cjk_font_tl
% \begin{variable}{\g_@@_config_tl}
% 保存配置文件名称。默认为空。
% \begin{macrocode}
\tl_new:N \g_@@_config_tl
% \end{macrocode}
% \end{variable}
%
% \begin{variable}{\g_@@_theorem_type_clist}
% 定理类型。
% \begin{macrocode}
\clist_new:N \g_@@_theorem_type_clist
% \end{macrocode}
% \end{variable}
%
% \begin{variable}{\l_@@_info_sm_date_tl,\l_@@_info_sm_date_en_tl,
% \l_@@_info_df_date_tl}
% 用于存储格式化后的论文提交日期和答辩日期的变量。
% \begin{macrocode}
\tl_new:N \l_@@_info_sm_date_tl
\tl_new:N \l_@@_info_sm_date_en_tl
\tl_new:N \l_@@_info_df_date_tl
% \end{macrocode}
% \end{variable}
%
% \begin{variable}{\c_@@_today_tl}
\int_to_arabic:n { \c_sys_year_int } -
\int_to_arabic:n { \c_sys_month_int } -
\int_to_arabic:n { \c_sys_day_int }
}
% \end{macrocode}
% \end{variable}
%
% \begin{variable}{\c_@@_name_type_clist,\c_@@_name_type_en_clist,
% \c_@@_name_degree_clist,\c_@@_name_degree_en_clist}
% 论文类型与学位类型。
% \begin{macrocode}
\clist_const:Nn \c_@@_name_type_clist
{ 毕业论文, 毕业设计 }
\clist_const:Nn \c_@@_name_type_en_clist
{ THESIS, DESIGN }
\clist_const:Nn \c_@@_name_degree_clist
{ 学士, 硕士, 硕士专业, 博士 }
\clist_const:Nn \c_@@_name_degree_en_clist
{ Bachelor, Master, Master, Doctor~of~Philosophy }
% \end{macrocode}
% \end{variable}
%
% \begin{variable}{\c_@@_month_en_clist}
% 英文月份名称。
% \begin{macrocode}
\clist_const:Nn \c_@@_month_en_clist
{
January, February, March, April, May, June,
July, August, September, October, November, December
}
% \end{macrocode}
% \end{variable}
%
% \begin{macro}{\@@_quad:,\@@_qquad:}
% 等价于 \LaTeXe{} 中的 \tn{quad} 和 \tn{qquad}。
\cs_new:Nn \@@_quad: { \skip_horizontal:n { 1 em } }
\cs_new:Nn \@@_qquad: { \skip_horizontal:n { 2 em } }
% \begin{macro}{\@@_vskip:,\@@_hskip:}
% 生成一个较小的 skip。
\cs_new:Nn \@@_vskip: { \skip_vertical:n { 1 ex } }
\cs_new:Nn \@@_hskip: { \skip_horizontal:n { 0.3 em } }
% 类似于 \hologo{LaTeX2e} 中的 \tn{vspace*},
% 从上一个页面元素底部开始生成 |skip|。
% \begin{macrocode}
\cs_new_protected:Npn \@@_vskip:N #1
{
\hrule height \c_zero_dim
\nobreak
\skip_vertical:n { - \baselineskip - \lineskip }
\skip_vertical:N #1
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_define_name:nn,\@@_define_name:nnn}
% 用来定义默认名称的辅助函数。
% \begin{macrocode}
\cs_new_protected:Npn \@@_define_name:nn #1#2
\cs_new_protected:Npn \@@_define_name:nnn #1#2#3
{
\tl_const:cn { c_@@_name_ #1 _tl } { #2 }
\tl_const:cn { c_@@_name_ #1 _en_tl } { #3 }
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_add_theorem_type:nnn}
% 添加已知的定理环境类型。
% \begin{macrocode}
\cs_new_protected:Npn \@@_add_theorem_type:nnn #1#2#3
{
\clist_gput_right:Nn \g_@@_theorem_type_clist { #1 }
\@@_define_name:nnn { #1 } { #2 } { #3 }
}
% \end{macrocode}
% \end{macro}
%
\cs_new:Npn \@@_name:n #1 { \tl_use:c { c_@@_name_ #1 _tl } }
\cs_new:Npn \@@_info:n #1 { \tl_use:c { l_@@_info_ #1 _tl } }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_ulined_center_box:nn}
% 带有下划线的水平盒子。
% \begin{arguments}
% \item 宽度,|dim| 型变量
% \item 内容,可带有格式
% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Npn \@@_ulined_center_box:nn #1#2
\mode_leave_vertical:
\rule [ -0.5 ex ] { #1 } { 0.4 pt }
\skip_horizontal:n { -#1 }
% \begin{macro}{\@@_spread_box:nnn,\@@_spread_box:nnV,\@@_spread_box:nnx}
% 分散对齐的水平盒子。
% \begin{arguments}
% \item 宽度,|dim| 型变量
% \item 格式
% \item 内容,不可带有格式
% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Npn \@@_spread_box:nnn #1#2#3
\cs_generate_variant:Nn \@@_spread_box:nnn { nnV }
\cs_generate_variant:Nn \@@_spread_box:nnn { nnx }
% \begin{arguments}
% \item 用于循环的 |int| 型变量
% \item 内容,|clist| 型变量
% \item 行数
% \item 宽度,|dim| 型变量
% \end{arguments}
{ \clist_item:Nn #2 { #1 } } \\
\int_incr:N #1
}
% \begin{macro}{\@@_put_inempty_seg:nnn}
% 将固定长度的非空字符串插入 |clist|。
% \begin{arguments}
% \item 原始字符串
% \item 起始位置
% \item 长度
% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Npn \@@_put_inempty_seg:nnn #1#2#3
{
\tl_if_empty:NF \l_@@_tmp_tl
{ \clist_put_right:NV \l_@@_tmp_clist { \l_@@_tmp_tl } }
% \begin{macro}{\@@_uline:n}
% 指定宽度的下划线。
% \begin{arguments}
% \item 宽度,|dim| 型变量
% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Npn \@@_uline:n #1
{
\mode_leave_vertical:
\rule [ -0.5 ex ] { #1 } { 0.4 pt }
\skip_horizontal:n { -#1 }
}
% \end{macrocode}
% \end{macro}
% \begin{macro}{\@@_uuline:n}
% 指定宽度的双层下划线。
% \begin{arguments}
% \item 宽度,|dim| 型变量
% \end{arguments}
\cs_new_protected:Npn \@@_uuline:n #1
{
\mode_leave_vertical:
\rule [ -0.5 ex ] { #1 } { 0.4 pt }
\skip_horizontal:n { -#1 }
\rule [ -0.6 ex ] { #1 } { 0.4 pt }
\skip_horizontal:n { -#1 }
}
% \begin{macro}{\@@_get_text_width:Nn,\@@_get_text_width:NV}
% 获取文本宽度。
% \begin{arguments}
% \item 存储宽度的 |dim| 型变量
% \item 文本
% \end{arguments}
% 将内容放入 \tn{hbox} 后读取其宽度,存入 |dim| 型变量。
\hbox_set:Nn \l_@@_tmp_box {#2}
\dim_set:Nn #1 { \box_wd:N \l_@@_tmp_box }
}
\cs_generate_variant:Nn \@@_get_text_width:Nn { NV }
% \end{macro}
%
% \begin{macro}{\@@_full_uline:Nn,\@@_full_uline:NV}
% 横跨整页的下划线。
% \begin{arguments}
% \item 宽度,|dim| 型变量
% \item 文本
% \end{arguments}
% 先使用 \cs{@@_get_text_width:Nn} 获取文本内容宽度,该宽度存储在调用的 |dim| 型变量中。随后输出文本内容。
% \begin{macrocode}
\cs_new_protected:Npn \@@_full_uline:Nn #1#2
{
\@@_get_text_width:Nn #1 { #2 }
}
\cs_generate_variant:Nn \@@_full_uline:Nn { NV }
% \end{macrocode}
% \end{macro}
%
% 生成占整页宽度的下划线条目。
% \begin{arguments}
% \item 宽度,|dim| 型变量
% \item 文本
% \item 文本
% \item 分隔符
% \end{arguments}
% \begin{macrocode}
{
\@@_full_uline:NV #1 { \@@_name:n { #2 } #4 }
\@@_ulined_center_box:nn { #1 } { \@@_info:n { #3 } }
}
% \end{macrocode}
% \end{macro}
%
% 生成占半页宽度的下划线条目。
% \begin{arguments}
% \item 宽度,|dim| 型变量
% \item 文本
% \item 文本
% \item 分隔符
% \end{arguments}
% \begin{macrocode}
{
\@@_full_uline:NV #1 { \@@_name:n { #2 } #4 }
\dim_sub:Nn #1 { \textwidth / 2 }
\@@_ulined_center_box:nn { #1 } { \@@_info:n { #3 } }
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_date:www,\@@_date_en:www}
% 将形如 |yyyy-mm-dd| 的 ISO 日期格式字符串转化为日期表示。该格式符合国际标准 ISO 8601 以及国内标准 GB/T 7408--2005《数据元和交换格式 信息交换 日期和时间表示法》。
% \begin{arguments}
% \item 年份
% \item 月份
% \item 日期
% \end{arguments}
% 中文日期表示通过封装 \pkg{zhnumber} 的内部函数实现;英文日期表示通过用于研究生英文封面。其中,变量类型 |w| 表明参数符合特定语法格式。
\cs_new:Npn \@@_date:www #1-#2-#3 \q_stop
{ \__zhnum_date_aux:nnn { #1 } { #2 } { #3 } }
\cs_new:Npn \@@_date_en:www #1-#2-#3 \q_stop
{ \clist_item:Nn \c_@@_month_en_clist { #2 } ~#3 , ~#1 }
% \end{macrocode}
% \end{macro}
%
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
% \subsubsection{封面相关}
% \changes{v0.16}{2022/03/10}{将封面和摘要内部函数定义移动到前部。}
%
% \begin{macro}{\@@_split_title:n,\@@_split_title:V}
% 分割标题。
% \begin{macrocode}
\cs_new_protected:Npn \@@_split_title:n #1
{
\tl_if_in:nnTF { #1 } { \\ }
{
% \end{macrocode}
% 从 |\\| 进行分割,存入 |clist|。
% \begin{macrocode}
\seq_set_split:Nnn \l_@@_tmp_seq { \\ } { #1 }
\clist_set_from_seq:NN \l_@@_tmp_clist \l_@@_tmp_seq
}
{
% \end{macrocode}
% 如果没找到换行符,则手动从固定宽度的位置进行分割。
% \begin{macrocode}
\@@_put_inempty_seg:nnn { #1 } { 1 } { 15 }
\@@_put_inempty_seg:nnn { #1 } { 16 } { 15 }
\@@_put_inempty_seg:nnn { #1 } { 31 } { 15 }
}
}
\cs_generate_variant:Nn \@@_split_title:n { V }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_multiline_title:nnn}
% 生成多行标题。
% \begin{arguments}
% \item 内容格式
% \item 名称盒子宽度,|dim| 型变量
% \item 内容盒子宽度,|dim| 型变量
% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Npn \@@_multiline_title:nnn #1#2#3
{
\@@_split_title:V \l_@@_info_title_tl
\@@_spread_box:nnV { #2 } { \kaishu } \c_@@_name_title_tl
\@@_hskip:
\clist_map_inline:Nn \l_@@_tmp_clist
{ \@@_ulined_center_box:nn { #3 } { #1 ##1 } \@@_vskip: }
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_cover_entry:nnn}
% 生成单项信息条目。
% \begin{arguments}
% \item 条目名称
% \item 名称盒子宽度,|dim| 型变量
% \item 内容盒子宽度,|dim| 型变量
% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Npn \@@_cover_entry:nnn #1#2#3
{
\@@_spread_box:nnx { #2 } { \kaishu } { \@@_name:n { #1 } }
\@@_hskip:
\@@_ulined_center_box:nn { #3 } { \@@_info:n { #1 } }
\@@_vskip:
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_cover_bientry:nnnn}
% 生成两项信息条目,仅用于本科生封面。
% \begin{arguments}
% \item 左侧条目名称
% \item 右侧条目名称
% \item 名称盒子宽度,|dim| 型变量
% \item 内容盒子宽度,|dim| 型变量
% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Npn \@@_cover_bientry:nnnn #1#2#3#4
{
\@@_spread_box:nnx { #3 } { \kaishu } { \@@_name:n { #1 } }
\@@_hskip:
\@@_ulined_center_box:nn { #4 } { \@@_info:n { #1 } }
\skip_horizontal:n { 0.5 em }
\@@_spread_box:nnx { #3 } { \kaishu } { \@@_name:n { #2 } }
\@@_hskip:
\@@_ulined_center_box:nn { #4 } { \@@_info:n { #2 } }
\@@_vskip:
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_cover_supv_entry:nnn}
% 生成两项导师信息条目,仅用于本科生封面。
% \begin{arguments}
% \item 条目名称
% \item 长内容盒子宽度,|dim| 型变量
% \item 短内容盒子宽度,|dim| 型变量
% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Npn \@@_cover_supv_entry:nnn #1#2#3
{
\@@_spread_box:nnx { #2 } { \kaishu } { \@@_name:n { #1 } }
\@@_hskip:
\@@_ulined_center_box:nn { #3 }
{ \clist_item:cn { l_@@_info_ #1 _clist } { 1 } }
\skip_horizontal:n { 0.5 em }
\@@_spread_box:nnV { #2 } { \kaishu } \c_@@_name_supv_ttl_tl
\@@_hskip:
\@@_ulined_center_box:nn { #3 }
{ \clist_item:cn { l_@@_info_ #1 _clist } { 2 } }
\@@_vskip:
}
% \end{macrocode}
% \end{macro}
%
% \subsubsection{摘要相关}
%
% \begin{macro}{\@@_abs_bookmark:nn,\@@_abs_bookmark:Vn}
% \changes{v0.14}{2021/12/21}{将摘要插入目录。}
% 生成摘要的目录条目。
% \begin{macrocode}
\cs_new_protected:Npn \@@_abs_bookmark:nn #1#2
{
\phantomsection
\bool_if:NTF \g_@@_abs_in_toc_bool
{ \@@_add_tocline:n { #1 } }
{ \pdfbookmark [0] { #1 } { #2 } }
}
\cs_generate_variant:Nn \@@_abs_bookmark:nn { Vn }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@@_abs_title:n,\@@_abs_title:V}
% 摘要标题双层下划线格式。
% \begin{arguments}
% \item 宽度,|dim| 型变量
% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Npn \@@_abs_title:n #1
{
\@@_get_text_width:Nn \l_@@_tmp_dim {#1}
\@@_uuline:n { \l_@@_tmp_dim } #1
}
\cs_generate_variant:Nn \@@_abs_title:n { V }
% \end{macrocode}
% \end{macro}
%
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
% \changes{v0.15}{2022/01/24}{使用 \pkg{xtemplate} 重构封面。}
%
% 本模板使用 \pkg{xtemplate} 提供的面向对象方法简化封面和摘要的绘制过程。
%
% 以下分别从页面元素(element)和页面整体(page)的层次进行了抽象。当我们把页面部件考虑为一个对象时,它天然地只具备有限数量的属性:内容、格式、边距、对齐方式等。而具体的页面是这些对象的实例的集合,附加边距、行距等属性,创建页面只需传入一个列表调用各个 Instance 即可。通过 \pkg{xtemplate} 提供的功能,我们可以根据这些属性创建模板(template),进而能大量构建具有\emph{相似行为}的实例(instance)。这种做法能充分分离内容和样式,极大优化代码的可读性。
%
% 声明对象类型。此类对象不需要参数。
% \begin{macrocode}
\DeclareObjectType { nju } { \c_zero_int }
% \end{macrocode}
%
% 定义元素模板。
% \begin{macrocode}
%<@@=njuelem>
% \end{macrocode}
%
% 声明页面元素模板接口。
% 元素是一个页面的基本组成单位,包括文段、图片等等。一个抽象的元素应当具备以下属性:
% \begin{description}
% \item[\opt{content}] 内容,即剥离样式的元素本身
% \item[\opt{format}] 格式,例如字号、字体
% \item[\opt{bottom-skip}] 下间距,即与下一个元素的距离
% \item[\opt{align}] 对齐方式,包括左对齐、右对齐、居中、正常段落
% \end{description}
% \begin{macrocode}
\DeclareTemplateInterface { nju } { element } { \c_zero_int }
{
content : tokenlist = \c_empty_tl,
format : tokenlist = \c_empty_tl,
bottom-skip : skip = \c_zero_skip,
align : choice { l, r, c, n } = c
}
% \end{macrocode}
%
% 声明页面元素模板代码。涉及的变量将被自动创建。
% \begin{macrocode}
\DeclareTemplateCode { nju } { element } { \c_zero_int }
{
content = \l_@@_content_tl,
format = \l_@@_format_tl,
bottom-skip = \l_@@_bottom_skip,
align =
{
l =
{ \tl_set_eq:NN \l_@@_begin_align_tl \flushleft
\tl_set_eq:NN \l_@@_end_align_tl \endflushleft },
r =
{ \tl_set_eq:NN \l_@@_begin_align_tl \flushright
\tl_set_eq:NN \l_@@_end_align_tl \endflushright },
c =
{ \tl_set_eq:NN \l_@@_begin_align_tl \center
\tl_set_eq:NN \l_@@_end_align_tl \endcenter },
n =
{ \tl_clear:N \l_@@_begin_align_tl
\tl_clear:N \l_@@_end_align_tl }
}
}
{
\AssignTemplateKeys
\group_begin:
\l_@@_begin_align_tl
\l_@@_format_tl
\l_@@_content_tl \par
\l_@@_end_align_tl
\group_end:
\__nju_vskip:N \l_@@_bottom_skip
}
% \end{macrocode}
%
% 定义页面模板。
% \begin{macrocode}
%<@@=njupage>
% \end{macrocode}
%
% 声明页面模板接口。
% 页面是元素的集合。一个抽象的页面应当具备以下属性:
% \begin{description}
% \item[\opt{element}] 包含的元素,这里使用的是名称列表
% \item[\opt{prefix}] 元素名称前缀
% \item[\opt{format}] 格式,例如行距
% \item[\opt{top-skip}] 上间距,即与页面顶部的距离
% \item[\opt{bottom-skip}] 下间距,即与页面底部的距离
% \end{description}
% \begin{macrocode}
\DeclareTemplateInterface { nju } { page } { \c_zero_int }
{
element : commalist = \c_empty_clist,
prefix : tokenlist = \c_empty_tl,
format : tokenlist = \c_empty_tl,
top-skip : skip = \c_zero_skip,
bottom-skip : skip = \c_zero_skip
}
% \end{macrocode}
%
% 声明页面模板代码。
% \begin{macrocode}
\DeclareTemplateCode { nju } { page } { \c_zero_int }
{
element = \l_@@_element_clist,
prefix = \l_@@_prefix_tl,
format = \l_@@_format_tl,
top-skip = \l_@@_top_skip,
bottom-skip = \l_@@_bottom_skip
}
{
\AssignTemplateKeys
\newpage
\__nju_vskip:N \l_@@_top_skip
\group_begin:
\l_@@_format_tl
\clist_map_inline:Nn \l_@@_element_clist
{ \UseInstance { nju } { \l_@@_prefix_tl ##1 } }
\group_end:
\__nju_vskip:N \l_@@_bottom_skip
}
%<@@=nju>
% \end{macrocode}
%
% \begin{macro}{\@@_declare_element:nn,\@@_declare_page:nn}
% 封装 \pkg{xtemplate} 提供的函数,简化创建实例的过程。
% \begin{arguments}
% \item 实例名称
% \item 参数列表
% \end{arguments}
% \begin{macrocode}
\cs_new_protected:Npn \@@_declare_element:nn #1#2
{ \DeclareInstance { nju } {#1} { element } {#2} }
\cs_new_protected:Npn \@@_declare_page:nn #1#2
{ \DeclareInstance { nju } {#1} { page } {#2} }
% \end{macrocode}
% \end{macro}
%
%
% \subsection{模板选项}
% \changes{v0.11}{2021/11/15}{进行了效率优化。}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{type}
nlcover .bool_set:N = \g_@@_nlcover_bool,
nlcover .initial:n = false,
% \footnote{原创性声明的英文翻译为 Declaration of Originality,为了使选项表义更清晰同时缩减名称长度,将其修改为“声明页”这一名称。}
decl-page .bool_set:N = \g_@@_orig_decl_bool,
decl-page .initial:n = false,
% \begin{macro}{draft}
% \changes{v0.13}{2021/12/15}{新增草稿模式选项。}
% 是否开启草稿模式(默认关闭)。
% \begin{macrocode}
draft .bool_gset:N = \g_@@_draft_bool,
draft .initial:n = false,
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{oneside,twoside}
% \changes{v0.14}{2022/01/14}{新增单双面模式选项。}
% 单双面模式(默认为双面)。
% \begin{macrocode}
oneside .value_forbidden:n = true,
twoside .value_forbidden:n = true,
{ gyre, mac, win, none }
{ \tl_set_eq:NN \g_@@_latin_font_tl \l_keys_choice_tl },
{ fandol, founder, mac, noto, source, win, none }
{ \tl_set_eq:NN \g_@@_cjk_font_tl \l_keys_choice_tl },
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{config}
% \changes{v0.16}{2022/02/23}{新增 \opt{config} 选项。}
% 配置文件路径。
% \begin{macrocode}
% \begin{macrocode}
\ProcessKeysOptions { nju }
% \end{macrocode}
bib .meta:nn = { nju / bib } { #1 },
info .meta:nn = { nju / info } { #1 },
style .meta:nn = { nju / style } { #1 }
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\njusetup}
% \changes{v0.6}{2021/09/10}{改用键值对输入信息。}
% 定义用于设置信息的命令。
% \begin{macrocode}
\NewDocumentCommand \njusetup { m } { \keys_set:nn { nju } { #1 } }
% \end{macrocode}
% \end{macro}
%
%
%
% \changes{v0.12}{2021/12/07}{重新组织宏包载入顺序。}
% 将选项传入 \cls{ctexbook} 文档类。
% 传入单双面模式选项。
% \begin{macrocode}
\bool_if:NTF \g_@@_twoside_bool { twoside, } { oneside, }
% \end{macrocode}
% 开启草稿模式后传入 |draft| 选项。
% \begin{macrocode}
\bool_if:NT \g_@@_draft_bool { draft, }
% \end{macrocode}
% 关于行距,\hologo{LaTeX} 默认1.2行距,MS Word 默认行距是1.3,要求1.5倍
% Word 行距,故 $1.5\times\frac{1.3}{1.2} = 1.625$
% \end{macrocode}
% 默认不载入任何字体,供本模板自行设置。
% \begin{macrocode}
% \end{macrocode}
% 正文字体设置为小四号。
% \begin{macrocode}
%
% 传入各宏包选项。
% \begin{macrocode}
\clist_map_inline:nn
{
{ no-math } { fontspec },
{ perpage } { footmisc },
{ amsmath, thmmarks } { ntheorem },
{ hyphens } { url },
{ warnings-off={ mathtools-colon, mathtools-overbracket } }
{ unicode-math },
{ capitalise, nameinlink, noabbrev }
}
{ \PassOptionsToPackage #1 }
% \end{macrocode}
%
% 使用\pkg{ctexbook}作为基础文档类。
% \changes{v0.13}{2021/12/13}{使用 \pkg{ntheorem} 创建定理环境,删除
% \pkg{amsthm} 和 \pkg{thmtools}。}
% \changes{v0.16}{2022/03/19}{不显式载入 \pkg{amsmath}。}
% 数学相关的宏包。其中,\pkg{amsmath} 必须在 \pkg{unicode-math} 前加载。
% \pkg{unicode-math} 指定了 \hologo{XeTeX} 和 \hologo{LuaTeX} 下所使用的
% 数学字体。用于配置数学环境的 \pkg{mathtools} 会与 \pkg{unicode-math}