summaryrefslogtreecommitdiff
path: root/macros/latex
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2024-02-19 03:01:14 +0000
committerNorbert Preining <norbert@preining.info>2024-02-19 03:01:14 +0000
commite11a34ebeb96a1e568cc937df3b614062ddb0adf (patch)
treebe8835e935b7358f24c2057ec9ef972132a056a9 /macros/latex
parenta3b386e8476527e1b87ec71f7156cd7751f8f325 (diff)
CTAN sync 202402190301
Diffstat (limited to 'macros/latex')
-rw-r--r--macros/latex/contrib/easybook/easybook.dtx109
-rw-r--r--macros/latex/contrib/easybook/easybook.pdfbin598997 -> 602008 bytes
-rw-r--r--macros/latex/contrib/easybook/easybook.tex59
-rw-r--r--macros/latex/contrib/l3kernel/CHANGELOG.md12
-rw-r--r--macros/latex/contrib/l3kernel/README.md2
-rw-r--r--macros/latex/contrib/l3kernel/expl3.dtx4
-rw-r--r--macros/latex/contrib/l3kernel/expl3.pdfbin610363 -> 610339 bytes
-rw-r--r--macros/latex/contrib/l3kernel/interface3.pdfbin1792513 -> 1793104 bytes
-rw-r--r--macros/latex/contrib/l3kernel/interface3.tex2
-rw-r--r--macros/latex/contrib/l3kernel/l3basics.dtx24
-rw-r--r--macros/latex/contrib/l3kernel/l3bitset.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3bootstrap.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3box.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3cctab.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3clist.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3coffins.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3color.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3debug.dtx6
-rw-r--r--macros/latex/contrib/l3kernel/l3deprecation.dtx6
-rw-r--r--macros/latex/contrib/l3kernel/l3doc.dtx4
-rw-r--r--macros/latex/contrib/l3kernel/l3doc.pdfbin565282 -> 565548 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3docstrip.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3docstrip.pdfbin151264 -> 151219 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3expan.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3file.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3flag.dtx10
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-assign.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-aux.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-basics.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-convert.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-expo.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-extended.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-functions.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-logic.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-parse.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-random.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-round.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-symbolic.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-traps.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-trig.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp-types.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fp.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3fparray.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3int.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3intarray.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3kernel-functions.dtx4
-rw-r--r--macros/latex/contrib/l3kernel/l3keys.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3legacy.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3luatex.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3msg.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3names.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3news.pdfbin396222 -> 396222 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3news01.pdfbin122959 -> 122959 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3news02.pdfbin150919 -> 150919 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3news03.pdfbin148747 -> 148747 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3news04.pdfbin114754 -> 114754 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3news05.pdfbin112524 -> 112524 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3news06.pdfbin151591 -> 151591 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3news07.pdfbin128344 -> 128344 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3news08.pdfbin163484 -> 163484 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3news09.pdfbin250159 -> 250159 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3news10.pdfbin150302 -> 150302 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3news11.pdfbin170102 -> 170102 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3news12.pdfbin205020 -> 205020 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3pdf.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3prefixes.csv4
-rw-r--r--macros/latex/contrib/l3kernel/l3prefixes.pdfbin82731 -> 82720 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3prg.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3prop.dtx4
-rw-r--r--macros/latex/contrib/l3kernel/l3quark.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3regex.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3seq.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3skip.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3sort.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3str-convert.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3str.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3styleguide.pdfbin296657 -> 296530 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3styleguide.tex2
-rw-r--r--macros/latex/contrib/l3kernel/l3syntax-changes.pdfbin231496 -> 231378 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3syntax-changes.tex2
-rw-r--r--macros/latex/contrib/l3kernel/l3sys.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3term-glossary.pdfbin242296 -> 242164 bytes
-rw-r--r--macros/latex/contrib/l3kernel/l3term-glossary.tex2
-rw-r--r--macros/latex/contrib/l3kernel/l3text-case.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3text-map.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3text-purify.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3text.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3tl-analysis.dtx79
-rw-r--r--macros/latex/contrib/l3kernel/l3tl-build.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3tl.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/l3token.dtx6
-rw-r--r--macros/latex/contrib/l3kernel/l3unicode.dtx2
-rw-r--r--macros/latex/contrib/l3kernel/source3.pdfbin7574815 -> 7556690 bytes
-rw-r--r--macros/latex/contrib/l3kernel/source3.tex2
-rw-r--r--macros/latex/contrib/l3packages/CHANGELOG.md8
-rw-r--r--macros/latex/contrib/l3packages/README.md2
-rw-r--r--macros/latex/contrib/l3packages/l3keys2e.dtx4
-rw-r--r--macros/latex/contrib/l3packages/l3keys2e.pdfbin412717 -> 412694 bytes
-rw-r--r--macros/latex/contrib/l3packages/xfp.dtx4
-rw-r--r--macros/latex/contrib/l3packages/xfp.pdfbin332421 -> 332379 bytes
-rw-r--r--macros/latex/contrib/l3packages/xparse.dtx4
-rw-r--r--macros/latex/contrib/l3packages/xparse.pdfbin534182 -> 534131 bytes
-rw-r--r--macros/latex/contrib/l3packages/xtemplate.dtx10
-rw-r--r--macros/latex/contrib/l3packages/xtemplate.pdfbin448106 -> 448820 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam-a-answer.pdfbin49588 -> 49886 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam-a-answer.tex10
-rw-r--r--macros/latex/contrib/randexam/randexam-a-blank.pdfbin41374 -> 41751 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam-b-answer.pdfbin49570 -> 49948 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam-b-blank.pdfbin41309 -> 41687 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam.cls423
-rw-r--r--macros/latex/contrib/randexam/randexam.pdfbin52431 -> 63636 bytes
-rw-r--r--macros/latex/contrib/randexam/randexam.tex142
-rw-r--r--macros/latex/contrib/sjtutex/README.md31
-rw-r--r--macros/latex/contrib/sjtutex/sjtu-vi-badge-red.pdfbin0 -> 20101 bytes
-rw-r--r--macros/latex/contrib/sjtutex/sjtu-vi-badge-small-red.pdfbin0 -> 20011 bytes
-rw-r--r--macros/latex/contrib/sjtutex/sjtu-vi-logo-red.pdfbin0 -> 39157 bytes
-rw-r--r--macros/latex/contrib/sjtutex/sjtu-vi-logo-small-red.pdfbin0 -> 39066 bytes
-rw-r--r--macros/latex/contrib/sjtutex/sjtu-vi-name-red.pdfbin0 -> 20802 bytes
-rw-r--r--macros/latex/contrib/sjtutex/sjtutex.dtx6137
-rw-r--r--macros/latex/contrib/sjtutex/sjtutex.pdfbin0 -> 713536 bytes
120 files changed, 6865 insertions, 355 deletions
diff --git a/macros/latex/contrib/easybook/easybook.dtx b/macros/latex/contrib/easybook/easybook.dtx
index a69d7de48b..bf101810cd 100644
--- a/macros/latex/contrib/easybook/easybook.dtx
+++ b/macros/latex/contrib/easybook/easybook.dtx
@@ -15,7 +15,7 @@
%<*class>
\NeedsTeXFormat{LaTeX2e}[2021/11/15]
\RequirePackage{l3keys2e}
-\ProvidesExplClass{easybook}{2024/02/16}{2024ad}
+\ProvidesExplClass{easybook}{2024/02/18}{2024ae}
{Easily typesetting Chinese theses or books}
\bool_set_false:N \l__eb_compile_draft_bool
@@ -297,7 +297,7 @@
%<*package>
\NeedsTeXFormat{LaTeX2e}[2021/11/15]
\RequirePackage{l3keys2e,etoolbox}
-\ProvidesExplPackage{easybase}{2024/02/16}{2024ad}
+\ProvidesExplPackage{easybase}{2024/02/18}{2024ae}
{Easily typesetting Chinese theses or books}
\cs_generate_variant:Nn \dim_set:Nn { NV }
@@ -630,19 +630,19 @@
}
\ctex_define:nn { hdrset }
{
- chap-mark .cs_set:Np = \eb_fancyhf_chapter_mark:n #1,
+ chap-mark .cs_set:Np = \eb@mark@chapter@whole #1,
chap-mark .initial:n =
{
\CTEXifname{\eb@mark@chapter@label}{}
\eb_mark_uppercase_case_init:n {#1}
},
- sec-mark .cs_set:Np = \eb_fancyhf_section_mark:n #1,
+ sec-mark .cs_set:Np = \eb@mark@section@whole #1,
sec-mark .initial:n =
{
\CTEXifname{\eb@mark@section@label}{}
\eb_mark_uppercase_case_init:n {#1}
},
- subsec-mark .cs_set:Np = \eb_fancyhf_subsection_mark:n #1,
+ subsec-mark .cs_set:Np = \eb@mark@subsection@whole #1,
subsec-mark .initial:n =
{
\CTEXifname{\eb@mark@subsection@label}{}
@@ -668,9 +668,9 @@
\cs_set:Npn \markdouble #1 { \markboth{#1}{\ifbool{@twoside}{#1}{}} }
\cs_new:Npn \eb@level@markdouble #1#2
- { \markdouble{\use:c { eb_fancyhf_#1_mark:n } {#2}} }
+ { \markdouble{\use:c { eb@mark@#1@whole } {#2}} }
\cs_new:Npn \eb@level@markright #1#2
- { \markright{\use:c { eb_fancyhf_#1_mark:n } {#2}} }
+ { \markright{\use:c { eb@mark@#1@whole } {#2}} }
\cs_gset:Npn \chaptermark #1 { \eb@level@markdouble{chapter}{#1} }
\cs_gset:Npn \sectionmark #1
{
@@ -1032,8 +1032,8 @@
\eb_patch_cmd:Nnn #1
{ \reset@font }
{
- \setspread{\fp_use:N \l__eb_spread_footnote_fp}
- \tl_use:N \l__eb_subfont_footnote_tl
+ \setspread{\eb@spread@footnote}
+ \eb@subfont@footnote
}
}
\cs_set_eq:NN \eb@@makefntext \@makefntext
@@ -1150,7 +1150,7 @@
{ \tl_clear:N \l__eb_fnmarktext_format_tl }
}
\bool_if:NF \l__eb_fnmarktext_format_match_bool { \spbset{spcmd = { }} }
- \tl_use:N \l__eb_subfont_footnote_tl
+ \eb@subfont@footnote
}
\cs_new_protected:Npn \defupfntmark #1
{ \cs_set:Npn \@makefnmark { \hbox:n {#1} } }
@@ -1328,8 +1328,12 @@
}
}
+\cs_new_protected:Npn \SetTocOuter #1
+ { \keys_set:nn { eb/tocouter } {#1} }
\tl_new:N \eb@bitoc@title
-\keys_define:nn { eb/floattoc }
+\newbool{bitoc}
+\cs_new:Npn \ebifbitoc { \ifbool{bitoc} }
+\keys_define:nn { eb/tocouter }
{
level .tl_set:N = \eb@toc@title@level,
level .initial:n =
@@ -1364,13 +1368,27 @@
plan .initial:n = cn,
columns .meta:n = { multoc = #1 },
title .code:n = \eb_assign_toc_title:n {#1},
- bilist .tl_gset:N = \g__eb_bilist_permute_value_tl,
+ bilist .code:n =
+ {
+ \tl_gset:Nn \g__eb_bilist_permute_value_tl {#1}
+ \str_if_eq:nnTF {#1} { mix }
+ {
+ \eb_preto_cmd:nn { CTEX@addtocline }
+ { \addtocontents{toc}{\boolfalse{bitoc}} }
+ \eb_preto_cmd:nn { CTEX@addbitocline }
+ { \addtocontents{toc}{\booltrue{bitoc}} }
+ }
+ {
+ \RemoveFromHook{cmd/CTEX@addtocline/before}
+ \RemoveFromHook{cmd/CTEX@addbitocline/before}
+ }
+ },
name .tl_set:N = \l__eb_print_index_name_tl,
name .initial:n = \imki@jobname
}
\bool_if:NTF \l__eb_class_mode_book_bool
- { \keys_define:nn { } { eb/floattoc .inherit:n = ctex/chapter } }
- { \keys_define:nn { } { eb/floattoc .inherit:n = ctex/section } }
+ { \keys_define:nn { } { eb/tocouter .inherit:n = ctex/chapter } }
+ { \keys_define:nn { } { eb/tocouter .inherit:n = ctex/section } }
\NewDocumentCommand{\eb_assign_toc_title:n}
{>{\SplitArgument{1}{,}}m}
{\eb_assign_toc_title_judge:nn #1}
@@ -1410,7 +1428,7 @@
{
\group_begin:
\tl_set_eq:Nc \eb@toc@title { list#4name }
- \IfValueT{#3}{\keys_set:nn { eb/floattoc } {#3}}
+ \IfValueT{#3}{\keys_set:nn { eb/tocouter } {#3}}
\eb_toc_title_level_cmd:n {#1}
\eb_toc_if_title_between_hook:nn {#1} {#4}
\eb_toc_start_multi_column_ext:n {#5}
@@ -1465,7 +1483,7 @@
{ \chapter* }
{ \section* }
}
- \IfValueT{#3}{\keys_set:nn { eb/floattoc } {#3}}
+ \IfValueT{#3}{\keys_set:nn { eb/tocouter } {#3}}
\bool_if:NT \l__eb_toc_plan_cn_bool
{
\IfBooleanF{#1}{\eb@toc@title@level{\eb@toc@title}{}}
@@ -1474,9 +1492,12 @@
}
\bool_if:NT \l__eb_toc_plan_bi_bool
{
- \IfBooleanF{#1}{\eb@toc@title@level{\eb@bitoc@title}{}}
- \eb_toc_if_title_between_hook:nn {#1} { bimain }
- \eb_toc_start_multi_column_ext:n { tec }
+ \tl_if_eq:NnF \g__eb_bilist_permute_value_tl { mix }
+ {
+ \IfBooleanF{#1}{\eb@toc@title@level{\eb@bitoc@title}{}}
+ \eb_toc_if_title_between_hook:nn {#1} { bimain }
+ \eb_toc_start_multi_column_ext:n { tec }
+ }
}
\group_end:
}
@@ -1605,7 +1626,7 @@
\cs_set_eq:NN \eb@ctexsetii \ctex_set:nn
\cs_new_protected:Npn \SetTocStyle #1#2#3
{
- \cs_set:cpn { eb@toc@style@set@#1@#2 }
+ \cs_set_protected:cpn { eb@toc@style@set@#1@#2 }
{ \eb@ctexsetii{#1}{#3} }
}
\cs_new_protected:Npn \UseTocStyle #1#2#3
@@ -1654,7 +1675,7 @@
\group_begin:
\tl_set_eq:NN \eb@toc@title \indexname
\cs_set_eq:NN \imki@indexlevel \use_none:n
- \IfValueT{#3}{\keys_set:nn { eb/floattoc } {#3}}
+ \IfValueT{#3}{\keys_set:nn { eb/tocouter } {#3}}
\cs_set_protected:Npn \imki@indexheaders
{
\eb_toc_title_level_cmd:n {#1}
@@ -1716,7 +1737,7 @@
caption-listing = #1
},
caption-every .initial:n = \sffamily\small,
- footnote .tl_set:N = \l__eb_subfont_footnote_tl,
+ footnote .tl_set:N = \eb@subfont@footnote,
marginpar .tl_set:N = \marginfont,
marginpar .initial:n = \footnotesize,
unknown .code:n = \eb_msg_deprecated_option:n { subfont }
@@ -1742,23 +1763,23 @@
}
\ctex_define:nn { spread }
{
- line .code:n = \AfterPreamble{\setspread{#1}},
+ line .code:n = \setspread{#1},
line .initial:n =
{
- \fp_if_nan:nTF { \l__ctex_line_spread_fp }
+ \fp_compare:nNnTF { \l__ctex_line_spread_fp } = { 1.3 }
{ 1.354 }
{ \fp_use:N \l__ctex_line_spread_fp }
},
table .fp_set:N = \l__eb_spread_table_fp,
table .initial:n = 1.354,
math .fp_set:N = \l__eb_spread_math_fp,
- math .initial:n = 1.354,
+ math .initial:n = 1.2,
footnote .code:n =
{
- \fp_set:Nn \l__eb_spread_footnote_fp {#1}
+ \tl_set:Nn \eb@spread@footnote {#1}
\group_begin:
\footnotesize
- \setspread{\fp_use:N \l__eb_spread_footnote_fp}
+ \setspread{\eb@spread@footnote}
\exp_args:NNNo \group_end:
\dim_set:Nn \footnotesep { \dim_use:N \box_ht:N \strutbox }
},
@@ -1777,8 +1798,22 @@
line = #1,table = #1,math = #1,
caption-every = #1,footnote = #1
},
- unknown .code:n = \eb_msg_deprecated_option:n { spread }
+ abovedisplayskip .code:n =
+ {\AfterPreamble{\skip_set:Nn \abovedisplayskip {#1}}},
+ abovedisplayskip .initial:n = 0.5ex plus .1ex minus .1ex,
+ belowdisplayskip .code:n =
+ {
+ \AfterPreamble
+ {
+ \skip_set:Nn \belowdisplayskip {#1}
+ \skip_set:Nn \belowdisplayshortskip {#1}
+ }
+ },
+ belowdisplayskip .initial:n = 0.5ex plus .1ex minus .1ex,
+ unknown .code:n = \eb_msg_deprecated_option:n { spread }
}
+\AfterPreamble
+ {\skip_set:Nn \abovedisplayshortskip { 0ex plus .1ex }}
\eb_seq_map_inline:nn
{ table,figure,listing }
@@ -1806,9 +1841,9 @@
\captionsetup[table][bi-second]{name = Table}
}
\eb_at_begin_environment:nn
- { tabular,tabularx,tblr,longtblr,longtable }
+ { tabular,tabularx,longtblr,longtable }
{ \setspread{\fp_use:N \l__eb_spread_table_fp} }
-\IfPackageAtLeastTF{tabularray}{2021/07/01}{\UseTblrLibrary{booktabs}}{}
+\UseTblrLibrary{booktabs}
\bool_if:NF \l__eb_float_page_bool
{
@@ -2022,13 +2057,6 @@
\setspread{\fp_use:N \l__eb_spread_math_fp}
\spread@equation
}
-\ctex_after_end_preamble:n
- {
- \skip_set:Nn \abovedisplayskip { 6pt plus 1pt minus 1pt }
- \skip_set:Nn \belowdisplayskip { 6pt plus 1pt minus 1pt }
- \skip_set:Nn \abovedisplayshortskip { 0pt plus 1pt minus 1pt }
- \skip_set:Nn \belowdisplayshortskip { 6pt plus 1pt minus 1pt }
- }
\ctex_at_end_package:nn { unicode-math }
{ \msg_redirect_module:nnn { unicode-math } { warning } { info } }
\ctex_at_end_package:nn { tcolorbox }
@@ -2071,7 +2099,7 @@
{
\group_begin:
\tl_set_eq:NN \eb@toc@title \bibname
- \IfValueT{##3}{ \keys_set:nn { eb/floattoc } {##3} }
+ \IfValueT{##3}{ \keys_set:nn { eb/tocouter } {##3} }
\cs_set_protected:Npn \bibsection
{
\eb_toc_title_level_cmd:n {##1}
@@ -2092,7 +2120,6 @@
\bool_if:NTF \l__eb_class_mode_book_bool
{ \bichapter*{#1}{\eb@bib@bitoc@title} }
{ \bisection*{#1}{\eb@bib@bitoc@title} }
- \sectionmark{#1}
}
\cs_new_protected:Npn \eb_biber_biblatex_set:
{
@@ -2215,7 +2242,7 @@
\clist_map_function:nN
{
{ none, 000000,000000,000000 },
- { seaside, 4169e1,9932cc,eb6100 },
+ { seaside, 3f3fc4,9932cc,09cc00 },
{ energy, f39800,00a0e9,893895 },
{ cyberpunk, 601986,eb6877,a4005b }
}
@@ -2352,7 +2379,7 @@
}
%</package>
%<*tcolorbox>
-\ProvidesExplFile{eb-tcolorbox.cfg}{2024/02/16}{2024ad}
+\ProvidesExplFile{eb-tcolorbox.cfg}{2024/02/18}{2024ae}
{Customization of tcolorbox for easybook}
\cs_set_protected:Npn \addtotcbstyle #1#2
diff --git a/macros/latex/contrib/easybook/easybook.pdf b/macros/latex/contrib/easybook/easybook.pdf
index dbddf2a96c..1330b516ff 100644
--- a/macros/latex/contrib/easybook/easybook.pdf
+++ b/macros/latex/contrib/easybook/easybook.pdf
Binary files differ
diff --git a/macros/latex/contrib/easybook/easybook.tex b/macros/latex/contrib/easybook/easybook.tex
index 3a725ee03c..92848347f4 100644
--- a/macros/latex/contrib/easybook/easybook.tex
+++ b/macros/latex/contrib/easybook/easybook.tex
@@ -5,7 +5,7 @@
\usepackage
{
enumitem,newtxmath,indentfirst,tabularray,
- fancyvrb,geometry,hologo,pifont,changelog
+ fancyvrb,geometry,hologo,pifont,changelog,calc
}
\definecolorscheme{blue}
{
@@ -23,8 +23,8 @@
name = easybook,
color-scheme = blue,
title = EASYBOOK使用手册,
- version = v2024ad,
- date = 2024/02/16,
+ version = v2024ae,
+ date = 2024/02/18,
authors = 瞿毅,
info = 简便地排版中文学位论文或书籍,
email = toquyi@163.com,
@@ -61,6 +61,7 @@
\ExplSyntaxOn\makeatletter
% * Do not add entries to the index
% - Leave the option value blank
+\let\isvalue\cnltx@isvalue
\NewDocumentCommand{\kvsplit}{st-mm}
{
\item\code
@@ -112,6 +113,12 @@
\IfBooleanF{#1}{\cnltx@checkdefault{\hfill\newline}}
}
\newnote{\newtag}[1][New]{\fbox{#1}}
+% Multi-row values alignment when there are many choices
+\newcommand{\leftfillchoice}[2]
+ {
+ \hspace*{\widthof{\option*{#1}}+\widthof{\code{\cnltx@isvalue}}-1em}
+ \code{\choices{#2}}
+ }
% Use a separate module margin marker to prevent overlap
\newcommand{\smodule}[1]{\cnltx@module@text*{\normalsize #1}}
\newcommand{\noitemsep}{\setlength{\itemsep}{0ex}}
@@ -308,7 +315,8 @@
\end{options}
\begin{options}
- \keychoice{mathfont}{\fbox{times},noto,notosans,nc,stix2,charter,ebgaramond,libertine,none}\dtag
+ \keychoice{mathfont}{\fbox{times},noto,notosans,nc,ncf,stix2,charter,ebgaramond,libertine}\dtag
+ \leftfillchoice{mathfont}{minion,garamondx,baskervaldx,baskerville,none} \\
选择合适的数学字体,将会加载 \pkg*{newtxmath} 和 \pkg*{bm} 宏包。使用选项 \code{none} 时可以使用 \pkg*{unicode-math} 等其它数学字体宏包定义字体。
\end{options}
@@ -454,8 +462,8 @@
\keyval{line}{数值}
正文行距因子。行距因子初始值为 \code{1.354}(相当于 \textsf{Word} 的1.25倍行距),如果设置了文类或 \pkg*{ctex} 宏包的全局行距选项 \option*{linespread} 则初始值设为它的值。
\keyval{table}{数值}\Default{1.354}
- 表格内容行距因子。对传统表格 \env{tabular} 和 \env{tabularx} 等环境以及 \pkg*{tabularray} 宏包的 \env{tblr} 环境生效,同时 \env{tblr} 也自带有 \option*{stretch} 选项设置行距系数。
- \keyval{math}{数值}\Default{1.354}
+ 表格内容行距因子,对传统表格 \env{tabular} 和 \env{tabularx} 等环境生效。\pkg*{tabularray} 宏包的 \env{tblr} 环境自带 \option*{stretch} 和 \option*{rowsep} 等行间距选项,这里不做调整。
+ \keyval{math}{数值}\Default{1.2}
数学环境的行距因子,包含了 \pkg*{amsmath} 和 \pkg*{mathtools} 宏包提供的公式环境。
\keyval{caption-figure}{数值}\Default{1.2}
图片题注的行距因子。
@@ -473,6 +481,10 @@
\end{ctexexam}
\keyval{every}{数值}
统一设置上述所有的行距因子。
+ \keyval{abovedisplayskip}{弹性长度}\Default{0.5ex plus .1ex minus .1ex}\newtag%
+ 行间公式与上面正文间的额外距离。
+ \keyval{belowdisplayskip}{弹性长度}\Default{0.5ex plus .1ex minus .1ex}\newtag%
+ 行间公式与下面正文间的额外距离。
\end{options}
\subsection[其它字体]{其它字体\smodule{subfont}}
@@ -880,7 +892,7 @@
\keyval{lolskip}{弹性长度}\Default{10pt}
代码目录中每章第一个条目上方增加的垂直距离。与 \CTeX 的表格和图片目录中每章间的条目距离选项 \option*{lotskip} 和 \option*{lofskip} 类似,在 \cls*{article} 模式中此选项失效。
\keyval{between}{代码钩子}\dtag[\textcolor{red}{\ding{73}}]
- 目录标题与条目内容间的钩子(作用于标题下方间距之后),一般插入负的垂直距离代码用于抵消目录首行额外的垂直间距。除了条目名的键路径外,此选项也可用于 \module*{tocset} 路径中,表示章节标题目录标题代码钩子。
+ 目录标题与条目内容间的钩子(作用于标题下方间距之后),如果是 \cls*{book} 模式则默认插入 \code{-10pt} 垂直距离抵消首行目录的额外垂直间距,这是由于图表和 由 \pkg*{newfloat} 宏包所创建环境的目录默认每使用一次章标题在题注目录中插入 \code{10pt} 距离。除了条目名的键路径外,此选项也可用于 \module*{tocset} 路径中,表示章节标题目录标题代码钩子,如果是 \cls*{book} 模式则默认插入 \code{-1pc} 垂直距离。
\keyval{bibetween}{代码钩子}
与选项 \option{between} 类似,是英文章节标题目录(如果启用)标题代码钩子。
\keychoice{dotalign}{\fbox{true},false}
@@ -919,7 +931,7 @@
\begin{options}
\keychoice{plan}{\fbox{cn},bi,both}\newtag[Exp]%
章节标题目录的输出方案。\code{cn} 只输出中文目录,\code{bi} 只输出英文目录。\code{both} 同时连续输出中文和英文目录,需要与双语目录标题命令 \cs{bichapter} 等或双语标题选项 \option{title} 配合使用。
- \keyval{bicontentsname}{英文目录标题}\Default{Contents}\newtag%
+ \keyval{bicontentsname}{英文目录标题}\Default{Contents}
英文目录的标题,为通用接口命令 \cs*{ctexset} 的选项。
\end{options}
\command{listoffigures}[\sarg\oarg{键值列表}]
@@ -929,9 +941,13 @@
\command{listoflstlistings}[\sarg\oarg{键值列表}]
输出代码目录命令。带有星号参数的命令不输出目录标题。
- 如果需要部分而不是全文的目录或其它类型的目录,可以查看 \pkg*{titletoc} 宏包的相关示例。如果需要双语图表目录,可以查看 \pkg*{bicaption} 宏包的相关示例。上面目录命令的可选参数改进了原本单一的功能,其中 \meta{键值列表} 的选项如下:
+ 如果需要部分而不是全文的目录或其它类型的目录,可以查看 \pkg*{titletoc} 宏包的相关示例。如果需要双语图表目录,可以查看 \pkg*{bicaption} 宏包的相关示例。上面目录命令的可选参数改进了原本单一的功能,也提供了配置命令 \cs{SetTocOuter} 在目录命令外设置选项默认值。
+ \begin{commands}
+ \command{SetTocOuter}[\marg{键值列表}]\newtag%
+ 统一设置上述所有目录可选参数的默认值\footnote{由于目录命令通常只在文中使用一次,因此不设计为可以分别指定不同目录的参数。},其中 \meta{键值列表} 的选项如下:
+ \end{commands}
\begin{options}
- \keyval{level}{标题命令}\newtag%
+ \keyval{level}{标题命令}
设定输出目录标题的命令。如果使用 \option{title} 选项设置了双语标题则需要配合双语标题命令。
\begin{ctexexam}
\tableofcontents[level = \chapter*]
@@ -942,7 +958,20 @@
\kvsplit{title}{中文目录标题,英文目录标题}
用于更改目录的双语标题。标题之间用一个英文逗号分开,对主目录来说前部分为中文目录标题,后部分为英文目录标题,对图表和代码目录来说后部分则是加入英文目录的条目。也可以只有一部分,表示中文目录的标题。
\keychoice{bilist}{mix,\fbox{new}}
- 确定章节标题目录中双语标题条目的输出排列方式。选项 \code{mix} 使每个英文标题条目在中文目录中跟随对应的中文标题输出,\code{new} 则在新建的英文目录中输出英文标题。
+ 确定章节标题目录中双语标题条目的输出排列方式。选项 \code{mix} 使每个英文标题条目在中文目录中跟随对应的中文标题输出,\code{new} 则在新建的英文目录中输出英文标题。这是个全局选项,在所有目录的可选参数中使用均可生效,但推荐在章节标题目录中使用。
+ \begin{commands}
+ \command{ebifbitoc}[\marg{英文目录代码}\marg{中文目录代码}]\newtag%
+ 启用混合双语目录条目即 \keyis{bilist}{mix} 时,在设置目录样式时可以配合 \cs{ebifbitoc} 命令判断当前条目是否为英文,从而输出不同的代码。
+ \begin{ctexexam}
+ \SetTocStyle{section}{fancy}
+ {
+ tocformat = \ebifbitoc{\color{red}}{\small},
+ tocindent = \ebifbitoc{1em}{2em}
+ }
+ \UseTocStyle{section}{fancy}{toc}
+ \tableofcontents[bilist = mix]
+ \end{ctexexam}
+ \end{commands}
\keyval{format}{目录标题格式}
设置目录标题的格式,在标题级别为 \code{chapter} 或者 \cls*{article} 模式且标题级别为 \code{section} 时有效。
\keyval{aftertitle}{标题后代码}
@@ -1358,13 +1387,17 @@
\shortversion{v = 1.638,date = 2022/03/04,changes = 增加目录条目样式选项注册命令 \cs{RegisterTocName}。}
\shortversion{v = 1.644,date = 2022/03/10,changes = 增加浮动环境目录声明命令 \cs{DeclareFloatList} 配合 \pkg*{caption} 宏包。}
\shortversion{v = 1.682,date = 2022/05/01,changes = 将迷你页判断命令 \cs{notminipage} 改为被保护命令兼容 \pkg*{circledtext} 宏包。}
- \begin{version}[v = 2024ad,date = 2024/02/16,simple]
- \item 核对依赖宏包的更新改动,优化使用手册的内容细节。
+ \begin{version}[v = 2024ae,date = 2024/02/18]
+ \fixed
\item 修复图表等浮动环境题注目录中条目标签编号的计数器值显示错误问题。
\item 修复附录命令 \cs{appendix} 的可选参数设置英文目录中条目名字和编号失效的问题。
+ \item 修复 \pkg*{biblatex} 宏包对脚注打补丁失效的问题。
+ \added
\item 新增目录风格定义命令 \cs{SetTocStyle} 和使用命令 \cs{UseTocStyle}。
+ \item 新增目录配置命令 \cs{SetTocOuter} 双语目录判断命令 \cs{ebifbitoc}。
\item 新增脚注段落文本格式定义命令 \cs{deffntpara} 和脚注间距离选项 \option{footnotesep}。
\item 新增悬挂缩进命令 \cs{hangfrom}。
+ \item 新增行间公式与正文上下间距选项 \option{abovedisplayskip} 和 \option{belowdisplayskip}。
\end{version}
\end{changelog}
\nocite{*}
diff --git a/macros/latex/contrib/l3kernel/CHANGELOG.md b/macros/latex/contrib/l3kernel/CHANGELOG.md
index 472c43a655..ac41336237 100644
--- a/macros/latex/contrib/l3kernel/CHANGELOG.md
+++ b/macros/latex/contrib/l3kernel/CHANGELOG.md
@@ -7,6 +7,15 @@ this project uses date-based 'snapshot' version identifiers.
## [Unreleased]
+## [2024-02-18]
+
+### Changed
+- Work-around to enable `\prop_set_from_keyval:Nn`, etc., to avoid an error if
+ `prop` is not already defined
+
+### Fixed
+- Extend debug checking to cover `\prop_(g)set_from_keyval:Nn`
+
## [2024-02-13]
### Added
@@ -1668,7 +1677,8 @@ this project uses date-based 'snapshot' version identifiers.
- Step functions have been added for dim variables,
e.g. `\dim_step_inline:nnnn`
-[Unreleased]: https://github.com/latex3/latex3/compare/2024-02-13...HEAD
+[Unreleased]: https://github.com/latex3/latex3/compare/2024-02-18...HEAD
+[2024-02-18]: https://github.com/latex3/latex3/compare/2024-02-13...2024-02-18
[2024-02-13]: https://github.com/latex3/latex3/compare/2024-01-22...2024-02-13
[2024-01-22]: https://github.com/latex3/latex3/compare/2024-01-04...2024-01-22
[2024-01-04]: https://github.com/latex3/latex3/compare/2023-12-11...2024-01-04
diff --git a/macros/latex/contrib/l3kernel/README.md b/macros/latex/contrib/l3kernel/README.md
index ee146d0405..769204cdef 100644
--- a/macros/latex/contrib/l3kernel/README.md
+++ b/macros/latex/contrib/l3kernel/README.md
@@ -1,7 +1,7 @@
LaTeX3 Programming Conventions
==============================
-Release 2024-02-13
+Release 2024-02-18
Overview
--------
diff --git a/macros/latex/contrib/l3kernel/expl3.dtx b/macros/latex/contrib/l3kernel/expl3.dtx
index a2f820f71f..f09ff8a437 100644
--- a/macros/latex/contrib/l3kernel/expl3.dtx
+++ b/macros/latex/contrib/l3kernel/expl3.dtx
@@ -24,7 +24,7 @@
%
%<*driver|generic|package|2ekernel>
%</driver|generic|package|2ekernel>
-\def\ExplFileDate{2024-02-13}%
+\def\ExplFileDate{2024-02-18}%
%<*driver>
\documentclass[full]{l3doc}
\usepackage{graphicx}
@@ -51,7 +51,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/expl3.pdf b/macros/latex/contrib/l3kernel/expl3.pdf
index 03b7a491c1..1117b70706 100644
--- a/macros/latex/contrib/l3kernel/expl3.pdf
+++ b/macros/latex/contrib/l3kernel/expl3.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/interface3.pdf b/macros/latex/contrib/l3kernel/interface3.pdf
index dcbc798249..9c0fc6973e 100644
--- a/macros/latex/contrib/l3kernel/interface3.pdf
+++ b/macros/latex/contrib/l3kernel/interface3.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/interface3.tex b/macros/latex/contrib/l3kernel/interface3.tex
index c4c45a6bca..63d687c9bd 100644
--- a/macros/latex/contrib/l3kernel/interface3.tex
+++ b/macros/latex/contrib/l3kernel/interface3.tex
@@ -58,7 +58,7 @@ for those people who are interested.
{latex-team@latex-project.org}%
}%
}
-\date{Released 2023-12-08}
+\date{Released 2024-02-18}
\pagenumbering{roman}
\maketitle
diff --git a/macros/latex/contrib/l3kernel/l3basics.dtx b/macros/latex/contrib/l3kernel/l3basics.dtx
index bc79956d05..0bfa11edaf 100644
--- a/macros/latex/contrib/l3kernel/l3basics.dtx
+++ b/macros/latex/contrib/l3kernel/l3basics.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
@@ -1252,16 +1252,22 @@
% \begin{function}[EXP]{\if:w, \if_charcode:w, \if_catcode:w}
% \begin{syntax}
% "\if:w" <token(s)> <true code> "\else:" <false code> "\fi:" \\
-% "\if_catcode:w" <token(s_> <true code> "\else:" <false code> "\fi:"
+% "\if_catcode:w" <token(s)> <true code> "\else:" <false code> "\fi:"
% \end{syntax}
+% "\if_charcode:w" is an alternative name for "\if:w".
% These conditionals expand \meta{token(s)} until two
-% unexpandable tokens \meta{token_1} and \meta{tokens_2} are left;
-% any further tokens become part of the \meta{true code}.
-% If you wish to prevent this expansion,
-% prefix the token in question with "\exp_not:N". "\if_catcode:w"
-% tests if the category codes of the two tokens are the same whereas
-% "\if:w" tests if the character codes are
-% identical. "\if_charcode:w" is an alternative name for "\if:w".
+% unexpandable tokens \meta{token_1} and \meta{token_2} are found;
+% any further tokens up to the next unbalanced "\else:" are the true branch,
+% ending with \meta{true code}. It is executed if the condition is fulfilled,
+% otherwise \meta{false code} is executed.
+% You can omit "\else:" when just in front of "\fi:" and
+% you can nest "\if...\else:...\fi:" constructs inside the true branch or the
+% \meta{false code}.
+% With "\exp_not:N", you can prevent the expansion of a token.
+%
+% "\if_catcode:w"
+% tests if \meta{token_1} and \meta{token_2} have the same category code whereas
+% "\if:w" and \cs{if_charcode:w} test if they have the same character code.
% \begin{texnote}
% \cs{if:w} and \cs{if_charcode:w} are both the \TeX{} primitive \tn{if}.
% \cs{if_catcode:w} is the \TeX{} primitive \tn{ifcat}.
diff --git a/macros/latex/contrib/l3kernel/l3bitset.dtx b/macros/latex/contrib/l3kernel/l3bitset.dtx
index e87a9c9e0f..38375db79b 100644
--- a/macros/latex/contrib/l3kernel/l3bitset.dtx
+++ b/macros/latex/contrib/l3kernel/l3bitset.dtx
@@ -42,7 +42,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3bootstrap.dtx b/macros/latex/contrib/l3kernel/l3bootstrap.dtx
index b6a747f833..42799fd051 100644
--- a/macros/latex/contrib/l3kernel/l3bootstrap.dtx
+++ b/macros/latex/contrib/l3kernel/l3bootstrap.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3box.dtx b/macros/latex/contrib/l3kernel/l3box.dtx
index 5cb80d888d..5582196acd 100644
--- a/macros/latex/contrib/l3kernel/l3box.dtx
+++ b/macros/latex/contrib/l3kernel/l3box.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3cctab.dtx b/macros/latex/contrib/l3kernel/l3cctab.dtx
index a11b0e31a7..43639710ca 100644
--- a/macros/latex/contrib/l3kernel/l3cctab.dtx
+++ b/macros/latex/contrib/l3kernel/l3cctab.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3clist.dtx b/macros/latex/contrib/l3kernel/l3clist.dtx
index 54b558f7ea..a017b91c03 100644
--- a/macros/latex/contrib/l3kernel/l3clist.dtx
+++ b/macros/latex/contrib/l3kernel/l3clist.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3coffins.dtx b/macros/latex/contrib/l3kernel/l3coffins.dtx
index c8a71eb252..3647bb7d77 100644
--- a/macros/latex/contrib/l3kernel/l3coffins.dtx
+++ b/macros/latex/contrib/l3kernel/l3coffins.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3color.dtx b/macros/latex/contrib/l3kernel/l3color.dtx
index 6ecdf216c4..9d07855fed 100644
--- a/macros/latex/contrib/l3kernel/l3color.dtx
+++ b/macros/latex/contrib/l3kernel/l3color.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3debug.dtx b/macros/latex/contrib/l3kernel/l3debug.dtx
index f345c6d303..af4afcdf69 100644
--- a/macros/latex/contrib/l3kernel/l3debug.dtx
+++ b/macros/latex/contrib/l3kernel/l3debug.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
@@ -69,7 +69,7 @@
%
% Standard file identification.
% \begin{macrocode}
-\ProvidesExplFile{l3debug.def}{2024-02-13}{}{L3 Debugging support}
+\ProvidesExplFile{l3debug.def}{2024-02-18}{}{L3 Debugging support}
% \end{macrocode}
%
% \begin{variable}{\s_@@_stop}
@@ -787,6 +787,7 @@
\prop_put_from_keyval:Nn
\prop_remove:Nn
\prop_set_eq:NN
+ \prop_set_from_keyval:Nn
\seq_set_eq:NN
\skip_zero:N
\skip_set:Nn
@@ -867,6 +868,7 @@
\prop_gput_from_keyval:Nn
\prop_gremove:Nn
\prop_gset_eq:NN
+ \prop_gset_from_keyval:Nn
\seq_gset_eq:NN
\skip_gzero:N
\skip_gset:Nn
diff --git a/macros/latex/contrib/l3kernel/l3deprecation.dtx b/macros/latex/contrib/l3kernel/l3deprecation.dtx
index 674ca610bd..50c5edd996 100644
--- a/macros/latex/contrib/l3kernel/l3deprecation.dtx
+++ b/macros/latex/contrib/l3kernel/l3deprecation.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
@@ -321,9 +321,9 @@
%
% \begin{macro}[deprecated]{\msg_gset:nnnn, \msg_gset:nnn}
% \begin{macrocode}
-\__kernel_patch_deprecation:nnNNpn { 2024-01-17 } { \msg_set:nnnn }
+\__kernel_patch_deprecation:nnNNpn { 2024-02-13 } { \msg_set:nnnn }
\cs_new_protected:Npn \msg_gset:nnnn { \msg_set:nnnn }
-\__kernel_patch_deprecation:nnNNpn { 2024-01-17 } { \msg_set:nnn }
+\__kernel_patch_deprecation:nnNNpn { 2024-02-13 } { \msg_set:nnn }
\cs_new_protected:Npn \msg_gset:nnn { \msg_set:nnn }
% \end{macrocode}
% \end{macro}
diff --git a/macros/latex/contrib/l3kernel/l3doc.dtx b/macros/latex/contrib/l3kernel/l3doc.dtx
index 48e022ae80..9e5c4b5449 100644
--- a/macros/latex/contrib/l3kernel/l3doc.dtx
+++ b/macros/latex/contrib/l3kernel/l3doc.dtx
@@ -71,7 +71,7 @@ and all files in that bundle must be distributed together.
% This isn't included in the typeset documentation because it's a bit
% ugly:
%<*class>
-\ProvidesExplClass{l3doc}{2024-02-13}{}
+\ProvidesExplClass{l3doc}{2024-02-18}{}
{L3 Experimental documentation class}
%</class>
% \fi
@@ -84,7 +84,7 @@ and all files in that bundle must be distributed together.
% require you to do updates, if the class changes.}}
%
% \author{\Team}
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
% \maketitle
% \tableofcontents
%
diff --git a/macros/latex/contrib/l3kernel/l3doc.pdf b/macros/latex/contrib/l3kernel/l3doc.pdf
index 9d301da547..da81829479 100644
--- a/macros/latex/contrib/l3kernel/l3doc.pdf
+++ b/macros/latex/contrib/l3kernel/l3doc.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3docstrip.dtx b/macros/latex/contrib/l3kernel/l3docstrip.dtx
index f55be84c36..08823150c0 100644
--- a/macros/latex/contrib/l3kernel/l3docstrip.dtx
+++ b/macros/latex/contrib/l3kernel/l3docstrip.dtx
@@ -63,7 +63,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3docstrip.pdf b/macros/latex/contrib/l3kernel/l3docstrip.pdf
index 923689f3d8..457ab48f9e 100644
--- a/macros/latex/contrib/l3kernel/l3docstrip.pdf
+++ b/macros/latex/contrib/l3kernel/l3docstrip.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3expan.dtx b/macros/latex/contrib/l3kernel/l3expan.dtx
index 7527b4091a..1af40338cf 100644
--- a/macros/latex/contrib/l3kernel/l3expan.dtx
+++ b/macros/latex/contrib/l3kernel/l3expan.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3file.dtx b/macros/latex/contrib/l3kernel/l3file.dtx
index 091c7b57f0..26ff4b3cf4 100644
--- a/macros/latex/contrib/l3kernel/l3file.dtx
+++ b/macros/latex/contrib/l3kernel/l3file.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3flag.dtx b/macros/latex/contrib/l3kernel/l3flag.dtx
index d1325b2c96..e182bd91f8 100644
--- a/macros/latex/contrib/l3kernel/l3flag.dtx
+++ b/macros/latex/contrib/l3kernel/l3flag.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
@@ -348,9 +348,9 @@
% code is activated, it checks existence of the \texttt{N}-type flag
% variables that result.
%
-% \begin{macro}{\flag_new:n, \flag_clear:n, \flag_clear_new:n}
-% \begin{macro}[EXP, pTF]{\flag_if_exist:n, \flag_if_raised:n}
-% \begin{macro}[EXP]{\flag_height:n, \flag_raise:n, \flag_ensure_raised:n}
+% \begin{macro}[no-user-doc]{\flag_new:n, \flag_clear:n, \flag_clear_new:n}
+% \begin{macro}[EXP, pTF, no-user-doc]{\flag_if_exist:n, \flag_if_raised:n}
+% \begin{macro}[EXP, no-user-doc]{\flag_height:n, \flag_raise:n, \flag_ensure_raised:n}
% \begin{macrocode}
\cs_new_protected:Npn \flag_new:n #1 { \flag_new:c { l_#1_flag } }
\cs_new_protected:Npn \flag_clear:n #1 { \flag_clear:c { l_#1_flag } }
@@ -371,7 +371,7 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\flag_show:n, \flag_log:n, \@@_show:Nn}
+% \begin{macro}[no-user-doc]{\flag_show:n, \flag_log:n, \@@_show:Nn}
% To avoid changing the output here we mostly keep the old code.
% \begin{macrocode}
\cs_new_protected:Npn \flag_show:n { \@@_show:Nn \tl_show:n }
diff --git a/macros/latex/contrib/l3kernel/l3fp-assign.dtx b/macros/latex/contrib/l3kernel/l3fp-assign.dtx
index ca71600b16..acec6c1b92 100644
--- a/macros/latex/contrib/l3kernel/l3fp-assign.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-assign.dtx
@@ -42,7 +42,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
% \maketitle
%
% \begin{documentation}
diff --git a/macros/latex/contrib/l3kernel/l3fp-aux.dtx b/macros/latex/contrib/l3kernel/l3fp-aux.dtx
index 1c8c57a3f9..306c35b86c 100644
--- a/macros/latex/contrib/l3kernel/l3fp-aux.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-aux.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fp-basics.dtx b/macros/latex/contrib/l3kernel/l3fp-basics.dtx
index 4227b8f6f5..f5460d81df 100644
--- a/macros/latex/contrib/l3kernel/l3fp-basics.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-basics.dtx
@@ -42,7 +42,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fp-convert.dtx b/macros/latex/contrib/l3kernel/l3fp-convert.dtx
index 413d4988a5..bdd6f17003 100644
--- a/macros/latex/contrib/l3kernel/l3fp-convert.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-convert.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fp-expo.dtx b/macros/latex/contrib/l3kernel/l3fp-expo.dtx
index 0013d859a9..ecc9f0561c 100644
--- a/macros/latex/contrib/l3kernel/l3fp-expo.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-expo.dtx
@@ -42,7 +42,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fp-extended.dtx b/macros/latex/contrib/l3kernel/l3fp-extended.dtx
index be9cc93107..79490a1f5a 100644
--- a/macros/latex/contrib/l3kernel/l3fp-extended.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-extended.dtx
@@ -42,7 +42,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fp-functions.dtx b/macros/latex/contrib/l3kernel/l3fp-functions.dtx
index 4024dbacf3..5ac7deff34 100644
--- a/macros/latex/contrib/l3kernel/l3fp-functions.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-functions.dtx
@@ -42,7 +42,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fp-logic.dtx b/macros/latex/contrib/l3kernel/l3fp-logic.dtx
index 42d88735c4..c433b72d2d 100644
--- a/macros/latex/contrib/l3kernel/l3fp-logic.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-logic.dtx
@@ -42,7 +42,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fp-parse.dtx b/macros/latex/contrib/l3kernel/l3fp-parse.dtx
index 2bcd5a2c89..7d7c9cabf4 100644
--- a/macros/latex/contrib/l3kernel/l3fp-parse.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-parse.dtx
@@ -42,7 +42,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fp-random.dtx b/macros/latex/contrib/l3kernel/l3fp-random.dtx
index 7d32a59a51..8ca58cc5a7 100644
--- a/macros/latex/contrib/l3kernel/l3fp-random.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-random.dtx
@@ -42,7 +42,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fp-round.dtx b/macros/latex/contrib/l3kernel/l3fp-round.dtx
index e6bb4e58c0..7bdf0c3efd 100644
--- a/macros/latex/contrib/l3kernel/l3fp-round.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-round.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fp-symbolic.dtx b/macros/latex/contrib/l3kernel/l3fp-symbolic.dtx
index 088c118b9c..c771c69d15 100644
--- a/macros/latex/contrib/l3kernel/l3fp-symbolic.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-symbolic.dtx
@@ -42,7 +42,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fp-traps.dtx b/macros/latex/contrib/l3kernel/l3fp-traps.dtx
index 90f33a7aa4..693af9e981 100644
--- a/macros/latex/contrib/l3kernel/l3fp-traps.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-traps.dtx
@@ -42,7 +42,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
% \maketitle
%
% \begin{documentation}
diff --git a/macros/latex/contrib/l3kernel/l3fp-trig.dtx b/macros/latex/contrib/l3kernel/l3fp-trig.dtx
index c7d235b991..28a70763a4 100644
--- a/macros/latex/contrib/l3kernel/l3fp-trig.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-trig.dtx
@@ -42,7 +42,7 @@
% {latex-team@latex-project.org}^^A
% }^^A
% }
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fp-types.dtx b/macros/latex/contrib/l3kernel/l3fp-types.dtx
index 2843b9131c..8a621d7096 100644
--- a/macros/latex/contrib/l3kernel/l3fp-types.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp-types.dtx
@@ -42,7 +42,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fp.dtx b/macros/latex/contrib/l3kernel/l3fp.dtx
index cfd8b118fc..9ccc42b1dc 100644
--- a/macros/latex/contrib/l3kernel/l3fp.dtx
+++ b/macros/latex/contrib/l3kernel/l3fp.dtx
@@ -49,7 +49,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3fparray.dtx b/macros/latex/contrib/l3kernel/l3fparray.dtx
index b9b4e4a096..4c0460d076 100644
--- a/macros/latex/contrib/l3kernel/l3fparray.dtx
+++ b/macros/latex/contrib/l3kernel/l3fparray.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3int.dtx b/macros/latex/contrib/l3kernel/l3int.dtx
index 9a6d09f193..728804f5f4 100644
--- a/macros/latex/contrib/l3kernel/l3int.dtx
+++ b/macros/latex/contrib/l3kernel/l3int.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3intarray.dtx b/macros/latex/contrib/l3kernel/l3intarray.dtx
index cc3f7a2c6c..0c9f78db99 100644
--- a/macros/latex/contrib/l3kernel/l3intarray.dtx
+++ b/macros/latex/contrib/l3kernel/l3intarray.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3kernel-functions.dtx b/macros/latex/contrib/l3kernel/l3kernel-functions.dtx
index c19add5937..0300696929 100644
--- a/macros/latex/contrib/l3kernel/l3kernel-functions.dtx
+++ b/macros/latex/contrib/l3kernel/l3kernel-functions.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
@@ -206,7 +206,7 @@
% \cs{__kernel_deprecation_code:nn} \Arg{error code} \Arg{working code}
% \end{syntax}
% Stores both an \meta{error} and \meta{working} definition for given material
-% such that they can be exchanged by \cs{debug_on:} and \cs{debug_off:}.
+% such that they can be exchanged by \cs{debug_on:n} and \cs{debug_off:n}.
% \end{function}
%
% \begin{function}[EXP]{\__kernel_exp_not:w}
diff --git a/macros/latex/contrib/l3kernel/l3keys.dtx b/macros/latex/contrib/l3kernel/l3keys.dtx
index 18b42ae30d..2b5327c9bb 100644
--- a/macros/latex/contrib/l3kernel/l3keys.dtx
+++ b/macros/latex/contrib/l3kernel/l3keys.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3legacy.dtx b/macros/latex/contrib/l3kernel/l3legacy.dtx
index 0a7b8bb9a1..3c7cfc2937 100644
--- a/macros/latex/contrib/l3kernel/l3legacy.dtx
+++ b/macros/latex/contrib/l3kernel/l3legacy.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3luatex.dtx b/macros/latex/contrib/l3kernel/l3luatex.dtx
index 8a18c7fbf1..ab77d9dab8 100644
--- a/macros/latex/contrib/l3kernel/l3luatex.dtx
+++ b/macros/latex/contrib/l3kernel/l3luatex.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3msg.dtx b/macros/latex/contrib/l3kernel/l3msg.dtx
index 5cbf548e0e..efa741f3b8 100644
--- a/macros/latex/contrib/l3kernel/l3msg.dtx
+++ b/macros/latex/contrib/l3kernel/l3msg.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3names.dtx b/macros/latex/contrib/l3kernel/l3names.dtx
index 6a1bb766d1..72d11a4d9e 100644
--- a/macros/latex/contrib/l3kernel/l3names.dtx
+++ b/macros/latex/contrib/l3kernel/l3names.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3news.pdf b/macros/latex/contrib/l3kernel/l3news.pdf
index 31473fd53c..fd20895dd2 100644
--- a/macros/latex/contrib/l3kernel/l3news.pdf
+++ b/macros/latex/contrib/l3kernel/l3news.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3news01.pdf b/macros/latex/contrib/l3kernel/l3news01.pdf
index 1e97f4aaca..db9c210133 100644
--- a/macros/latex/contrib/l3kernel/l3news01.pdf
+++ b/macros/latex/contrib/l3kernel/l3news01.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3news02.pdf b/macros/latex/contrib/l3kernel/l3news02.pdf
index ed804fc6b3..90f997495b 100644
--- a/macros/latex/contrib/l3kernel/l3news02.pdf
+++ b/macros/latex/contrib/l3kernel/l3news02.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3news03.pdf b/macros/latex/contrib/l3kernel/l3news03.pdf
index ffcf4a37f2..29726a457e 100644
--- a/macros/latex/contrib/l3kernel/l3news03.pdf
+++ b/macros/latex/contrib/l3kernel/l3news03.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3news04.pdf b/macros/latex/contrib/l3kernel/l3news04.pdf
index 971bea5082..0497dfdd70 100644
--- a/macros/latex/contrib/l3kernel/l3news04.pdf
+++ b/macros/latex/contrib/l3kernel/l3news04.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3news05.pdf b/macros/latex/contrib/l3kernel/l3news05.pdf
index bbdc0373a5..f3ff96748c 100644
--- a/macros/latex/contrib/l3kernel/l3news05.pdf
+++ b/macros/latex/contrib/l3kernel/l3news05.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3news06.pdf b/macros/latex/contrib/l3kernel/l3news06.pdf
index 3a46d423fa..f79e8a7b97 100644
--- a/macros/latex/contrib/l3kernel/l3news06.pdf
+++ b/macros/latex/contrib/l3kernel/l3news06.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3news07.pdf b/macros/latex/contrib/l3kernel/l3news07.pdf
index 6c9632fdf4..cdb64db395 100644
--- a/macros/latex/contrib/l3kernel/l3news07.pdf
+++ b/macros/latex/contrib/l3kernel/l3news07.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3news08.pdf b/macros/latex/contrib/l3kernel/l3news08.pdf
index 5ec72ff809..92dcba924e 100644
--- a/macros/latex/contrib/l3kernel/l3news08.pdf
+++ b/macros/latex/contrib/l3kernel/l3news08.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3news09.pdf b/macros/latex/contrib/l3kernel/l3news09.pdf
index a2ea7832c0..03bc119504 100644
--- a/macros/latex/contrib/l3kernel/l3news09.pdf
+++ b/macros/latex/contrib/l3kernel/l3news09.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3news10.pdf b/macros/latex/contrib/l3kernel/l3news10.pdf
index 113dfe2f19..e63e5c5935 100644
--- a/macros/latex/contrib/l3kernel/l3news10.pdf
+++ b/macros/latex/contrib/l3kernel/l3news10.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3news11.pdf b/macros/latex/contrib/l3kernel/l3news11.pdf
index 74d21a3c62..7169cfa33a 100644
--- a/macros/latex/contrib/l3kernel/l3news11.pdf
+++ b/macros/latex/contrib/l3kernel/l3news11.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3news12.pdf b/macros/latex/contrib/l3kernel/l3news12.pdf
index ccbd0305ff..4ee15a6eee 100644
--- a/macros/latex/contrib/l3kernel/l3news12.pdf
+++ b/macros/latex/contrib/l3kernel/l3news12.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3pdf.dtx b/macros/latex/contrib/l3kernel/l3pdf.dtx
index 0490af4c46..75f88eca38 100644
--- a/macros/latex/contrib/l3kernel/l3pdf.dtx
+++ b/macros/latex/contrib/l3kernel/l3pdf.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3prefixes.csv b/macros/latex/contrib/l3kernel/l3prefixes.csv
index 286be82652..54fb41bdeb 100644
--- a/macros/latex/contrib/l3kernel/l3prefixes.csv
+++ b/macros/latex/contrib/l3kernel/l3prefixes.csv
@@ -97,7 +97,7 @@ fmwao,widows-and-orphans,Frank Mittelbach,https://www.latex-project.org/,https:/
fnote,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2023-10-17,2023-10-17,
fnpct,fnpct,Clemens Niederberger,https://github.com/cgnieder/fnpct/,https://github.com/cgnieder/fnpct.git,https://github.com/cgnieder/fnpct/issues,2013-03-16,2020-04-14,
fontsizes,fontsizes,Julien Rivaud,,,,,2018-06-13,
-fontspec,fontspec,Will Robertson,https://github.com/wspr/fontspec,https://github.com/wspr/fontspec.git,https://github.com/wspr/fontspec/issues,2013-03-16,2013-03-16,
+fontspec,fontspec,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/fontspec.git,https://github.com/latex3/fontspec/issues,2013-03-16,2024-02-15,
fp,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
fun,functional,Jianrui Lyu,https://github.com/lvjr/functional,https://github.com/lvjr/functional.git,https://github.com/lvjr/functional/issues,2022-04-02,2022-04-02,
galley,l3galley,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
@@ -277,7 +277,7 @@ withargs,withargs,Michiel Helvensteijn,,,,2014-02-05,2014-02-05,
witharrows,witharrows,François Pantigny,,,,2019-12-19,2019-12-19,
xeCJK,xecjk,Qing Lee,https://github.com/CTeX-org/ctex-kit,https://github.com/CTeX-org/ctex-kit.git,https://github.com/CTeX-org/ctex-kit/issues,2013-05-26,2013-05-26,
xetex,l3kernel,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
-xfrac,xfrac,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
+xfrac,xfrac,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/xfrac.git,https://github.com/latex3/xfrac/issues,2012-09-27,2024-02-14,
xmarks,latex2e,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex2e.git,https://github.com/latex3/latex2e/issues,2021-03-03,2021-03-03,
xparse,xparse,The LaTeX Project,https://www.latex-project.org/latex3.html,https://github.com/latex3/latex3.git,https://github.com/latex3/latex3/issues,2012-09-27,2012-09-27,
xpatch,"regexpatch,xpatch",Enrico Gregorio,,,,2013-03-16,2013-03-16,
diff --git a/macros/latex/contrib/l3kernel/l3prefixes.pdf b/macros/latex/contrib/l3kernel/l3prefixes.pdf
index 2bd39c3787..7aaca4d831 100644
--- a/macros/latex/contrib/l3kernel/l3prefixes.pdf
+++ b/macros/latex/contrib/l3kernel/l3prefixes.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3prg.dtx b/macros/latex/contrib/l3kernel/l3prg.dtx
index 5b7a36238b..a90e86669a 100644
--- a/macros/latex/contrib/l3kernel/l3prg.dtx
+++ b/macros/latex/contrib/l3kernel/l3prg.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3prop.dtx b/macros/latex/contrib/l3kernel/l3prop.dtx
index 8281611924..acab35c56e 100644
--- a/macros/latex/contrib/l3kernel/l3prop.dtx
+++ b/macros/latex/contrib/l3kernel/l3prop.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
@@ -1014,9 +1014,11 @@
% make the second choice; this way props that are accidentally
% \tn{relax} are treated as they were before. The auxiliary receives
% \cs{use_i:nn} or \cs{use_ii:nn} as~|#3|.
+% As a transitional fix we avoid erroring in case the prop is undefined (the \cs{exp_after:wN} is omitted in that case, taking the flat branch).
% \begin{macrocode}
\cs_new:Npn \@@_if_flat:NTF #1
{
+ \prop_if_exist:NT #1
\exp_after:wN \@@_if_flat_aux:w #1
\s_@@_mark \use_ii:nn
\@@_flatten:w \s_@@_mark \use_i:nn \s_@@_stop
diff --git a/macros/latex/contrib/l3kernel/l3quark.dtx b/macros/latex/contrib/l3kernel/l3quark.dtx
index 3aeff3f8de..e29563a054 100644
--- a/macros/latex/contrib/l3kernel/l3quark.dtx
+++ b/macros/latex/contrib/l3kernel/l3quark.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3regex.dtx b/macros/latex/contrib/l3kernel/l3regex.dtx
index d59d61ddb6..2a7e996edd 100644
--- a/macros/latex/contrib/l3kernel/l3regex.dtx
+++ b/macros/latex/contrib/l3kernel/l3regex.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3seq.dtx b/macros/latex/contrib/l3kernel/l3seq.dtx
index c68a7a86af..2eeaf3386e 100644
--- a/macros/latex/contrib/l3kernel/l3seq.dtx
+++ b/macros/latex/contrib/l3kernel/l3seq.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3skip.dtx b/macros/latex/contrib/l3kernel/l3skip.dtx
index e18ea29c9b..0d8ec55663 100644
--- a/macros/latex/contrib/l3kernel/l3skip.dtx
+++ b/macros/latex/contrib/l3kernel/l3skip.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3sort.dtx b/macros/latex/contrib/l3kernel/l3sort.dtx
index 0e9e70bbdb..309bbdc4bb 100644
--- a/macros/latex/contrib/l3kernel/l3sort.dtx
+++ b/macros/latex/contrib/l3kernel/l3sort.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3str-convert.dtx b/macros/latex/contrib/l3kernel/l3str-convert.dtx
index dc87dbb621..75c3e14ee2 100644
--- a/macros/latex/contrib/l3kernel/l3str-convert.dtx
+++ b/macros/latex/contrib/l3kernel/l3str-convert.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3str.dtx b/macros/latex/contrib/l3kernel/l3str.dtx
index 8be8e8ff09..ca31ee72eb 100644
--- a/macros/latex/contrib/l3kernel/l3str.dtx
+++ b/macros/latex/contrib/l3kernel/l3str.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3styleguide.pdf b/macros/latex/contrib/l3kernel/l3styleguide.pdf
index c40939a7a3..e51d369b0b 100644
--- a/macros/latex/contrib/l3kernel/l3styleguide.pdf
+++ b/macros/latex/contrib/l3kernel/l3styleguide.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3styleguide.tex b/macros/latex/contrib/l3kernel/l3styleguide.tex
index d2e46f56c4..98b50b2f30 100644
--- a/macros/latex/contrib/l3kernel/l3styleguide.tex
+++ b/macros/latex/contrib/l3kernel/l3styleguide.tex
@@ -32,7 +32,7 @@ The released version of this bundle is available from CTAN.
{latex-team@latex-project.org}%
}%
}
-\date{Released 2023-12-08}
+\date{Released 2024-02-18}
\begin{document}
diff --git a/macros/latex/contrib/l3kernel/l3syntax-changes.pdf b/macros/latex/contrib/l3kernel/l3syntax-changes.pdf
index e8db43bb3e..3bdc707c38 100644
--- a/macros/latex/contrib/l3kernel/l3syntax-changes.pdf
+++ b/macros/latex/contrib/l3kernel/l3syntax-changes.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3syntax-changes.tex b/macros/latex/contrib/l3kernel/l3syntax-changes.tex
index 0b64e14487..2b605478d0 100644
--- a/macros/latex/contrib/l3kernel/l3syntax-changes.tex
+++ b/macros/latex/contrib/l3kernel/l3syntax-changes.tex
@@ -32,7 +32,7 @@ The released version of this bundle is available from CTAN.
{latex-team@latex-project.org}%
}%
}
-\date{Released 2023-12-08}
+\date{Released 2024-02-18}
\newcommand{\TF}{\textit{(TF)}}
diff --git a/macros/latex/contrib/l3kernel/l3sys.dtx b/macros/latex/contrib/l3kernel/l3sys.dtx
index d62bd9a80b..32de4338c5 100644
--- a/macros/latex/contrib/l3kernel/l3sys.dtx
+++ b/macros/latex/contrib/l3kernel/l3sys.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3term-glossary.pdf b/macros/latex/contrib/l3kernel/l3term-glossary.pdf
index 736d53b4c0..93e859b252 100644
--- a/macros/latex/contrib/l3kernel/l3term-glossary.pdf
+++ b/macros/latex/contrib/l3kernel/l3term-glossary.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/l3term-glossary.tex b/macros/latex/contrib/l3kernel/l3term-glossary.tex
index f26cf48fbe..c9393940ad 100644
--- a/macros/latex/contrib/l3kernel/l3term-glossary.tex
+++ b/macros/latex/contrib/l3kernel/l3term-glossary.tex
@@ -32,7 +32,7 @@ The released version of this bundle is available from CTAN.
{latex-team@latex-project.org}%
}%
}
-\date{Released 2023-12-08}
+\date{Released 2024-02-18}
\newcommand{\TF}{\textit{(TF)}}
diff --git a/macros/latex/contrib/l3kernel/l3text-case.dtx b/macros/latex/contrib/l3kernel/l3text-case.dtx
index ec9368ae18..3d73b8d5d6 100644
--- a/macros/latex/contrib/l3kernel/l3text-case.dtx
+++ b/macros/latex/contrib/l3kernel/l3text-case.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3text-map.dtx b/macros/latex/contrib/l3kernel/l3text-map.dtx
index c8e5db95dc..4ae250c241 100644
--- a/macros/latex/contrib/l3kernel/l3text-map.dtx
+++ b/macros/latex/contrib/l3kernel/l3text-map.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3text-purify.dtx b/macros/latex/contrib/l3kernel/l3text-purify.dtx
index a797b3a609..35a63c0320 100644
--- a/macros/latex/contrib/l3kernel/l3text-purify.dtx
+++ b/macros/latex/contrib/l3kernel/l3text-purify.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3text.dtx b/macros/latex/contrib/l3kernel/l3text.dtx
index 7ef37636f3..91df04a4b8 100644
--- a/macros/latex/contrib/l3kernel/l3text.dtx
+++ b/macros/latex/contrib/l3kernel/l3text.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3tl-analysis.dtx b/macros/latex/contrib/l3kernel/l3tl-analysis.dtx
index 9ff2ec04e7..62ce80c145 100644
--- a/macros/latex/contrib/l3kernel/l3tl-analysis.dtx
+++ b/macros/latex/contrib/l3kernel/l3tl-analysis.dtx
@@ -44,7 +44,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
@@ -1216,7 +1216,7 @@
% {
% \peek_analysis_map_inline:n,
% \@@_peek_analysis_loop:NNn, \@@_peek_analysis_test:,
-% \@@_peek_analysis_exp:N, \@@_peek_analysis_exp_active:N,
+% \@@_peek_analysis_exp:N, \@@_peek_analysis_exp_aux:N,
% \@@_peek_analysis_nonexp:N, \@@_peek_analysis_cs:N,
% \@@_peek_analysis_char:N, \@@_peek_analysis_char:w,
% \@@_peek_analysis_special:, \@@_peek_analysis_retest:,
@@ -1230,9 +1230,11 @@
% Save the user's code in a control sequence that is suitable for
% nested maps. We may wish to pass to this function an \tn{outer}
% control sequence or active character; for this we will undefine
-% potentially-\tn{outer} tokens within a group, closed after the
-% function reads its arguments (for an \tn{outer} active character
-% there is no good alternative). This user's code function also
+% any expandable token (testing if it is \tn{outer} is much slower)
+% within a group, closed immediately after the function reads its
+% arguments to avoid affecting the user's code or even our peek code
+% (there is no risk of undefining \cs{group_end:} itself since that is
+% not expandable). This user's code function also
% calls the loop auxiliary, and includes the trailing
% \cs{prg_break_point:Nn} for when the user wants to stop the loop.
% The loop auxiliary must remove that break point because it must look
@@ -1261,7 +1263,11 @@
% The loop starts a group (closed by the user-code function defined
% above) with a normalized escape character, and checks if the next
% token is special or \texttt{N}-type (distinguishing expandable from
-% non-expandable tokens).
+% non-expandable tokens). The test for nonexpandable tokens in
+% \cs{@@_peek_analysis_test:} must be done after the tests for
+% begin-group, end-group, and space tokens, in case \cs{l_peek_token}
+% is either \tn{outer} or is a primitive \TeX{} conditional, as such
+% tokens cannot be skipped over correctly by conditional code.
% \begin{macrocode}
\cs_new_protected:Npn \@@_peek_analysis_loop:NNn #1#2#3
{
@@ -1317,11 +1323,9 @@
% the two cases is easy: since we have made the escape character
% printable, \cs{token_to_str:N} gives at least two characters for a
% control sequence versus a single one for an active character
-% (possibly being a space). Producing the right outcome is trickier,
-% as |#1| cannot appear in either branch of the conditional (it could
-% be \tn{outer}, or simply a \TeX{} conditional), and can only be
-% safely discarded by \cs{use_none:n} if it is first hit with
-% \cs{exp_not:N}.
+% (possibly being a space). Importantly, once we apply
+% \cs{token_to_str:N} we no longer need to worry about \tn{outer}
+% tokens.
% \begin{macrocode}
\cs_new_protected:Npn \@@_peek_analysis_exp:N #1
{
@@ -1333,22 +1337,19 @@
\exp_not:n { \__kernel_exp_not:w \exp_after:wN }
{ \exp_not:N \exp_not:N \exp_not:N #1 }
}
- \if:w \scan_stop:
- \exp_after:wN \use_none:n \token_to_str:N #1 \prg_do_nothing:
- \scan_stop:
- \exp_after:wN \exp_after:wN
- \exp_after:wN \@@_peek_analysis_exp_active:N
- \else:
- { -1 } 0
- \exp_after:wN \exp_after:wN
- \exp_after:wN \use_none:n
- \fi:
- \exp_not:N #1
+ \exp_after:wN \@@_peek_analysis_exp_aux:Nw
+ \token_to_str:N #1 \prg_do_nothing: \s_@@
}
\l_@@_peek_code_tl
}
-\cs_new:Npe \@@_peek_analysis_exp_active:N #1
- { { \exp_not:N \int_value:w `#1 } \token_to_str:N D }
+\cs_new:Npe \@@_peek_analysis_exp_aux:Nw #1#2 \s_@@
+ {
+ \exp_not:N \if:w \scan_stop: #2 \scan_stop:
+ { \exp_not:N \int_value:w `#1 } \token_to_str:N D
+ \exp_not:N \else:
+ { -1 } 0
+ \exp_not:N \fi:
+ }
% \end{macrocode}
% For normal non-expandable tokens we must distinguish characters
% (including active ones and macro parameter characters) from control
@@ -1357,10 +1358,9 @@
% sequence call the user code with suitable arguments, wrapping |#1|
% within \cs{exp_not:n} just in case it happens to be equal to a macro
% parameter character. We do not skip \cs{exp_not:n} when
-% unnecessary, because there might be situations where the argument
-% could be used by the user after further redefinitions of the token,
-% and it seems more convenient to know that \cs{exp_not:n} is always
-% used.
+% unnecessary, because this auxiliary is also called in
+% \cs{@@_peek_analysis_retest:} where we have changed some control
+% sequences or active characters to \cs{scan_stop:} temporarily.
% \begin{macrocode}
\cs_new_protected:Npn \@@_peek_analysis_nonexp:N #1
{
@@ -1389,12 +1389,17 @@
% characters to anything else than character code~$32$), then we apply
% \cs{@@_analysis_b_char:Nn}, which detects active characters by
% comparing them to \cs{tex_undefined:D}, and we must have undefined
-% the active space for this test to work ---we use an |e|-expanding
-% assignment to get the active space in the right place. Finally
-% \cs{@@_peek_analysis_char:w} puts the arguments in the correct
-% order, including \cs{exp_not:n} for macro parameter characters and
-% active characters (the latter could be macro parameter characters,
-% and it seems more uniform to always put \cs{exp_not:n}).
+% the active space (locally) for this test to work.
+% To define \cs{@@_peek_analysis_char:N} itself we use an
+% |e|-expanding assignment to get the active space in the right place
+% after making it (just for this definition) unexpandable.
+% Finally \cs{@@_peek_analysis_char:w} receives the \meta{charcode},
+% \meta{user function}, \meta{catcode}, and \meta{token}, and places
+% the arguments in the correct order. It keeps \cs{exp_not:n} for
+% macro parameter characters and active characters (the latter could
+% be macro parameter characters, and it seems more uniform to always
+% put \cs{exp_not:n}), and otherwise eliminates it by expanding once
+% with \cs{exp_args:NNNo}.
% \begin{macrocode}
\group_begin:
\char_set_active_eq:NN \ \scan_stop:
@@ -1457,7 +1462,7 @@
\cs_new_protected:Npn \@@_peek_analysis_retest:
{
\if_meaning:w \l_@@_analysis_token \scan_stop:
- \exp_after:wN \@@_peek_analysis_normal:N
+ \exp_after:wN \@@_peek_analysis_nonexp:N
\else:
\exp_after:wN \@@_peek_analysis_str:
\fi:
@@ -1607,8 +1612,8 @@
\@@_peek_analysis_collect:w
}
% \end{macrocode}
-% End by calling the user code with suitable arguments (here |#1|,
-% |#2| are \cs{fi:}), which closes the group begun early on.
+% As in all other cases, end by calling the user code with suitable
+% arguments (here |#1| is \cs{fi:}).
% \begin{macrocode}
\cs_new_protected:Npn \@@_peek_analysis_collect_end:NNNN #1#2#3#4
{
diff --git a/macros/latex/contrib/l3kernel/l3tl-build.dtx b/macros/latex/contrib/l3kernel/l3tl-build.dtx
index 7971301ef3..4a2b44b287 100644
--- a/macros/latex/contrib/l3kernel/l3tl-build.dtx
+++ b/macros/latex/contrib/l3kernel/l3tl-build.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3tl.dtx b/macros/latex/contrib/l3kernel/l3tl.dtx
index 1043feaad9..c1391c9de1 100644
--- a/macros/latex/contrib/l3kernel/l3tl.dtx
+++ b/macros/latex/contrib/l3kernel/l3tl.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/l3token.dtx b/macros/latex/contrib/l3kernel/l3token.dtx
index fe8d1a780e..a5a225ab8b 100644
--- a/macros/latex/contrib/l3kernel/l3token.dtx
+++ b/macros/latex/contrib/l3kernel/l3token.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
@@ -1005,6 +1005,10 @@
% effect after the loop. Within the code, \cs{l_peek_token} is set
% equal (as a token, not a token list) to the token under
% consideration.
+%
+% Peek functions cannot be used within this mapping function (nor
+% other mapping functions) since the input stream contains trailing
+% material necessary for the functioning of the loop.
% \begin{texnote}
% In case the input stream has not yet been tokenized (converted
% from characters to tokens), characters are tokenized one by one as
diff --git a/macros/latex/contrib/l3kernel/l3unicode.dtx b/macros/latex/contrib/l3kernel/l3unicode.dtx
index de3b6067ba..fd4171ffaf 100644
--- a/macros/latex/contrib/l3kernel/l3unicode.dtx
+++ b/macros/latex/contrib/l3kernel/l3unicode.dtx
@@ -43,7 +43,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
diff --git a/macros/latex/contrib/l3kernel/source3.pdf b/macros/latex/contrib/l3kernel/source3.pdf
index 09f28f0667..f660845598 100644
--- a/macros/latex/contrib/l3kernel/source3.pdf
+++ b/macros/latex/contrib/l3kernel/source3.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3kernel/source3.tex b/macros/latex/contrib/l3kernel/source3.tex
index 5aae34aba2..0527b2c6de 100644
--- a/macros/latex/contrib/l3kernel/source3.tex
+++ b/macros/latex/contrib/l3kernel/source3.tex
@@ -57,7 +57,7 @@ for those people who are interested.
{latex-team@latex-project.org}%
}%
}
-\date{Released 2023-12-08}
+\date{Released 2024-02-18}
\pagenumbering{roman}
\maketitle
diff --git a/macros/latex/contrib/l3packages/CHANGELOG.md b/macros/latex/contrib/l3packages/CHANGELOG.md
index abef360b7a..4677988532 100644
--- a/macros/latex/contrib/l3packages/CHANGELOG.md
+++ b/macros/latex/contrib/l3packages/CHANGELOG.md
@@ -7,6 +7,11 @@ this project uses date-based 'snapshot' version identifiers.
## [Unreleased]
+## [2024-02-18]
+
+### Changed
+- Re-added `\IfInstanceExist(TF)` to docs - is required
+
## [2024-02-13]
### Changed
@@ -243,7 +248,8 @@ this project uses date-based 'snapshot' version identifiers.
- Switch to ISO date format
- Improve cross-module use of internal functions
-[Unreleased]: https://github.com/latex3/latex3/compare/2024-02-13...HEAD
+[Unreleased]: https://github.com/latex3/latex3/compare/2024-02-18...HEAD
+[2024-02-18]: https://github.com/latex3/latex3/compare/2024-02-13...2024-02-18
[2024-02-13]: https://github.com/latex3/latex3/compare/2023-10-10...2024-02-13
[2023-10-10]: https://github.com/latex3/latex3/compare/2023-08-29...2023-10-10
[2023-08-29]: https://github.com/latex3/latex3/compare/2023-02-02...2023-08-29
diff --git a/macros/latex/contrib/l3packages/README.md b/macros/latex/contrib/l3packages/README.md
index 2579ee6e96..2b489b3e97 100644
--- a/macros/latex/contrib/l3packages/README.md
+++ b/macros/latex/contrib/l3packages/README.md
@@ -1,6 +1,6 @@
# `l3packages`: Higher-level LaTeX3 Concepts (Deprecated)
-Release 2024-02-13
+Release 2024-02-18
## Overview
diff --git a/macros/latex/contrib/l3packages/l3keys2e.dtx b/macros/latex/contrib/l3packages/l3keys2e.dtx
index f5c494120a..a65b0239dd 100644
--- a/macros/latex/contrib/l3packages/l3keys2e.dtx
+++ b/macros/latex/contrib/l3packages/l3keys2e.dtx
@@ -62,7 +62,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
@@ -154,7 +154,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{l3keys2e}{2024-02-13}{}
+\ProvidesExplPackage{l3keys2e}{2024-02-18}{}
{LaTeX2e option processing using LaTeX3 keys}
% \end{macrocode}
%
diff --git a/macros/latex/contrib/l3packages/l3keys2e.pdf b/macros/latex/contrib/l3packages/l3keys2e.pdf
index a6e0bd9e41..b05bece984 100644
--- a/macros/latex/contrib/l3packages/l3keys2e.pdf
+++ b/macros/latex/contrib/l3packages/l3keys2e.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3packages/xfp.dtx b/macros/latex/contrib/l3packages/xfp.dtx
index d695d44bb1..3a97e46903 100644
--- a/macros/latex/contrib/l3packages/xfp.dtx
+++ b/macros/latex/contrib/l3packages/xfp.dtx
@@ -63,7 +63,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
@@ -171,7 +171,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{xfp}{2024-02-13}{}
+\ProvidesExplPackage{xfp}{2024-02-18}{}
{L3 Floating point unit}
% \end{macrocode}
%
diff --git a/macros/latex/contrib/l3packages/xfp.pdf b/macros/latex/contrib/l3packages/xfp.pdf
index b45cdd5b15..0544fac0fa 100644
--- a/macros/latex/contrib/l3packages/xfp.pdf
+++ b/macros/latex/contrib/l3packages/xfp.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3packages/xparse.dtx b/macros/latex/contrib/l3packages/xparse.dtx
index e701edada3..6dba694d39 100644
--- a/macros/latex/contrib/l3packages/xparse.dtx
+++ b/macros/latex/contrib/l3packages/xparse.dtx
@@ -67,7 +67,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
@@ -1064,7 +1064,7 @@
% \end{macrocode}
%
% \begin{macrocode}
-\ProvidesExplPackage{xparse}{2024-02-13}{}
+\ProvidesExplPackage{xparse}{2024-02-18}{}
{L3 Experimental document command parser}
% \end{macrocode}
%
diff --git a/macros/latex/contrib/l3packages/xparse.pdf b/macros/latex/contrib/l3packages/xparse.pdf
index 183ebaaa78..d666c5ec7f 100644
--- a/macros/latex/contrib/l3packages/xparse.pdf
+++ b/macros/latex/contrib/l3packages/xparse.pdf
Binary files differ
diff --git a/macros/latex/contrib/l3packages/xtemplate.dtx b/macros/latex/contrib/l3packages/xtemplate.dtx
index ee393ef3b3..7a956d82bf 100644
--- a/macros/latex/contrib/l3packages/xtemplate.dtx
+++ b/macros/latex/contrib/l3packages/xtemplate.dtx
@@ -46,7 +46,7 @@
% }^^A
% }
%
-% \date{Released 2024-02-13}
+% \date{Released 2024-02-18}
%
% \maketitle
%
@@ -450,6 +450,14 @@
% the general idea of fixing some settings.
% \end{function}
%
+% \begin{function}{\IfInstanceExistT, \IfInstanceExistF, \IfInstanceExistTF}
+% \begin{syntax}
+% \cs{IfInstanceExistTF} \Arg{object type} \Arg{instance} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if the named \meta{instance} of a \meta{object type} exists, and
+% then inserts the appropriate code into the input stream.
+% \end{function}
+%
% \begin{function}{\DeclareInstanceCopy}
% \begin{syntax}
% \cs{DeclareInstanceCopy}
diff --git a/macros/latex/contrib/l3packages/xtemplate.pdf b/macros/latex/contrib/l3packages/xtemplate.pdf
index c5fc465835..9edb9f169a 100644
--- a/macros/latex/contrib/l3packages/xtemplate.pdf
+++ b/macros/latex/contrib/l3packages/xtemplate.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam-a-answer.pdf b/macros/latex/contrib/randexam/randexam-a-answer.pdf
index 6c62155246..d961cd9cb5 100644
--- a/macros/latex/contrib/randexam/randexam-a-answer.pdf
+++ b/macros/latex/contrib/randexam/randexam-a-answer.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam-a-answer.tex b/macros/latex/contrib/randexam/randexam-a-answer.tex
index bd1cbc9f70..09fecee21c 100644
--- a/macros/latex/contrib/randexam/randexam-a-answer.tex
+++ b/macros/latex/contrib/randexam/randexam-a-answer.tex
@@ -2,7 +2,7 @@
% !TEX program = xelatex
\documentclass[12pt,math=all]{randexam}
-%\boolfalse{exam@answer} % hide answers
+%\SetExamBoolFalse{answer} % hide answers
\SetExamOption{
seed = 19061116, % random seed
@@ -14,7 +14,7 @@
\gradetable[total=4]
-\exampart{Fill in the blanks.}{6 questions; 3 points for each; 18 points in total.}
+\exampart{Fill in the blanks.}[6 questions; 3 points for each; 18 points in total.]
% make answer table: six in total, three for each row, strut height 3em
\answertable[total=6,column=3,strut=3em]
@@ -71,7 +71,7 @@ text text text text text text text text text text $\xi-2\eta\sim$ \fillout{$N(-3
\newpage
-\exampart{Select one answer from four choices.}{6 questions; 3 points for each; 18 points in total.}
+\exampart{Select one answer from four choices.}[6 questions; 3 points for each; 18 points in total.]
% make answer table: six in total, six for each row, default strut height
\answertable[total=6,column=6]
@@ -170,7 +170,7 @@ text text text text text text text text text text text text text text \pickout{D
\newpage
-\exampart{Work out math questions.}{6 questions; 8 points for each; 48 points in total.}
+\exampart{Work out math questions.}[6 questions; 8 points for each; 48 points in total.]
\begin{question}
The first question $\int\e^{2x}\,(\tan x+1)^2\dx$.
@@ -307,7 +307,7 @@ Text text $H_0:\mu=3140$ text text ($\alpha = 0.01$).
\newpage
-\exampart{Work out math proofs.}{2 questions; 16 points in total.}
+\exampart{Work out math proofs.}[2 questions; 16 points in total.]
\SetExamTranslation{solution-Solution=Proof} % rename "Solution" as "Proof"
diff --git a/macros/latex/contrib/randexam/randexam-a-blank.pdf b/macros/latex/contrib/randexam/randexam-a-blank.pdf
index dcc54e2939..9656be370d 100644
--- a/macros/latex/contrib/randexam/randexam-a-blank.pdf
+++ b/macros/latex/contrib/randexam/randexam-a-blank.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam-b-answer.pdf b/macros/latex/contrib/randexam/randexam-b-answer.pdf
index c6be0a3b3d..fe0867038c 100644
--- a/macros/latex/contrib/randexam/randexam-b-answer.pdf
+++ b/macros/latex/contrib/randexam/randexam-b-answer.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam-b-blank.pdf b/macros/latex/contrib/randexam/randexam-b-blank.pdf
index 17ea5a41ab..c059b6e615 100644
--- a/macros/latex/contrib/randexam/randexam-b-blank.pdf
+++ b/macros/latex/contrib/randexam/randexam-b-blank.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam.cls b/macros/latex/contrib/randexam/randexam.cls
index 105d3de168..ec5d1c43c2 100644
--- a/macros/latex/contrib/randexam/randexam.cls
+++ b/macros/latex/contrib/randexam/randexam.cls
@@ -6,7 +6,7 @@
% ----------------------------------------------------------------------------
\NeedsTeXFormat{LaTeX2e}
-\ProvidesClass{randexam}[2024-02-03 v2024D Make an exam paper and its randomized variants]
+\ProvidesClass{randexam}[2024-02-18 v2024E Make an exam paper and its randomized variants]
%% Old LaTeX release could not recognize date format like 2022-11-01
%\@ifl@t@r\fmtversion{2022-11-01}{}{
@@ -25,27 +25,74 @@
\IgnoreSpacesOn
%% ---------------------------------------------------------------------------
-%% Declare class options
+%% Boolean commands for this class
%% ---------------------------------------------------------------------------
\RequirePackage{etoolbox}
-\newbool{exam@plain} \boolfalse{exam@plain} % use plain page style
-\newbool{exam@twoinone} \boolfalse{exam@twoinone} % use A3 paper
-\newbool{exam@oneside} \boolfalse{exam@oneside} % use single sided exam paper
-\newbool{exam@resetnumber}\booltrue{exam@resetnumber} % reset numbers in new exam parts
-\newbool{exam@random} \boolfalse{exam@random} % shuffle questions
-\newbool{exam@answer} \booltrue{exam@answer} % show answers
-\newbool{exam@evaluator} \boolfalse{exam@evaluator} % add evaluator line in the grade table
-\newbool{exam@mathdesign} \booltrue{exam@mathdesign} % use mathdesign fonts
-\newbool{exam@freealign} \boolfalse{exam@freealign} % load freealign package
-\newbool{exam@medmath} \boolfalse{exam@medmath} % use medium-size formulas
-\newbool{exam@moremath} \boolfalse{exam@moremath} % define more math commands
+\NewDocumentCommand\NewExamBool{m}{
+ \newbool{exam@#1}
+}
+
+\NewDocumentCommand\SetExamBoolTrue{m}{
+ \booltrue{exam@#1}
+}
+
+\NewDocumentCommand\SetExamBoolFalse{m}{
+ \boolfalse{exam@#1}
+}
+
+\NewExpandableDocumentCommand\IfExamBoolT{m+m}{
+ \ifbool{exam@#1}{#2}{}
+}
+
+\NewExpandableDocumentCommand\IfExamBoolF{m+m}{
+ \ifbool{exam@#1}{}{#2}
+}
+
+\NewExpandableDocumentCommand\IfExamBoolTF{m+m+m}{
+ \ifbool{exam@#1}{#2}{#3}
+}
+
+%% ---------------------------------------------------------------------------
+%% Declare language commands
+%% ---------------------------------------------------------------------------
+
+\tlSet\l@rdxm@current@language@tl{english}
+
+\NewExpandableDocumentCommand\IfExamLanguageEqT{m+m}{
+ \ExpandArgs{V}\ifstrequal\l@rdxm@current@language@tl{#1}{#2}{}
+}
+
+\NewExpandableDocumentCommand\IfExamLanguageEqF{m+m}{
+ \ExpandArgs{V}\ifstrequal\l@rdxm@current@language@tl{#1}{}{#2}
+}
+
+\NewExpandableDocumentCommand\IfExamLanguageEqTF{m+m+m}{
+ \ExpandArgs{V}\ifstrequal\l@rdxm@current@language@tl{#1}{#2}{#3}
+}
+
+%% ---------------------------------------------------------------------------
+%% Declare class options
+%% ---------------------------------------------------------------------------
+
+\NewExamBool{plain} \SetExamBoolFalse{plain} % use plain page style
+\NewExamBool{twoinone} \SetExamBoolFalse{twoinone} % use A3 paper
+\NewExamBool{oneside} \SetExamBoolFalse{oneside} % use single sided exam paper
+\NewExamBool{resetnumber}\SetExamBoolTrue{resetnumber} % reset numbers in new exam parts
+\NewExamBool{random} \SetExamBoolFalse{random} % shuffle questions
+\NewExamBool{answer} \SetExamBoolTrue{answer} % show answers
+\NewExamBool{evaluator} \SetExamBoolFalse{evaluator} % add evaluator line in the grade table
+\NewExamBool{mathdesign} \SetExamBoolTrue{mathdesign} % use mathdesign fonts
+\NewExamBool{freealign} \SetExamBoolFalse{freealign} % load freealign package
+\NewExamBool{medmath} \SetExamBoolFalse{medmath} % use medium-size formulas
+\NewExamBool{moremath} \SetExamBoolFalse{moremath} % define more math commands
\DeclareKeys[randexam]{
- plain .if = exam@plain
+ language .store = \l@rdxm@current@language@tl
+ ,plain .if = exam@plain
,a3paper .if = exam@twoinone
- ,a3input .code = \booltrue{exam@twoinone}\booltrue{exam@plain}
+ ,a3input .code = \SetExamBoolTrue{twoinone}\SetExamBoolTrue{plain}
,oneside .if = exam@oneside
,random .if = exam@random
,noanswer .ifnot = exam@answer
@@ -56,26 +103,26 @@
,moremath .if = exam@moremath
,math .choice:
,math .default:n = many
- ,math/many .code = \booltrue{exam@mathdesign}\booltrue{exam@freealign}
- ,math/most .code = \booltrue{exam@mathdesign}\booltrue{exam@freealign}
- \booltrue{exam@medmath}
- ,math/all .code = \booltrue{exam@mathdesign}\booltrue{exam@freealign}
- \booltrue{exam@medmath}\booltrue{exam@moremath}
+ ,math/many .code = \SetExamBoolTrue{mathdesign}\SetExamBoolTrue{freealign}
+ ,math/most .code = \SetExamBoolTrue{mathdesign}\SetExamBoolTrue{freealign}
+ \SetExamBoolTrue{medmath}
+ ,math/all .code = \SetExamBoolTrue{mathdesign}\SetExamBoolTrue{freealign}
+ \SetExamBoolTrue{medmath}\SetExamBoolTrue{moremath}
}
%% Support for Chinese language
-\newbool{exam@ctex} \boolfalse{exam@ctex} % load ctex package
-\newbool{exam@solidot} \boolfalse{exam@solidot} % use full-width solid periods
-\newbool{exam@sourcehan}\boolfalse{exam@sourcehan} % use source han font
+\NewExamBool{ctex} \SetExamBoolFalse{ctex} % load ctex package
+\NewExamBool{solidot} \SetExamBoolFalse{solidot} % use full-width solid periods
+\NewExamBool{sourcehan}\SetExamBoolFalse{sourcehan} % use source han font
\DeclareKeys[randexam]{
ctex .if = exam@ctex
,solidot .if = exam@solidot
,sourcehan .if = exam@sourcehan
,chinese .choice:
,chinese .default:n = many
- ,chinese/many .code = \booltrue{exam@ctex}
- ,chinese/most .code = \booltrue{exam@ctex}\booltrue{exam@solidot}
- ,chinese/all .code = \booltrue{exam@ctex}\booltrue{exam@solidot}\booltrue{exam@sourcehan}
+ ,chinese/many .code = \SetExamBoolTrue{ctex}
+ ,chinese/most .code = \SetExamBoolTrue{ctex}\SetExamBoolTrue{solidot}
+ ,chinese/all .code = \SetExamBoolTrue{ctex}\SetExamBoolTrue{solidot}\SetExamBoolTrue{sourcehan}
}
\DeclareUnknownKeyHandler{\PassOptionsToClass{\CurrentOption}{article}}
@@ -84,12 +131,18 @@
\LoadClass{article}
-\ifbool{exam@twoinone}{
+%% Avoid option conflicts with fontspec package
+%% see https://github.com/latex3/fontspec/issues/501
+\let\@raw@classoptionslist\@empty
+
+\IfExamBoolTF{twoinone}{
\RequirePackage[a3paper,landscape,twocolumn,columnsep=60mm,left=30mm,right=30mm,top=25mm,bottom=25mm]{geometry}
}{
\RequirePackage[a4paper,left=30mm,right=30mm,top=25mm,bottom=25mm]{geometry}
}
+\geometry{headheight=17pt}
+
\RequirePackage{amsmath}
\RequirePackage{array}
\RequirePackage{calc}
@@ -100,10 +153,12 @@
\RequirePackage{zref-user,zref-lastpage}
\RequirePackage{tabularx}
\RequirePackage{xcolor}
+\RequirePackage{tabularray}
+\UseTblrLibrary{diagbox}
-\ifbool{exam@plain}{\allowdisplaybreaks[4]}{}
+\IfExamBoolT{plain}{\allowdisplaybreaks[4]}
-\ifbool{exam@twoinone}{
+\IfExamBoolT{twoinone}{
\RequirePackage{pdfpages}
% When pdfpages package is newer enough, putting \includepdf at the beginning
% of document body will cause an error about an undefined command;
@@ -111,9 +166,9 @@
% Also since LaTeX release 2018-04-01 \@ifundefined won't turn an undefined command
% into \relax; see https://www.latex-project.org/news/latex2e-news/ltnews28.pdf
\@ifundefined{@setmarks}{\let\@setmarks\relax}{}
-}{}
+}
-\ifbool{exam@mathdesign}{
+\IfExamBoolTF{mathdesign}{
\RequirePackage[utopia]{mathdesign} % charter, utopia
\renewcommand\bfdefault{bx}
\let\oldoiint\oiint\renewcommand{\oiint}{\oldoiint\nolimits}
@@ -122,6 +177,7 @@
\RequirePackage{amssymb}
}
+\setlength\arraycolsep{4pt}
\newcolumntype{Y}{>{\centering\arraybackslash}X}
\newcolumntype{n}[1]{>{\centering\arraybackslash}m{#1}}
@@ -157,8 +213,6 @@
%% Translation commands for exam keywords
%% ---------------------------------------------------------------------------
-\tlSet\l@rdxm@current@language@tl{english}
-
\DeclareUnknownKeyHandler[randexam/translation]{
\tlSet{\expName{l@rdxm@translate@\l@rdxm@declare@language@tl @#1@tl}}{#2}
}
@@ -223,7 +277,7 @@
,solution-Solution = Solution
}
-\SelectExamTranslation{english}
+\ExpandArgs{V}\SelectExamTranslation\l@rdxm@current@language@tl
%% ---------------------------------------------------------------------------
%% Keyvalue commands for exam elements
@@ -257,6 +311,16 @@
\UseName{l@rdxm@value@#1@#2@tl}
}
+\NewExpandableDocumentCommand\IfExamValueEmptyT{mm+m}{
+ \ifcsempty{l@rdxm@value@#1@#2@tl}{#3}{}
+}
+\NewExpandableDocumentCommand\IfExamValueEmptyF{mm+m}{
+ \ifcsempty{l@rdxm@value@#1@#2@tl}{}{#3}
+}
+\NewExpandableDocumentCommand\IfExamValueEmptyTF{mm+m+m}{
+ \ifcsempty{l@rdxm@value@#1@#2@tl}{#3}{#4}
+}
+
%% In fact, \ifdef/ifcsname is a wrapper for \ifdefined/\ifcsname in eTeX;
%% they will not turn an undefined macro into \relax
\NewExpandableDocumentCommand\IfExamValueExistT{mm+m}{
@@ -275,6 +339,44 @@
}
%% ---------------------------------------------------------------------------
+%% Theme commands for exam papers
+%% ---------------------------------------------------------------------------
+
+%% #1: theme name; #2: theme code
+\NewDocumentCommand\DeclareExamTheme{m+m}{
+ \tlSet{\expName{l@rdxm@theme@#1@tl}}{#2}
+}
+
+%% #1: theme name
+\NewDocumentCommand\SelectExamTheme{m}{
+ \UseName{l@rdxm@theme@#1@tl}
+}
+
+\DeclareKeys[randexam]{
+ theme .code = \SelectExamTheme{#1}
+}
+
+%% ---------------------------------------------------------------------------
+%% Fill commands for exam papers
+%% ---------------------------------------------------------------------------
+
+\NewDocumentCommand\ExamFillCdot{}{
+ \leavevmode\xleaders\hbox to 0.5em{\hss$\cdot$\hss}\hfill\kern0pt\relax
+}
+
+\NewDocumentCommand\ExamFillUline{}{
+ \xleaders\hbox{\underline{\kern1pt}}\hfill\kern0pt
+}
+
+\NewDocumentCommand\ExamFillUlinePhantom{m}{
+ \xleaders\hbox{\underline{\vphantom{#1}\kern1pt}}\hfill\kern0pt
+}
+
+\NewDocumentCommand\ExamFillUlineText{m}{
+ \ExamFillUlinePhantom{#1}\underline{#1}\ExamFillUlinePhantom{#1}
+}
+
+%% ---------------------------------------------------------------------------
%% Command for exam title: \examtitle
%% ---------------------------------------------------------------------------
@@ -289,7 +391,7 @@
\DeclareExamTemplate{examtitle}{normal}{
\begingroup
\Large\noindent
- \ifbool{exam@answer}{
+ \IfExamBoolTF{answer}{
\textcolor{red!80!black}{
\UseExamValue{examtitle}{name}\hfill\UseExamTranslation{examtitle-Solutions}
}
@@ -302,15 +404,15 @@
\NewDocumentCommand\examtitle{+m}{
\SetExamValue{examtitle}{#1}
- \thispagestyle{plain}
- \ifbool{exam@random}{
+ \IfExamBoolF{plain}{\thispagestyle{fancyfirst}}
+ \IfExamBoolT{random}{
\tlIfEqT{\expWhole{\UseExamValue{examtitle}{version}}}{A}{
\SetExamValue{examtitle}{version=B}
}
\tlIfEqT{\expWhole{\UseExamValue{examtitle}{version}}}{C}{
\SetExamValue{examtitle}{version=D}
}
- }{}
+ }
\UseExamTemplate{examtitle}{default}
}
@@ -360,7 +462,7 @@
{}
{\UseExamValue{gradetable}{total}}
\rdxm@gobble@one
- \ifbool{exam@evaluator}{
+ \IfExamBoolT{evaluator}{
\rdxm@table@make@row
\l@rdxm@gradetable@evaluator@tl
{\textbf{\UseExamTranslation{gradetable-Evaluator}}
@@ -368,13 +470,13 @@
{}
{\UseExamValue{gradetable}{total}}
\rdxm@gobble@one
- }{}
+ }
\noindent
\begin{tabularx}{\linewidth}{|c|*{\UseExamValue{gradetable}{total}}{Y|}Y|}
\hline
\l@rdxm@gradetable@part@tl \\ \hline
\l@rdxm@gradetable@score@tl \\ \hline
- \ifbool{exam@evaluator}{\l@rdxm@gradetable@evaluator@tl \\ \hline}{}
+ \IfExamBoolT{evaluator}{\l@rdxm@gradetable@evaluator@tl \\ \hline}
\end{tabularx}
}
\SelectExamTemplate{gradetable}{normal}
@@ -391,56 +493,115 @@
%% Setting header and footer
%% ---------------------------------------------------------------------------
-\newcommand{\rdxm@columnbox}[1]{\makebox[\columnwidth]{#1}}
-\newcommand{\rdxm@headleft}{\UseExamValue{examtitle}{name}}
-\newcommand{\rdxm@headright}{
- \ifbool{exam@answer}{
+\DeclareExamTemplate{headleft}{empty}{}
+\DeclareExamTemplate{headcenter}{empty}{}
+\DeclareExamTemplate{headright}{empty}{}
+\DeclareExamTemplate{footleft}{empty}{}
+\DeclareExamTemplate{footcenter}{empty}{}
+\DeclareExamTemplate{footright}{empty}{}
+
+\DeclareExamTemplate{headleft}{plain}{}
+\DeclareExamTemplate{headcenter}{plain}{}
+\DeclareExamTemplate{headright}{plain}{}
+\DeclareExamTemplate{footleft}{plain}{}
+\DeclareExamTemplate{footcenter}{plain}{\thepage}
+\DeclareExamTemplate{footright}{plain}{}
+
+\DeclareExamTemplate{headleft}{fancy}{
+ \UseExamValue{examtitle}{name}
+}
+\DeclareExamTemplate{headcenter}{fancy}{}
+\DeclareExamTemplate{headright}{fancy}{
+ \IfExamBoolTF{answer}{
\UseExamTranslation{headfoot-Solutions}
}{
\UseExamTranslation{headfoot-Name}:\hspace{12em}
}
}
-\newcommand{\rdxm@headtext}{\rdxm@headleft\hfill\rdxm@headright}
-\newcommand{\rdxm@footleft}{\UseExamValue{examtitle}{date}}
-\newcommand{\rdxm@footcenter}{
+\DeclareExamTemplate{footleft}{fancy}{
+ \UseExamValue{examtitle}{date}
+}
+\DeclareExamTemplate{footcenter}{fancy}{
\MakeExamNameNumber{\UseExamTranslation{headfoot-Page}}{\thepage}
\space
\MakeExamNameNumber{\UseExamTranslation{headfoot-of}}{\zpageref{LastPage}}
}
-\newcommand{\rdxm@footright}{
+\DeclareExamTemplate{footright}{fancy}{
\MakeExamNameNumber{\UseExamTranslation{headfoot-Version}}
{\UseExamValue{examtitle}{version}}
}
-\newcommand{\rdxm@foottext}{\rdxm@footleft\hfill\rdxm@footcenter\hfill\rdxm@footright}
-% fancy page style
-\fancyhf{} % clear head and foot
-\ifbool{exam@twoinone}{
- \renewcommand{\headrulewidth}{0pt}
- \lhead{\small\underline{\rdxm@columnbox{\rdxm@headtext}\strut}}
- \rhead{\small\underline{\rdxm@columnbox{\rdxm@headtext}\strut}}
- \lfoot{\small\rdxm@columnbox{\rdxm@foottext}}
- \rfoot{\small\rdxm@columnbox{\stepcounter{page}\rdxm@foottext}}
+\tlSet\l@rdxm@headtext@tl{
+ \UseExamTemplate{headleft}{default}
+ \hfill
+ \UseExamTemplate{headcenter}{default}
+ \hfill
+ \UseExamTemplate{headright}{default}
+}
+
+\tlSet\l@rdxm@foottext@tl{
+ \UseExamTemplate{footleft}{default}
+ \hfill
+ \UseExamTemplate{footcenter}{default}
+ \hfill
+ \UseExamTemplate{footright}{default}
+}
+
+\newrobustcmd\rdxm@columnbox[1]{\makebox[\columnwidth]{#1}}
+
+\newrobustcmd\rdxm@other@pages@only[1]{\ifnumgreater{\value{page}}{1}{#1}{}}
+\newrobustcmd\rdxm@fancyhead[2][]{\fancyhead[#1]{\rdxm@other@pages@only{#2}}}
+\newrobustcmd\rdxm@fancyfoot[2][]{\fancyfoot[#1]{\rdxm@other@pages@only{#2}}}
+
+\IfExamBoolTF{twoinone}{
+ \rdxm@fancyhead[L]{\small\underline{\rdxm@columnbox{\l@rdxm@headtext@tl}\strut}}
+ \fancyhead[C]{}
+ \fancyhead[R]{\small\underline{\rdxm@columnbox{\l@rdxm@headtext@tl}\strut}}
+ \fancyfoot[L]{\small\rdxm@columnbox{\l@rdxm@foottext@tl}}
+ \fancyfoot[C]{}
+ \fancyfoot[R]{\small\rdxm@columnbox{\stepcounter{page}\l@rdxm@foottext@tl}}
}{
- \lhead{\small\rdxm@headleft}
- \rhead{\small\rdxm@headright}
- \cfoot{\small\rdxm@foottext}
+ \rdxm@fancyhead[L]{\small\UseExamTemplate{headleft}{default}}
+ \rdxm@fancyhead[C]{\small\UseExamTemplate{headcenter}{default}}
+ \rdxm@fancyhead[R]{\small\UseExamTemplate{headright}{default}}
+ \fancyfoot[L]{\small\UseExamTemplate{footleft}{default}}
+ \fancyfoot[C]{\small\UseExamTemplate{footcenter}{default}}
+ \fancyfoot[R]{\small\UseExamTemplate{footright}{default}}
}
-% plain page style
+%% plain page style
\fancypagestyle{plain}{
- \renewcommand{\headrulewidth}{0pt}
- \fancyhf{}
- \ifbool{exam@twoinone}{
- \rhead{\small\underline{\rdxm@columnbox{\rdxm@headtext\strut}}}
- \lfoot{\small\rdxm@columnbox{\rdxm@foottext}}
- \rfoot{\small\rdxm@columnbox{\stepcounter{page}\rdxm@foottext}}
+ \renewcommand\headrulewidth{0pt}
+ \fancyhead{}
+ \SelectExamTemplate{footleft}{plain}
+ \SelectExamTemplate{footcenter}{plain}
+ \SelectExamTemplate{footright}{plain}
+}
+
+%% fancy page style
+\tlSet\l@rdxm@fancy@page@code@tl{
+ \SelectExamTemplate{headleft}{fancy}
+ \SelectExamTemplate{headcenter}{fancy}
+ \SelectExamTemplate{headright}{fancy}
+ \SelectExamTemplate{footleft}{fancy}
+ \SelectExamTemplate{footcenter}{fancy}
+ \SelectExamTemplate{footright}{fancy}
+}
+\fancypagestyle{fancy}{
+ \IfExamBoolTF{twoinone}{
+ \renewcommand\headrulewidth{0pt}
}{
- \cfoot{\small\rdxm@foottext}
+ \renewcommand\headrulewidth{0.4pt}
}
+ \l@rdxm@fancy@page@code@tl
+}
+\fancypagestyle{fancyfirst}{
+ \renewcommand\headrulewidth{0pt}
+ \l@rdxm@fancy@page@code@tl
}
-\ifbool{exam@plain}{\pagestyle{plain}}{\pagestyle{fancy}}
+%% set page style at this time since users may change header/footer templates
+\AtBeginDocument{\IfExamBoolTF{plain}{\pagestyle{plain}}{\pagestyle{fancy}}}
%% ---------------------------------------------------------------------------
%% Class option for shuffling questions: random
@@ -454,7 +615,7 @@
seed .initial:n = 19061116
}
-\ifbool{exam@random}{
+\IfExamBoolT{random}{
\RequirePackage{pgf}
\RequirePackage{pgffor}
\newcommand*\exam@set@seed{
@@ -465,7 +626,7 @@
\pgfmathsetseed{\rdxm@random@seed}
\pgfmathrandominteger\rdxm@random@seed{1}{2147483647}
}
-}{}
+}
%% ---------------------------------------------------------------------------
%% Command for exam groups: \exampart
@@ -481,7 +642,7 @@
\SetExamValue{exampart}{number=\Roman}
%% No displaying question number when there is only one question in the part
-\newbool{exam@onlyonequestion}\boolfalse{exam@onlyonequestion}
+\NewExamBool{onlyonequestion}\SetExamBoolFalse{onlyonequestion}
\xdef\allquestions{}
\xdef\lastquestion{}
@@ -564,12 +725,12 @@
}
\newcommand{\printquestions}{
- \ifbool{exam@random}{
+ \IfExamBoolT{random}{
\rdxm@appto@questions
\rdxm@shuffle@questions
\setcounter{question}{0}
\allquestions
- }{}
+ }
\xdef\allquestions{}
\xdef\lastquestion{}
}
@@ -582,11 +743,13 @@
}
:~\UseExamValue{exampart}{type}
}
- \space(\UseExamValue{exampart}{points})
+ \IfExamValueEmptyF{exampart}{points}{
+ \space(\UseExamValue{exampart}{points})
+ }
}
\SelectExamTemplate{exampart}{normal}
-\newcommand{\exampart}[2]{
+\NewDocumentCommand\exampart{+m+O{}}{
\printquestions
\setcounter{totalquestions}{\value{totalquestions}+\value{question}}
\setcounter{question}{0}
@@ -598,9 +761,9 @@
\endgroup
\par\nopagebreak
\if\relax\detokenize{#1}\relax % #1 is empty
- \booltrue{exam@onlyonequestion}
+ \SetExamBoolTrue{onlyonequestion}
\else
- \boolfalse{exam@onlyonequestion}
+ \SetExamBoolFalse{onlyonequestion}
\vspace{1em}
\fi
% \@afterheading sets \@nobreaktrue, which will prevent page breaks before lists;
@@ -649,8 +812,8 @@
}
\DeclareExamTemplate{questionbegin}{normal}{
- \ifbool{exam@resetnumber}{
- \ifbool{exam@onlyonequestion}{
+ \IfExamBoolTF{resetnumber}{
+ \IfExamBoolTF{onlyonequestion}{
\renewcommand{\hangtext}{\qquad}
}{
\renewcommand{\hangtext}{\textbf{\textsf{\textcolor{question~number}{\arabic{question}}.}}\;\,}
@@ -702,7 +865,7 @@
\let \oldmedskip = \medskip
\let \oldbigskip = \bigskip
-\ifbool{exam@random}{
+\IfExamBoolTF{random}{
\newcommand\rdxm@appto@questions{
\xappto\allquestions{\expandonce\lastquestion}
}
@@ -740,7 +903,7 @@
}
\newcommand{\rdxm@stop@random}{
- \ifbool{exam@random}{
+ \IfExamBoolT{random}{
\renewenvironment{question}{\questionreal}{\endquestionreal}
\renewenvironment{solution}{\solutionreal}{\endsolutionreal}
\let \newpage = \oldnewpage
@@ -748,13 +911,13 @@
\let \smallskip = \oldsmallskip
\let \medskip = \oldmedskip
\let \bigskip = \oldbigskip
- }{}
+ }
}
\def\CommentCutFile{\jobname.cut}
\AtBeginDocument{
- \ifbool{exam@answer}{}{\excludecomment{solution}}
+ \IfExamBoolF{answer}{\excludecomment{solution}}
}
%% ---------------------------------------------------------------------------
@@ -848,26 +1011,32 @@
%% Command for multiple-choice questions: \pickin and \pickout
%% ---------------------------------------------------------------------------
-\newcommand{\answer}[1]{\ifbool{exam@answer}{#1}{\phantom{#1}}}
-
-\newcommand*{\cdotfill}{\leavevmode\xleaders\hbox to 0.5em{\hss$\cdot$\hss}\hfill\kern0pt\relax}
+\newcommand{\answer}[1]{\IfExamBoolTF{answer}{#1}{\phantom{#1}}}
\newcommand*{\tick@box}[1]{[\makebox[1.5em]{\color{blue}\answer{#1}}]}
\newcommand*{\tick@text@t}{$\checkmark$}
\newcommand*{\tick@text@f}{{\large$\times$}}
\newcommand*{\tick@text@T}{\sffamily T}
\newcommand*{\tick@text@F}{\sffamily F}
-\newcommand*{\tickin}[1]{\tick@box{\csname tick@text@#1\endcsname}}
-\newcommand*{\tickout}[1]{\unskip\nobreak\cdotfill\tick@box{\csname tick@text@#1\endcsname}}
-\newcommand*{\ulinefill}[1]{\xleaders\hbox{\underline{\vphantom{#1}\kern1pt}}\hfill\kern0pt}
+\NewDocumentCommand\tickin{m}{
+ \tick@box{\csname tick@text@#1\endcsname}
+}
+\NewDocumentCommand\tickout{m}{
+ \unskip\nobreak\ExamFillCdot\tick@box{\csname tick@text@#1\endcsname}
+}
+
\newcommand*{\minwidthbox}[2]{\makebox[{\ifdim#1<\width\width\else#1\fi}]{#2}}
-\newcommand*{\fillout}[1]{\allowbreak\hbox{}\nobreak\ulinefill{#1}\underline{\color{blue}\answer{#1}}\ulinefill{#1}}
-\newcommand*{\fillin}[1]{\underline{\hspace{1em}\color{blue}\minwidthbox{2em}{\answer{#1}}\hspace{1em}}}
+\NewDocumentCommand\fillout{m}{
+ \allowbreak\hbox{}\nobreak\ExamFillUlineText{\color{blue}\answer{#1}}
+}
+\NewDocumentCommand\fillin{m}{
+ \underline{\hspace{1em}\color{blue}\minwidthbox{2em}{\answer{#1}}\hspace{1em}}
+}
\newcommand*\pickoutreal[1]{
- \unskip\nobreak\cdotfill(\makebox[1.5em]{\color{blue}\answer{#1}})
+ \unskip\nobreak\ExamFillCdot(\makebox[1.5em]{\color{blue}\answer{#1}})
}
\newcommand*\pickinreal[1]{
\unskip\nobreak
@@ -889,7 +1058,7 @@
\newcommand\rdxm@shuffle@abcd[1]{\csuse{rdxm@shuffle@\@rdxm@choice@random @#1}}
\newcommand*\pickout[1]{
- \ifbool{exam@random}{
+ \IfExamBoolTF{random}{
\exam@set@seed
\pgfmathrandominteger\@rdxm@choice@random{1}{3}
%\@rdxm@choice@random
@@ -900,10 +1069,10 @@
}
\newcommand*\pickoutfixed[1]{
\pickoutreal{#1}
- \boolfalse{exam@random}
+ \SetExamBoolFalse{random}
}
\newcommand*\pickin[1]{
- \ifbool{exam@random}{
+ \IfExamBoolTF{random}{
\exam@set@seed
\pgfmathrandominteger\@rdxm@choice@random{1}{3}
%\@rdxm@choice@random
@@ -914,7 +1083,7 @@
}
\newcommand*\pickinfixed[1]{
\pickinreal{#1}
- \boolfalse{exam@random}
+ \SetExamBoolFalse{random}
}
%% ---------------------------------------------------------------------------
@@ -1003,24 +1172,24 @@
\fi
}
-\ifbool{exam@random}{
+\IfExamBoolT{random}{
\csdef{rdxm@swap@items@1}#1#2#3#4{\item#3\item#4\item#1\item#2}
\csdef{rdxm@swap@items@2}#1#2#3#4{\item#2\item#1\item#4\item#3}
\csdef{rdxm@swap@items@3}#1#2#3#4{\item#4\item#3\item#2\item#1}
\long\def\rdxm@swap@items#1\item#2\item#3\item#4\item#5\@rdxm@stop@mark{
#1\csuse{rdxm@swap@items@\@rdxm@choice@random}{#2}{#3}{#4}{#5}
}
-}{}
+}
\NewDocumentEnvironment{abcd}{+b}{
- \ifbool{exam@random}{
+ \IfExamBoolTF{random}{
\begin{abcdreal}\rdxm@swap@items#1\@rdxm@stop@mark\end{abcdreal}
}{
\begin{abcdreal}#1\end{abcdreal}
}
}{}
\NewDocumentEnvironment{abcd*}{+b}{
- \ifbool{exam@random}{
+ \IfExamBoolTF{random}{
\begin{abcd*real}\rdxm@swap@items#1\@rdxm@stop@mark\end{abcd*real}
}{
\begin{abcd*real}#1\end{abcd*real}
@@ -1041,7 +1210,7 @@
%% ---------------------------------------------------------------------------
\AtBeginDocument{
- \ifbool{exam@freealign}{\RequirePackage{freealign}}{}
+ \IfExamBoolT{freealign}{\RequirePackage{freealign}}
}
%% ---------------------------------------------------------------------------
@@ -1075,7 +1244,7 @@
%% ---------------------------------------------------------------------------
\AtBeginDocument{
- \ifbool{exam@medmath}{\RequirePackage{medmath}}{}
+ \IfExamBoolT{medmath}{\RequirePackage{medmath}}
}
%% ---------------------------------------------------------------------------
@@ -1089,27 +1258,6 @@
\setlength{\belowdisplayshortskip}{2pt}
}
-\setlength\arraycolsep{4pt}
-
-\newrobustcmd\rdxm@moremath@diagbox{
- \RequirePackage{diagbox}
- %% Fix problem in using \diagbox in array environment
- \newrobustcmd{\diagboxtwo}[3][]{
- \ifbool{mmode}{
- \hbox{\let\tabcolsep=\arraycolsep\diagbox[##1]{$##2$}{$##3$}}
- }{
- \diagbox[##1]{##2}{##3}
- }
- }
- \newrobustcmd{\diagboxthree}[4][]{
- \ifbool{mmode}{
- \hbox{\let\tabcolsep=\arraycolsep\diagbox[##1]{$##2$}{$##3$}{$##4$}}
- }{
- \diagbox[##1]{##2}{##3}{##4}
- }
- }
-}
-
\newrobustcmd\rdxm@moremath@limits{
\AtBeginDocument{
\let\rdxm@saved@lim=\lim \def\lim{\rdxm@saved@lim\limits}
@@ -1245,8 +1393,7 @@
\def\T{\mathrm{T}\kern-.5pt}
}
-\ifbool{exam@moremath}{
- \rdxm@moremath@diagbox
+\IfExamBoolT{moremath}{
\rdxm@moremath@limits
\rdxm@moremath@differential
\rdxm@moremath@widebar
@@ -1254,7 +1401,7 @@
\rdxm@moremath@widefrac
\rdxm@moremath@whitearrow
\rdxm@moremath@miscellaneous
-}{}
+}
%% ---------------------------------------------------------------------------
%% Load local user config file
@@ -1266,23 +1413,17 @@
%% Support for Chinese Language
%% ---------------------------------------------------------------------------
+\IfExamLanguageEqT{chinese}{\SetExamBoolTrue{ctex}}
+
\newrobustcmd\rdxm@chinese@ctex{
%% 四号 小四号 五号 小五号
%% 14bp 12bp 10.5bp 9bp
%% 实际上,在旧版本 ctex 中只能用 cs4size 和 c5size 选项
%% 而新版本 ctex 中,可以利用 zihao 选项指定各种中文字号
\PassOptionsToPackage{CJKnumber}{xeCJK}
- \RequirePackage[cs4size,UTF8,noindent,heading]{ctex}
- \ifbool{exam@plain}{\pagestyle{plain}}{\pagestyle{fancy}}
+ \RequirePackage[cs4size,UTF8,noindent]{ctex}
%% 在旧版本 xeCJK 中,必须用 CJKnumber 选项载入 CJKnumb 包,后面才载入会报错
%% 但在新版本 xeCJK 中 CJKnumber 选项已经被废弃,需要在后面自行载入它
- %% 在 xeCJK 中已经禁止载入 CJK,但是在新版本 ctex 宏包中却失效了
- %% 我们假装 CJK 已经载入,再载入 CJKnumb,避免出现 \CJKglue 重复定义的问题
- %% 注意用 PDFLaTeX 编译时需要用到 CJK,所以只在未定义时才作修改
- \ifdefined\CJKglue
- \@namedef{ver@CJK.sty}{}
- %\@namedef{opt@CJK.sty}{}
- \fi
\RequirePackage{CJKnumb}
%% 新版本 xeCJK 已经废弃并禁用 CJKfntef,改用 xeCJKfntef 取代,我们需要载入后者
%% 注意要保证能在较旧的 TeX 系统中编译,我们只能用 \ifXeTeX 而不能用 \ifxetex
@@ -1299,7 +1440,7 @@
\xeCJKsetcharclass{"2460}{"24FF}{1} % 带圈数字字母,括号数字字母,带点数字等
}{}
}
-\ifbool{exam@ctex}{\rdxm@chinese@ctex}{}
+\IfExamBoolT{ctex}{\rdxm@chinese@ctex}
\newrobustcmd\rdxm@chinese@sourcehan{
\setCJKmainfont[BoldFont=Source~Han~Sans~SC]{Source~Han~Serif~SC}
@@ -1309,11 +1450,11 @@
%\setCJKsansfont{思源黑体}
}
\AtBeginDocument{
- \ifbool{exam@sourcehan}{
+ \IfExamBoolT{sourcehan}{
\ifbool{XeTeX}{\rdxm@chinese@sourcehan}{
\ifbool{LuaTeX}{\rdxm@chinese@sourcehan}{}
}
- }{}
+ }
}
%% 这里不能用 \ifbool,因为涉及到 catcode 的改变
@@ -1348,7 +1489,7 @@
,question-Question = 题
,solution-Solution = 解
}
-\ifbool{exam@ctex}{\SelectExamTranslation{chinese}}{}
+\IfExamBoolT{ctex}{\SelectExamTranslation{chinese}}
%% ---------------------------------------------------------------------------
%% Stop ignoring spaces in the code
diff --git a/macros/latex/contrib/randexam/randexam.pdf b/macros/latex/contrib/randexam/randexam.pdf
index 307234cc1c..68c0e5925d 100644
--- a/macros/latex/contrib/randexam/randexam.pdf
+++ b/macros/latex/contrib/randexam/randexam.pdf
Binary files differ
diff --git a/macros/latex/contrib/randexam/randexam.tex b/macros/latex/contrib/randexam/randexam.tex
index 382375dc11..74e57318df 100644
--- a/macros/latex/contrib/randexam/randexam.tex
+++ b/macros/latex/contrib/randexam/randexam.tex
@@ -3,7 +3,7 @@
\documentclass[12pt,plain,math=most]{randexam}
\geometry{b5paper,margin=2cm}
-\newcommand*{\myversion}{2024D}
+\newcommand*{\myversion}{2024E}
\newcommand*{\mydate}{\the\year-\mylpad\month-\mylpad\day}
\newcommand*{\mylpad}[1]{\ifnum#1<10 0\the#1\else\the#1\fi}
@@ -30,8 +30,6 @@
\usepackage{tabularx}
\usepackage{booktabs}
-\newcommand{\fillbox}[1]{\ulinefill{#1}\underline{#1}\ulinefill{#1}}
-
\usepackage{fancyvrb}
\DefineVerbatimEnvironment{code}{Verbatim}{%
@@ -56,10 +54,10 @@
\noindent\Large
\begin{tabularx}{\linewidth}{|X|}
\hline
- Title: \fillbox{\color{blue3}The randexam class for LaTeX}\\
- Author: \fillbox{Jianrui Lyu (tolvjr@163.com)}\\
- Version: \fillbox{\myversion{} (\mydate)}\\
- Code: \fillbox{\url{https://github.com/lvjr/randexam}}\\
+ Title: \ExamFillUlineText{\color{blue3}The randexam class for LaTeX}\\
+ Author: \ExamFillUlineText{Jianrui Lyu (tolvjr@163.com)}\\
+ Version: \ExamFillUlineText{\myversion{} (\mydate)}\\
+ Code: \ExamFillUlineText{\url{https://github.com/lvjr/randexam}}\\
\hline
\end{tabularx}%
}
@@ -110,11 +108,11 @@ multiple \mycmd{\exampart}, and an optional \mycmd{\examdata} commands:
\begin{code}
\examtitle{name=Math Final Exam,date=2018-06-28,version=A}
......
-\exampart{Fill in the blanks.}{3 points for each.}
+\exampart{Fill in the blanks.}[3 points for each.]
......
-\exampart{Select one answer.}{3 points for each.}
+\exampart{Select one answer.}[3 points for each.]
......
-\exampart{Work out math calculations.}{8 points for each.}
+\exampart{Work out math calculations.}[8 points for each.]
......
\examdata{Some data may be used in the exam}
......
@@ -138,11 +136,11 @@ will be modified from \myval{A} to \myval{B}.
The questions in an exam could be separated into several parts:
\begin{code}
-\exampart{Fill in the blanks.}{3 points for each.}
+\exampart{Fill in the blanks.}[3 points for each.]
......
-\exampart{Select one answer.}{3 points for each.}
+\exampart{Select one answer.}[3 points for each.]
......
-\exampart{Work out math calculations.}{8 points for each.}
+\exampart{Work out math calculations.}[8 points for each.]
......
\end{code}
@@ -163,7 +161,7 @@ or the exam variants will be incorrect.
\subsection{True-or-false questions}
\begin{code}
-\exampart{True-or-false questions}{3 points for each.}
+\exampart{True-or-false questions}[3 points for each.]
\begin{question}
The first true-or-false question. \tickout{T}
@@ -192,7 +190,7 @@ so as to make \mypkg{randexam} hide them in generating blank exam papers.
\subsection{Fill-in-the-blank questions}
\begin{code}
-\exampart{Fill in the blanks.}{3 points for each.}
+\exampart{Fill in the blanks.}[3 points for each.]
\begin{question}
The first fill-in-the-blank question \fillout{answer}.
@@ -220,7 +218,7 @@ so as to make \mypkg{randexam} hide them in generating blank exam papers.
\subsection{Multiple-choice questions}
\begin{code}
-\exampart{Select one answer.}{3 points for each.}
+\exampart{Select one answer.}[3 points for each.]
\begin{question}
The first multiple-choice questions \pickout{A}.
@@ -278,7 +276,7 @@ according to the lengths of the choices.
For subjective questions, you could put answers inside \myenv{solution} environment.
\begin{code}
-\exampart{Work out math calculations.}{8 points for each.}
+\exampart{Work out math calculations.}[8 points for each.]
\begin{question}
The first math calculation question.
@@ -318,7 +316,7 @@ Answer to the second question.
You can write other types of questions. For example:
\begin{code}
-\exampart{Some question type}{4 points for each.}
+\exampart{Some question type}[4 points for each.]
\begin{question}
First question text. \answer{Answer text.}
@@ -522,7 +520,8 @@ All options provided by \mypkg{randexam} class are listed in the following table
\myopt{math=most} & $\Leftrightarrow$ \myopt{mathdesign,freealign,medmath} \\
\myopt{math=all} & $\Leftrightarrow$ \myopt{mathdesign,freealign,medmath,moremath} \\
\midrule
- \myopt{chinese} & select Chinese language and load \mypkg{ctex} package \\
+ \myopt{language} & set language and use corresponding translations \\
+ %\myopt{chinese} & select Chinese language and load \mypkg{ctex} package \\
\bottomrule
\end{tabularx}
@@ -651,6 +650,27 @@ After this, you could load current translation of some keywords with \mycmd{\Use
This command is useful in defining new templates for the exam (see Subsection \ref{subsect:template}).
+\subsection{Checking current language}
+
+There are commands \mycmd{\IfExamLanguageEqT},
+\mycmd{\IfExamLanguageEqF}, and \mycmd{\IfExamLanguageEqTF},
+with which you can execute code based on current language.
+
+\subsection{Checking boolean flags}
+
+There are several commands for creating, setting, or checking boolean flags:
+
+\begin{tabularx}{\linewidth}{@{}lX@{}}
+\toprule
+ \mycmd{\NewExamBool} & create a new boolean flag \\
+ \mycmd{\SetExamBoolTrue} & set the boolean flag to true \\
+ \mycmd{\SetExamBoolFalse} & set the boolean flag to false \\
+ \mycmd{\IfExamBoolT} & run code if the boolean flag is true \\
+ \mycmd{\IfExamBoolF} & run code if the boolean flag is false \\
+ \mycmd{\IfExamBoolTF} & run true-state code or false-state code \\
+\bottomrule
+\end{tabularx}
+
\subsection{Saving and reading key values}
With \mycmd{\SetExamValue} and \mycmd{\UseExamValue} you could save and read
@@ -667,9 +687,14 @@ the value of a key, respectively.
\hrule
\vspace{0.5em}
-The \mypkg{randexam} class also provides commands \mycmd{\IfExamValueExistT},
-\mycmd{\IfExamValueExistF}, and \mycmd{\IfExamValueExistTF},
-with which you can do conditional typesetting.
+The class also provides commands for conditional typesetting.
+
+\begin{tabularx}{\linewidth}{@{}XXX@{}}
+\toprule
+\mycmd{\IfExamValueExistT} & \mycmd{\IfExamValueExistF} & \mycmd{\IfExamValueExistTF} \\
+\mycmd{\IfExamValueEmptyT} & \mycmd{\IfExamValueEmptyF} & \mycmd{\IfExamValueEmptyTF} \\
+\bottomrule
+\end{tabularx}
\begin{code}
\IfExamValueExistTF{somemodule}{somekey}{True}{False}
@@ -763,4 +788,77 @@ are listed in the following table:
\end{tabularx}\par
\endgroup
+\subsection{Filling space with contents}
+
+In defining exam templates, we may need the following filling commands.
+
+\begin{tabularx}{\linewidth}{@{}lX@{}}
+\toprule
+ \mycmd{\ExamFillCdot} & fill space with centered dots \\
+ \mycmd{\ExamFillUline} & fill space with an underline \\
+ \mycmd{\ExamFillUlineText} & fill space with underlined text \\
+ \mycmd{\ExamFillUlinePhantom} & fill space with underlined phantom text \\
+\bottomrule
+\end{tabularx}
+
+\begin{code}
+Hello\ExamFillCdot World\par
+Hello\ExamFillUline World\par
+Hello\ExamFillUlineText{Text}World\par
+Hello\ExamFillUlinePhantom{\Huge Text}World\par
+\end{code}
+
+Hello\ExamFillCdot World\par
+Hello\ExamFillUline World\par
+Hello\ExamFillUlineText{Text}World\par
+Hello\ExamFillUlinePhantom{\Huge Text}World\par
+
+\subsection{Headers and Footers}
+
+To customize headers and footers of the exam paper,
+we could modify the following \myval{fancy} templates.
+
+\begin{code}
+\DeclareExamTemplate{headleft}{fancy}{
+ \UseExamValue{examtitle}{name}
+}
+\DeclareExamTemplate{headcenter}{fancy}{}
+\DeclareExamTemplate{headright}{fancy}{
+ \IfExamBoolTF{answer}{
+ \UseExamTranslation{headfoot-Solutions}
+ }{
+ \UseExamTranslation{headfoot-Name}:\hspace{12em}
+ }
+}
+\DeclareExamTemplate{footleft}{fancy}{
+ \UseExamValue{examtitle}{date}
+}
+\DeclareExamTemplate{footcenter}{fancy}{
+ \UseExamTranslation{headfoot-Page} \thepage\space
+ \UseExamTranslation{headfoot-of} \zpageref{LastPage}
+}
+\DeclareExamTemplate{footright}{fancy}{
+ \UseExamTranslation{headfoot-Version}
+ \UseExamValue{examtitle}{version}
+}
+\end{code}
+
+Actually, \mypkg{randexam} class uses \mypkg{fancyhdr} package
+to customize headers and footers.
+
+\subsection{Themes of exam papers}
+
+With \mycmd{\DeclareExamTheme} command you can collect some templates into a theme,
+which could be activated later with \mycmd{\SelectExamTheme} command.
+
+\begin{code}
+\DeclareExamTheme{mytheme}{
+ \SelectExamTemplate{examtitle}{mytheme}
+ \SelectExamTemplate{exampart}{mytheme}
+ \SelectExamTemplate{examdata}{mytheme}
+}
+......
+\SelectExamTheme{mytheme}
+\end{code}
+
\end{document}
diff --git a/macros/latex/contrib/sjtutex/README.md b/macros/latex/contrib/sjtutex/README.md
new file mode 100644
index 0000000000..7935863283
--- /dev/null
+++ b/macros/latex/contrib/sjtutex/README.md
@@ -0,0 +1,31 @@
+# SJTUTeX
+
+## 简介
+
+SJTUTeX 旨在建立一个简单易用的上海交通大学文档类集,包括学位论文文档类 `sjtuthesis`,以及普通文档类 `sjtuarticle` 和 `sjtureport`。
+
+在使用该文档类集之前,请仔细阅读文档 `sjtutex.pdf`。
+
+本项目也是 [SJTUThesis](https://github.com/sjtug/SJTUThesis) 项目使用的文档类集,如果遇到使用问题,请前往 [Discussions](https://github.com/sjtug/SJTUThesis/discussions) 提问或提交 [Issues](https://github.com/sjtug/SJTUThesis/issues);如果对文档类有改进建议,也欢迎提交 [Pull Requests](https://github.com/sjtug/SJTUTeX/pulls)。
+
+## 软件许可证
+
+[交大视觉形象系统](https://vi.sjtu.edu.cn)的相关图像资源版权归上海交通大学所有。其他部分使用 [LaTeX Project Public License](http://www.latex-project.org/lppl.txt) 授权。
+
+---
+
+# SJTUTeX
+
+## Description
+
+SJTUTeX aims to establish a simple and easy-to-use collection of document classes for Shanghai Jiao Tong University, including the thesis document class `sjtuthesis`, as well as the regular document classes `sjtuarticle` and `sjtureport`.
+
+Before using this collection of document classes, please read the document `sjtutex.pdf` carefully.
+
+This project is also used by the [SJTUThesis](https://github.com/sjtug/SJTUThesis) project. If you encounter any usage problems, please go to [Discussions](https://github.com/sjtug/SJTUThesis/discussions) to ask questions or open [Issues](https://github.com/sjtug/SJTUThesis/issues); if you have any suggestions for improving the document class, you could also submit [Pull Requests](https://github.com/sjtug/SJTUTeX/pulls).
+
+## License
+
+This work may be distributed and/or modified under the
+conditions of the [LaTeX Project Public License](http://www.latex-project.org/lppl.txt), either version 1.3
+of this license or (at your option) any later version.
diff --git a/macros/latex/contrib/sjtutex/sjtu-vi-badge-red.pdf b/macros/latex/contrib/sjtutex/sjtu-vi-badge-red.pdf
new file mode 100644
index 0000000000..7b34ecf219
--- /dev/null
+++ b/macros/latex/contrib/sjtutex/sjtu-vi-badge-red.pdf
Binary files differ
diff --git a/macros/latex/contrib/sjtutex/sjtu-vi-badge-small-red.pdf b/macros/latex/contrib/sjtutex/sjtu-vi-badge-small-red.pdf
new file mode 100644
index 0000000000..53901f695b
--- /dev/null
+++ b/macros/latex/contrib/sjtutex/sjtu-vi-badge-small-red.pdf
Binary files differ
diff --git a/macros/latex/contrib/sjtutex/sjtu-vi-logo-red.pdf b/macros/latex/contrib/sjtutex/sjtu-vi-logo-red.pdf
new file mode 100644
index 0000000000..08a405be04
--- /dev/null
+++ b/macros/latex/contrib/sjtutex/sjtu-vi-logo-red.pdf
Binary files differ
diff --git a/macros/latex/contrib/sjtutex/sjtu-vi-logo-small-red.pdf b/macros/latex/contrib/sjtutex/sjtu-vi-logo-small-red.pdf
new file mode 100644
index 0000000000..a1ec93ed9c
--- /dev/null
+++ b/macros/latex/contrib/sjtutex/sjtu-vi-logo-small-red.pdf
Binary files differ
diff --git a/macros/latex/contrib/sjtutex/sjtu-vi-name-red.pdf b/macros/latex/contrib/sjtutex/sjtu-vi-name-red.pdf
new file mode 100644
index 0000000000..26a249e41b
--- /dev/null
+++ b/macros/latex/contrib/sjtutex/sjtu-vi-name-red.pdf
Binary files differ
diff --git a/macros/latex/contrib/sjtutex/sjtutex.dtx b/macros/latex/contrib/sjtutex/sjtutex.dtx
new file mode 100644
index 0000000000..4e340a821f
--- /dev/null
+++ b/macros/latex/contrib/sjtutex/sjtutex.dtx
@@ -0,0 +1,6137 @@
+% \iffalse meta-comment
+%
+% Copyright (C) SJTUG
+% 2018--2024 Weijian Wu <alexarawu@outlook.com>
+% 2022--2024 Zilong Li <logcreative@outlook.com>
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either
+% version 1.3c of this license or (at your option) any later
+% version. The latest version of this license is in:
+%
+% http://www.latex-project.org/lppl.txt
+%
+% and version 1.3 or later is part of all distributions of
+% LaTeX version 2005/12/01 or later.
+%
+%<*internal>
+\iffalse
+%</internal>
+%
+%<*internal>
+\fi
+\begingroup
+ \def\NameOfLaTeXe{LaTeX2e}
+\expandafter\endgroup\ifx\NameOfLaTeXe\fmtname\else
+\csname fi\endcsname
+%</internal>
+%
+%<*install>
+\input ctxdocstrip.tex
+\keepsilent
+\askforoverwritefalse
+
+\preamble
+
+ Copyright (C) SJTUG
+ 2018--2024 Weijian Wu <alexarawu@outlook.com>
+ 2022--2024 Zilong Li <logcreative@outlook.com>
+
+ This work may be distributed and/or modified under the
+ conditions of the LaTeX Project Public License, either
+ version 1.3c of this license or (at your option) any later
+ version. The latest version of this license is in:
+
+ http://www.latex-project.org/lppl.txt
+
+ and version 1.3 or later is part of all distributions of
+ LaTeX version 2005/12/01 or later.
+
+\endpreamble
+
+\generate{
+ \usedir{tex/latex/sjtutex}
+ \file{sjtuthesis.cls} {\from{\jobname.dtx}{class,thesis}}
+ \file{sjtureport.cls} {\from{\jobname.dtx}{class,report}}
+ \file{sjtuarticle.cls} {\from{\jobname.dtx}{class,article}}
+ \file{sjtu-lang-thesis-zh.def} {\from{\jobname.dtx}{lang,thesis,zh}}
+ \file{sjtu-lang-thesis-en.def} {\from{\jobname.dtx}{lang,thesis,en}}
+ \file{sjtu-lang-thesis-de.def} {\from{\jobname.dtx}{lang,thesis,de}}
+ \file{sjtu-lang-thesis-ja.def} {\from{\jobname.dtx}{lang,thesis,ja}}
+ \file{sjtu-lang-generic-zh.def} {\from{\jobname.dtx}{lang,generic,zh}}
+ \file{sjtu-lang-generic-en.def} {\from{\jobname.dtx}{lang,generic,en}}
+ \file{sjtu-lang-generic-de.def} {\from{\jobname.dtx}{lang,generic,de}}
+ \file{sjtu-lang-generic-ja.def} {\from{\jobname.dtx}{lang,generic,ja}}
+ \file{sjtu-name-thesis-zh.def} {\from{\jobname.dtx}{name,thesis,zh}}
+ \file{sjtu-name-thesis-en.def} {\from{\jobname.dtx}{name,thesis,en}}
+ \file{sjtu-name-thesis-de.def} {\from{\jobname.dtx}{name,thesis,de}}
+ \file{sjtu-name-thesis-ja.def} {\from{\jobname.dtx}{name,thesis,ja}}
+ \file{sjtu-name-generic-zh.def} {\from{\jobname.dtx}{name,generic,zh}}
+ \file{sjtu-name-generic-en.def} {\from{\jobname.dtx}{name,generic,en}}
+ \file{sjtu-name-generic-de.def} {\from{\jobname.dtx}{name,generic,de}}
+ \file{sjtu-name-generic-ja.def} {\from{\jobname.dtx}{name,generic,ja}}
+ \file{sjtu-scheme-zh.def} {\from{\jobname.dtx}{scheme,zh}}
+ \file{sjtu-scheme-en.def} {\from{\jobname.dtx}{scheme,en}}
+ \file{sjtu-scheme-de.def} {\from{\jobname.dtx}{scheme,de}}
+ \file{sjtu-scheme-ja.def} {\from{\jobname.dtx}{scheme,ja}}
+ \file{sjtu-text-font-newtx.def} {\from{\jobname.dtx}{font,text,newtx}}
+ \file{sjtu-text-font-newpx.def} {\from{\jobname.dtx}{font,text,newpx}}
+ \file{sjtu-text-font-lm.def} {\from{\jobname.dtx}{font,text,lm}}
+ \file{sjtu-text-font-libertinus.def}{\from{\jobname.dtx}{font,text,libertinus}}
+ \file{sjtu-text-font-stixtwo.def} {\from{\jobname.dtx}{font,text,stixtwo}}
+ \file{sjtu-text-font-xits.def} {\from{\jobname.dtx}{font,text,xits}}
+ \file{sjtu-text-font-newcm.def} {\from{\jobname.dtx}{font,text,newcm}}
+ \file{sjtu-text-font-cambria.def} {\from{\jobname.dtx}{font,text,cambria}}
+ \file{sjtu-text-font-times.def} {\from{\jobname.dtx}{font,text,times}}
+ \file{sjtu-math-font-newtx.def} {\from{\jobname.dtx}{font,math,newtx}}
+ \file{sjtu-math-font-newpx.def} {\from{\jobname.dtx}{font,math,newpx}}
+ \file{sjtu-math-font-lm.def} {\from{\jobname.dtx}{font,math,lm}}
+ \file{sjtu-math-font-libertinus.def}{\from{\jobname.dtx}{font,math,libertinus}}
+ \file{sjtu-math-font-stixtwo.def} {\from{\jobname.dtx}{font,math,stixtwo}}
+ \file{sjtu-math-font-xits.def} {\from{\jobname.dtx}{font,math,xits}}
+ \file{sjtu-math-font-newcm.def} {\from{\jobname.dtx}{font,math,newcm}}
+ \file{sjtu-math-font-cambria.def} {\from{\jobname.dtx}{font,math,cambria}}
+ \file{sjtu-math-font-times.def} {\from{\jobname.dtx}{font,math,times}}
+ \file{sjtu-cjk-font-windows.def} {\from{\jobname.dtx}{font,cjk,windows,und}}
+ \file{sjtu-cjk-font-windows-zh.def} {\from{\jobname.dtx}{font,cjk,windows,zh}}
+ \file{sjtu-cjk-font-windows-ja.def} {\from{\jobname.dtx}{font,cjk,windows,ja}}
+ \file{sjtu-cjk-font-mac.def} {\from{\jobname.dtx}{font,cjk,mac,und}}
+ \file{sjtu-cjk-font-mac-zh.def} {\from{\jobname.dtx}{font,cjk,mac,zh}}
+ \file{sjtu-cjk-font-mac-ja.def} {\from{\jobname.dtx}{font,cjk,mac,ja}}
+ \file{sjtu-cjk-font-ubuntu.def} {\from{\jobname.dtx}{font,cjk,ubuntu,und}}
+ \file{sjtu-cjk-font-ubuntu-zh.def} {\from{\jobname.dtx}{font,cjk,ubuntu,zh}}
+ \file{sjtu-cjk-font-ubuntu-ja.def} {\from{\jobname.dtx}{font,cjk,ubuntu,ja}}
+ \file{sjtu-cjk-font-adobe.def} {\from{\jobname.dtx}{font,cjk,adobe,und}}
+ \file{sjtu-cjk-font-adobe-zh.def} {\from{\jobname.dtx}{font,cjk,adobe,zh}}
+ \file{sjtu-cjk-font-adobe-ja.def} {\from{\jobname.dtx}{font,cjk,adobe,ja}}
+ \file{sjtu-cjk-font-fandol.def} {\from{\jobname.dtx}{font,cjk,fandol,und}}
+ \file{sjtu-cjk-font-fandol-zh.def} {\from{\jobname.dtx}{font,cjk,fandol,zh}}
+ \file{sjtu-cjk-font-fandol-ja.def} {\from{\jobname.dtx}{font,cjk,fandol,ja}}
+ \file{sjtu-cjk-font-founder.def} {\from{\jobname.dtx}{font,cjk,founder,und}}
+ \file{sjtu-cjk-font-founder-zh.def} {\from{\jobname.dtx}{font,cjk,founder,zh}}
+ \file{sjtu-cjk-font-founder-ja.def} {\from{\jobname.dtx}{font,cjk,founder,ja}}
+%</install>
+%<*internal>
+ \usedir{source/latex/sjtutex}
+ \file{\jobname.ins} {\from{\jobname.dtx}{install}}
+%</internal>
+%<*install>
+}
+
+\obeyspaces
+\Msg{*************************************************************}
+\Msg{* *}
+\Msg{* To finish the installation you have to move the following *}
+\Msg{* files into a directory searched by TeX: *}
+\Msg{* *}
+\Msg{* The recommended directory is TDS:tex/latex/sjtutex *}
+\Msg{* *}
+\Msg{* sjtuthesis.cls *}
+\Msg{* sjtureport.cls *}
+\Msg{* sjtuarticle.cls *}
+\Msg{* sjtu-lang-generic-de.def *}
+\Msg{* sjtu-lang-generic-en.def *}
+\Msg{* sjtu-lang-generic-ja.def *}
+\Msg{* sjtu-lang-generic-zh.def *}
+\Msg{* sjtu-lang-thesis-de.def *}
+\Msg{* sjtu-lang-thesis-en.def *}
+\Msg{* sjtu-lang-thesis-ja.def *}
+\Msg{* sjtu-lang-thesis-zh.def *}
+\Msg{* sjtu-name-generic-de.def *}
+\Msg{* sjtu-name-generic-en.def *}
+\Msg{* sjtu-name-generic-ja.def *}
+\Msg{* sjtu-name-generic-zh.def *}
+\Msg{* sjtu-name-thesis-de.def *}
+\Msg{* sjtu-name-thesis-en.def *}
+\Msg{* sjtu-name-thesis-ja.def *}
+\Msg{* sjtu-name-thesis-zh.def *}
+\Msg{* sjtu-scheme-de.def *}
+\Msg{* sjtu-scheme-en.def *}
+\Msg{* sjtu-scheme-ja.def *}
+\Msg{* sjtu-scheme-zh.def *}
+\Msg{* sjtu-text-font-cambria.def *}
+\Msg{* sjtu-text-font-libertinus.def *}
+\Msg{* sjtu-text-font-lm.def *}
+\Msg{* sjtu-text-font-newcm.def *}
+\Msg{* sjtu-text-font-newpx.def *}
+\Msg{* sjtu-text-font-newtx.def *}
+\Msg{* sjtu-text-font-stixtwo.def *}
+\Msg{* sjtu-text-font-times.def *}
+\Msg{* sjtu-text-font-xits.def *}
+\Msg{* sjtu-math-font-cambria.def *}
+\Msg{* sjtu-math-font-libertinus.def *}
+\Msg{* sjtu-math-font-lm.def *}
+\Msg{* sjtu-math-font-newcm.def *}
+\Msg{* sjtu-math-font-newpx.def *}
+\Msg{* sjtu-math-font-newtx.def *}
+\Msg{* sjtu-math-font-stixtwo.def *}
+\Msg{* sjtu-math-font-times.def *}
+\Msg{* sjtu-math-font-xits.def *}
+\Msg{* sjtu-cjk-font-adobe-ja.def *}
+\Msg{* sjtu-cjk-font-adobe-zh.def *}
+\Msg{* sjtu-cjk-font-adobe.def *}
+\Msg{* sjtu-cjk-font-fandol-ja.def *}
+\Msg{* sjtu-cjk-font-fandol-zh.def *}
+\Msg{* sjtu-cjk-font-fandol.def *}
+\Msg{* sjtu-cjk-font-founder-ja.def *}
+\Msg{* sjtu-cjk-font-founder-zh.def *}
+\Msg{* sjtu-cjk-font-founder.def *}
+\Msg{* sjtu-cjk-font-mac-ja.def *}
+\Msg{* sjtu-cjk-font-mac-zh.def *}
+\Msg{* sjtu-cjk-font-mac.def *}
+\Msg{* sjtu-cjk-font-ubuntu-ja.def *}
+\Msg{* sjtu-cjk-font-ubuntu-zh.def *}
+\Msg{* sjtu-cjk-font-ubuntu.def *}
+\Msg{* sjtu-cjk-font-windows-ja.def *}
+\Msg{* sjtu-cjk-font-windows-zh.def *}
+\Msg{* sjtu-cjk-font-windows.def *}
+\Msg{* sjtu-vi-badge-red.pdf *}
+\Msg{* sjtu-vi-badge-small-red.pdf *}
+\Msg{* sjtu-vi-logo-red.pdf *}
+\Msg{* sjtu-vi-logo-small-red.pdf *}
+\Msg{* sjtu-vi-name-red.pdf *}
+\Msg{* *}
+\Msg{* To produce the documentation, run the file sjtutex.dtx *}
+\Msg{* through XeLaTeX. *}
+\Msg{* *}
+\Msg{* Happy TeXing! *}
+\Msg{* *}
+\Msg{*************************************************************}
+
+\endbatchfile
+%</install>
+%
+%<*internal>
+\fi
+%</internal>
+%
+%<*class>
+\NeedsTeXFormat{LaTeX2e}[2020/10/01]
+\providecommand\IfFormatAtLeastTF{\@ifl@t@r\fmtversion}
+\IfFormatAtLeastTF{2020/10/01}{}
+ {\PackageError{sjtutex}
+ {Your LaTeX format is outdated!\MessageBreak\MessageBreak
+ Release `2020/10/01' or newer is required to\MessageBreak
+ compile this document.\MessageBreak\MessageBreak
+ Please update your TeX distribution}{}}
+%</class>
+%<*!(driver|install)>
+%<+!driver>\GetIdInfo$Id: sjtutex.dtx b468d42 2024-02-18 19:15:02 +0800 Alexara Wu <alexarawu@outlook.com> $
+%<class&thesis> {Thesis document class for Shanghai Jiao Tong University (SJTUTeX)}
+%<class&thesis>\ProvidesExplClass{sjtuthesis}
+%<class&report> {Report document class for Shanghai Jiao Tong University (SJTUTeX)}
+%<class&report>\ProvidesExplClass{sjtureport}
+%<class&article> {Article document class for Shanghai Jiao Tong University (SJTUTeX)}
+%<class&article>\ProvidesExplClass{sjtuarticle}
+%<lang&thesis&zh> {Chinese specific definition for thesis (SJTUTeX)}
+%<lang&thesis&zh>\ProvidesExplFile{sjtu-lang-thesis-zh.def}
+%<lang&thesis&en> {English specific definition for thesis (SJTUTeX)}
+%<lang&thesis&en>\ProvidesExplFile{sjtu-lang-thesis-en.def}
+%<lang&thesis&de> {German specific definition for thesis (SJTUTeX)}
+%<lang&thesis&de>\ProvidesExplFile{sjtu-lang-thesis-de.def}
+%<lang&thesis&ja> {Japanese specific definition for thesis (SJTUTeX)}
+%<lang&thesis&ja>\ProvidesExplFile{sjtu-lang-thesis-ja.def}
+%<lang&generic&zh> {Chinese specific definition for generic (SJTUTeX)}
+%<lang&generic&zh>\ProvidesExplFile{sjtu-lang-generic-zh.def}
+%<lang&generic&en> {English specific definition for generic (SJTUTeX)}
+%<lang&generic&en>\ProvidesExplFile{sjtu-lang-generic-en.def}
+%<lang&generic&de> {German specific definition for generic (SJTUTeX)}
+%<lang&generic&de>\ProvidesExplFile{sjtu-lang-generic-de.def}
+%<lang&generic&ja> {Japanese specific definition for generic (SJTUTeX)}
+%<lang&generic&ja>\ProvidesExplFile{sjtu-lang-generic-ja.def}
+%<name&thesis&zh> {Chinese name config for thesis (SJTUTeX)}
+%<name&thesis&zh>\ProvidesExplFile{sjtu-name-thesis-zh.def}
+%<name&thesis&en> {English name config for thesis (SJTUTeX)}
+%<name&thesis&en>\ProvidesExplFile{sjtu-name-thesis-en.def}
+%<name&thesis&de> {German name config for thesis (SJTUTeX)}
+%<name&thesis&de>\ProvidesExplFile{sjtu-name-thesis-de.def}
+%<name&thesis&ja> {Japanese name config for thesis (SJTUTeX)}
+%<name&thesis&ja>\ProvidesExplFile{sjtu-name-thesis-ja.def}
+%<name&generic&zh> {Chinese name config for generic (SJTUTeX)}
+%<name&generic&zh>\ProvidesExplFile{sjtu-name-generic-zh.def}
+%<name&generic&en> {English name config for generic (SJTUTeX)}
+%<name&generic&en>\ProvidesExplFile{sjtu-name-generic-en.def}
+%<name&generic&de> {German name config for generic (SJTUTeX)}
+%<name&generic&de>\ProvidesExplFile{sjtu-name-generic-de.def}
+%<name&generic&ja> {Japanese name config for generic (SJTUTeX)}
+%<name&generic&ja>\ProvidesExplFile{sjtu-name-generic-ja.def}
+%<scheme&zh> {Chinese scheme (SJTUTeX)}
+%<scheme&zh>\ProvidesExplFile{sjtu-scheme-zh.def}
+%<scheme&en> {English scheme (SJTUTeX)}
+%<scheme&en>\ProvidesExplFile{sjtu-scheme-en.def}
+%<scheme&de> {German scheme (SJTUTeX)}
+%<scheme&de>\ProvidesExplFile{sjtu-scheme-de.def}
+%<scheme&ja> {Japanese scheme (SJTUTeX)}
+%<scheme&ja>\ProvidesExplFile{sjtu-scheme-ja.def}
+%<font&text&newtx> {New TX text fonts definition (SJTUTeX)}
+%<font&text&newtx>\ProvidesExplFile{sjtu-text-font-newtx.def}
+%<font&text&newpx> {New PX text fonts definition (SJTUTeX)}
+%<font&text&newpx>\ProvidesExplFile{sjtu-text-font-newpx.def}
+%<font&text&stixtwo> {STIX Two text fonts definition (SJTUTeX)}
+%<font&text&stixtwo>\ProvidesExplFile{sjtu-text-font-stixtwo.def}
+%<font&text&xits> {XITS text fonts definition (SJTUTeX)}
+%<font&text&xits>\ProvidesExplFile{sjtu-text-font-xits.def}
+%<font&text&lm> {Latin Modern text fonts definition (SJTUTeX)}
+%<font&text&lm>\ProvidesExplFile{sjtu-text-font-lm.def}
+%<font&text&libertinus> {Libertinus text fonts definition (SJTUTeX)}
+%<font&text&libertinus>\ProvidesExplFile{sjtu-text-font-libertinus.def}
+%<font&text&newcm> {New Computer Modern text fonts definition (SJTUTeX)}
+%<font&text&newcm>\ProvidesExplFile{sjtu-text-font-newcm.def}
+%<font&text&cambria> {Cambria text fonts definition (SJTUTeX)}
+%<font&text&cambria>\ProvidesExplFile{sjtu-text-font-cambria.def}
+%<font&text&times> {Times text fonts definition (SJTUTeX)}
+%<font&text&times>\ProvidesExplFile{sjtu-text-font-times.def}
+%<font&math&newtx> {New TX math fonts definition (SJTUTeX)}
+%<font&math&newtx>\ProvidesExplFile{sjtu-math-font-newtx.def}
+%<font&math&newpx> {New PX math fonts definition (SJTUTeX)}
+%<font&math&newpx>\ProvidesExplFile{sjtu-math-font-newpx.def}
+%<font&math&stixtwo> {STIX Two math fonts definition (SJTUTeX)}
+%<font&math&stixtwo>\ProvidesExplFile{sjtu-math-font-stixtwo.def}
+%<font&math&xits> {XITS math fonts definition (SJTUTeX)}
+%<font&math&xits>\ProvidesExplFile{sjtu-math-font-xits.def}
+%<font&math&lm> {Latin Modern math fonts definition (SJTUTeX)}
+%<font&math&lm>\ProvidesExplFile{sjtu-math-font-lm.def}
+%<font&math&libertinus> {Libertinus math fonts definition (SJTUTeX)}
+%<font&math&libertinus>\ProvidesExplFile{sjtu-math-font-libertinus.def}
+%<font&math&newcm> {New Computer Modern math fonts definition (SJTUTeX)}
+%<font&math&newcm>\ProvidesExplFile{sjtu-math-font-newcm.def}
+%<font&math&cambria> {Cambria math fonts definition (SJTUTeX)}
+%<font&math&cambria>\ProvidesExplFile{sjtu-math-font-cambria.def}
+%<font&math&times> {Times math fonts definition (SJTUTeX)}
+%<font&math&times>\ProvidesExplFile{sjtu-math-font-times.def}
+%<font&cjk&windows&und> {Windows CJK fonts definition (SJTUTeX)}
+%<font&cjk&windows&und>\ProvidesExplFile{sjtu-cjk-font-windows.def}
+%<font&cjk&windows&zh> {Windows CJK fonts definition for Chinese (SJTUTeX)}
+%<font&cjk&windows&zh>\ProvidesExplFile{sjtu-cjk-font-windows-zh.def}
+%<font&cjk&windows&ja> {Windows CJK fonts definition for Japanese (SJTUTeX)}
+%<font&cjk&windows&ja>\ProvidesExplFile{sjtu-cjk-font-windows-ja.def}
+%<font&cjk&mac&und> {macOS CJK fonts definition (SJTUTeX)}
+%<font&cjk&mac&und>\ProvidesExplFile{sjtu-cjk-font-mac.def}
+%<font&cjk&mac&zh> {macOS CJK fonts definition for Chinese (SJTUTeX)}
+%<font&cjk&mac&zh>\ProvidesExplFile{sjtu-cjk-font-mac-zh.def}
+%<font&cjk&mac&ja> {macOS CJK fonts definition for Japanese (SJTUTeX)}
+%<font&cjk&mac&ja>\ProvidesExplFile{sjtu-cjk-font-mac-ja.def}
+%<font&cjk&ubuntu&und> {Ubuntu CJK fonts definition (SJTUTeX)}
+%<font&cjk&ubuntu&und>\ProvidesExplFile{sjtu-cjk-font-ubuntu.def}
+%<font&cjk&ubuntu&zh> {Ubuntu CJK fonts definition for Chinese (SJTUTeX)}
+%<font&cjk&ubuntu&zh>\ProvidesExplFile{sjtu-cjk-font-ubuntu-zh.def}
+%<font&cjk&ubuntu&ja> {Ubuntu CJK fonts definition for Japanese (SJTUTeX)}
+%<font&cjk&ubuntu&ja>\ProvidesExplFile{sjtu-cjk-font-ubuntu-ja.def}
+%<font&cjk&adobe&und> {Adobe CJK fonts definition (SJTUTeX)}
+%<font&cjk&adobe&und>\ProvidesExplFile{sjtu-cjk-font-adobe.def}
+%<font&cjk&adobe&zh> {Adobe CJK fonts definition for Chinese (SJTUTeX)}
+%<font&cjk&adobe&zh>\ProvidesExplFile{sjtu-cjk-font-adobe-zh.def}
+%<font&cjk&adobe&ja> {Adobe CJK fonts definition for Japanese (SJTUTeX)}
+%<font&cjk&adobe&ja>\ProvidesExplFile{sjtu-cjk-font-adobe-ja.def}
+%<font&cjk&fandol&und> {Fandol CJK fonts definition (SJTUTeX)}
+%<font&cjk&fandol&und>\ProvidesExplFile{sjtu-cjk-font-fandol.def}
+%<font&cjk&fandol&zh> {Fandol CJK fonts definition for Chinese (SJTUTeX)}
+%<font&cjk&fandol&zh>\ProvidesExplFile{sjtu-cjk-font-fandol-zh.def}
+%<font&cjk&fandol&ja> {Fandol CJK fonts definition for Japanese (SJTUTeX)}
+%<font&cjk&fandol&ja>\ProvidesExplFile{sjtu-cjk-font-fandol-ja.def}
+%<font&cjk&founder&und> {Founder CJK fonts definition (SJTUTeX)}
+%<font&cjk&founder&und>\ProvidesExplFile{sjtu-cjk-font-founder.def}
+%<font&cjk&founder&zh> {Founder CJK fonts definition for Chinese (SJTUTeX)}
+%<font&cjk&founder&zh>\ProvidesExplFile{sjtu-cjk-font-founder-zh.def}
+%<font&cjk&founder&ja> {Founder CJK fonts definition for Japanese (SJTUTeX)}
+%<font&cjk&founder&ja>\ProvidesExplFile{sjtu-cjk-font-founder-ja.def}
+%<!driver> {\ExplFileDate}{2.1}{\ExplFileDescription}
+%</!(driver|install)>
+%
+%<*driver>
+\PassOptionsToPackage{fontset=ubuntu}{ctex}
+\documentclass{ctxdoc}
+\newcommand{\sjtutex}{SJTU\TeX}
+\expandafter\def\csname ver@\jobname.dtx\endcsname
+ {2024/02/18 v2.1 SJTUTeX}
+\usepackage{float}
+\usepackage{multirow}
+\usepackage{longtable}
+\usepackage{listings}
+\AtEndOfClass{\sloppy}
+\definecolor{sjtu-red}{RGB}{200,22,30}
+\definecolor{sjtu-dark-red}{RGB}{167,32,56}
+\definecolor{sjtu-amber}{RGB}{253,208,0}
+\definecolor{sjtu-orange}{RGB}{240,131,0}
+\definecolor{sjtu-blue}{RGB}{0,134,209}
+\definecolor{sjtu-dark-blue}{RGB}{0,64,152}
+\definecolor{sjtu-green}{RGB}{51,141,39}
+\definecolor{sjtu-dark-green}{RGB}{0,81,78}
+\lstdefinestyle{style@base}{^^A
+ basewidth = 0.5 em,
+ gobble = 2,
+ lineskip = 2 pt,
+ frame = l,
+ framerule = 1.2 pt,
+ framesep = 0 pt,
+ escapeinside = {(*}{*)},
+ basicstyle = \small\ttfamily,
+ xleftmargin = 0.5 em,
+ xrightmargin = 0.5 em,
+ framexleftmargin = 0.5 em,
+ framexrightmargin = 0.5 em}
+\lstdefinestyle{style@shell}{^^A
+ style = style@base,
+ rulecolor = \color{sjtu-dark-green},
+ backgroundcolor = \color{sjtu-dark-green!2},
+ language = bash,
+ alsoletter = {-},
+ keywordstyle = \color{sjtu-green},
+ emphstyle = \color{sjtu-amber}}
+\lstdefinestyle{style@latex}{^^A
+ style = style@base,
+ rulecolor = \color{sjtu-dark-blue},
+ backgroundcolor = \color{sjtu-dark-blue!2},
+ language = [LaTeX]TeX,
+ alsoletter = {*, -},
+ keywordstyle = \color{sjtu-dark-red!80},
+ texcsstyle = *\color{sjtu-blue},
+ emphstyle = [1]\color{sjtu-orange},
+ emphstyle = [2]\color{sjtu-green},
+ emphstyle = [3]\color{sjtu-dark-blue!80}}
+\lstnewenvironment{shell}[1][]{^^A
+ \lstset{style=style@shell, #1}}{}
+\lstnewenvironment{latex}[1][]{^^A
+ \lstset{style=style@latex, #1}}{}
+\newcommand\TNA[1]{\textcolor{sjtu-blue}{\tn{#1}}}
+\newcommand\TNB[1]{\textcolor{sjtu-dark-red!80}{\tn{#1}}}
+\newcommand\OPT[1]{\textcolor{sjtu-dark-blue!80}{#1}}
+\newcommand\OPS[1]{\textcolor{sjtu-green}{#1}}
+\newcommand\ENV[1]{\textcolor{sjtu-orange}{#1}}
+\newcommand\BEV[1]{\TNA{begin}\{\ENV{#1}\}}
+\newcommand\EEV[1]{\TNA{end}\{\ENV{#1}\}}
+\newcommand\note[1]{{^^A
+ \color{sjtu-dark-green}{\noindent\bfseries 说明:}~\emph{#1}}}
+\newcommand\sjtutexrev[1]{^^A
+ \href{https://github.com/sjtug/SJTUTeX/commit/#1}{\texttt{sjtutex} rev. #1}}
+\hypersetup{^^A
+ bookmarksnumbered = true,
+ bookmarksopen = true}
+\makeatletter
+\pdfstringdefDisableCommands{^^A
+ \let\color\@gobble}
+\makeatother
+\begin{document}
+ \DocInput{\jobname.dtx}
+ \IndexLayout
+ \PrintChanges
+ \PrintIndex
+\end{document}
+%</driver>
+% \fi
+%
+% \changes{v2.0}{2021/09/10}{应用 \LaTeXiii{} 重构代码。}
+% \changes{v2.0}{2022/12/27}{新增文档类 \cls{sjtuarticle} 和 \cls{sjtureport}。}
+%
+% \GetFileId{\jobname.dtx}
+%
+% \title{\bfseries\color{sjtu-red}\sjtutex{}: 上海交通大学文档类集}
+% \author{SJTUG}
+% \date{\filedate\quad\fileversion\thanks{\sjtutexrev{\ExplFileVersion}.}}
+%
+% \hypersetup{^^A
+% pdfsubject = {上海交通大学文档类集使用说明},
+% pdfkeywords = {模板; 上海交通大学; 使用说明}}
+%
+% \maketitle
+%
+% \begin{abstract}
+% 此宏包旨在建立一个简单易用的上海交通大学文档类集,包括学位论文文档类
+% \cls{sjtuthesis} 以及普通文档类 \cls{sjtuarticle} 和 \cls{sjtureport}。
+% \end{abstract}
+%
+% \def\abstractname{免责声明}
+% \begin{abstract}
+% \noindent
+% \begin{enumerate}
+% \item 本模板的发布遵守 \href{https://www.latex-project.org/lppl/lppl-1-3c.txt}
+% {\LaTeX{} Project Public License (1.3c)},使用前请认真阅读协议内容。
+% \item 学位论文模板根据 \href{https://www.gs.sjtu.edu.cn/post/detail/Z3MxNDc=}
+% {《上海交通大学博士、硕士学位论文撰写指南》} ,并参考
+% \href{https://bysj.jwc.sjtu.edu.cn/ShowNews.aspx?newsno=Yr2wg3ibJJhIZh0A52amXw....}
+% {《上海交通大学本科生毕业设计(论文)撰写规范》}
+% 编写而成。旨在供上海交通大学准毕业生撰
+% 写学位论文使用。
+% \item 学位论文模板仅为撰写指南的参考实现,不保证审查老师不提意见。任何由于使用本模板
+% 而引起的论文格式审查问题均与本模板作者无关。
+% \item 任何个人或组织以本模板为基础进行修改、扩展而生成的新的专用模板,请严格遵
+% 守 \LaTeX{} Project Public License 协议。由于违犯协议而引起的任何纠纷
+% 争端均与本模板作者无关。
+% \end{enumerate}
+% \end{abstract}
+%
+% \tableofcontents
+%
+% \begin{documentation}
+%
+% \section{介绍}
+%
+% 最早的一版 \LaTeX{} 学位论文模板由一位热心的物理系同学制作,中文字符处理采用了当时最为流行的
+% CJK--\LaTeX{} 方案。在此基础上,weijianwen 根据交大研究生院对学位论文的要求,完成
+% 了一份基本可用的交大 \LaTeX{} 学位论文模板。由于 CJK--\LaTeX{} 方案不易使用,
+% weijianwen 与 William Wang 开始着手把模板向 \XeTeX{} 引擎移植。之后 weijianwen
+% 又断断续续做了一些完善模板的工作,在原有硕士学位论文模板的基础上完成了交大学士
+% 和博士学位论文模板。
+%
+% 2012 年 5 月模板开始在 GitHub^^A
+% \footnote{\url{https://github.com/weijianwen/SJTUThesis},项目转移后该链接已重定向。}^^A
+% 上管理和更新,2018 年 1 月项目转移至 SJTUG 名
+% 下。2019 年 6 月 Alexara Wu 重构了整个宏包的代码,并使用 Doc\TeX{} 文档和
+% \textsc{DocStrip} 工具进行代码的管理,升级版本号为 1.0。2022 年 11 月,论文模板
+% 改版后,使用 \LaTeXiii{} 重构了代码,添加 \cls{sjtureport} 和 \cls{sjtuarticle}
+% 文档类,升级版本号为 2.0。
+%
+% 现在,\sjtutex{} 代码在 GitHub^^A
+% \footnote{\url{https://github.com/sjtug/SJTUTeX}}^^A
+% 上维护。
+% 原 \href{https://github.com/sjtug/SJTUThesis}{SJTUThesis} 仓库则作为学位论文示例文档,提供开箱即用的模板。
+% 学位论文模板用户可以在 \href{https://github.com/sjtug/SJTUThesis/discussions}{Discussions}
+% 上提问使用问题,也可以在 \href{https://github.com/sjtug/SJTUThesis/issues}{Issues}
+% 中进行 Bug 反馈与新功能提案。如果需要对文档类代码进行修改,欢迎前往
+% \href{https://github.com/sjtug/SJTUTeX}{\sjtutex} 仓库进行 Pull Request。
+% \sjtutex{} 模板的许多实现细节离不开
+% \href{https://github.com/sjtug/SJTUThesis/graphs/contributors}
+% {热心同学们} 的贡献,在此感谢所有为模板贡献过代码的同学们,以及所有测试和使用
+% 模板的各位同学!
+%
+% \note{模板的作用在于减少论文写作过程中格式调整的时间,前提是遵守模板的用法,否
+% 则即便用了 \sjtutex{} 也难以保证输出的论文符合学校规范。}
+%
+% \section{简明教程}
+%
+% \subsection{安装 \TeX{} 发行版}
+%
+% 因为 \LaTeXiii{} 和相关宏包在不断更新,所以推荐使用最新的 \TeX{} 发行版。
+% \sjtutex{} 支持主流的 \TeX{} 发行版,包括 \TeX{} Live、\hologo{MiKTeX}、
+% Mac\TeX{},但不支持 \CTeX{} 套装。安装方法具体可以参考
+% \href{https://github.com/sjtug/SJTUThesis/wiki/TeX-发行版及其安装}
+% {Wiki 页面《\TeX{} 发行版及其安装》}。
+%
+% \sjtutex{} 最低支持至 2021 年发行的 \TeX{} 发行版,\pkg{ctex} 宏包版本应当在
+% v2.5 及以上。版本过低将无法正常编译。
+%
+% \subsection{文件组成}
+%
+% 表~\ref{tab:files} 列出了 \sjtutex{} 的主要文件及其功能介绍。
+%
+% \begin{table}[!hbt]
+% \centering
+% \begin{threeparttable}
+% \caption{模板的文件组成}
+% \label{tab:files}
+% \begin{tabular}{l|l|p{4cm}}
+% \toprule
+% \strong{类别} & \strong{文件} & \strong{说明} \\
+% \midrule
+% 文档类 & \file{sjtuthesis.cls} & 学位论文文档类 \\
+% & \file{sjtureport.cls} & 报告文档类 \\
+% & \file{sjtuarticle.cls} & 文稿文档类 \\
+% & \file{sjtu-name-*.def} & 文档类名称配置 \\
+% & \file{sjtu-lang-*.def} & 文档类语言配置 \\
+% & \file{sjtu-scheme-*.def} & 文档类语言方案 \\
+% \midrule
+% 字体配置文件 & \file{sjtu-text-font-*.def} & 西文字体配置 \\
+% & \file{sjtu-math-font-*.def} & 数学字体配置 \\
+% & \file{sjtu-cjk-font-*.def} & CJK 字体配置 \\
+% \midrule
+% 视觉形象系统\tnote{a} & \file{sjtu-vi-logo-*.pdf} & 校标图片 \\
+% & \file{sjtu-vi-badge-*.pdf} & 校徽图片 \\
+% & \file{sjtu-vi-name-*.pdf} & 校名图片 \\
+%
+% \bottomrule
+% \end{tabular}
+% \begin{tablenotes}
+% \item[a] \href{https://vi.sjtu.edu.cn}{交大视觉形象系统}
+% 的相关图像资源版权归上海交通大学所有。
+% \end{tablenotes}
+% \end{threeparttable}
+% \end{table}
+%
+% \subsection{使用文档类}
+%
+% 共有 3 种文档类,\cls{sjtuthesis} 用于学位论文的排版,\cls{sjtureport} 用于课程大报告的排版,
+% \cls{sjtuarticle} 用于课程小论文的排版。
+%
+% 将文档保存在下载好的 \sjtutex{} 模板根目录下,文件以 \texttt{.tex} 后缀结尾。
+% 注意在使用文档类时,需要将涉及到的所有源文件使用 UTF-8 编码保存。对于不同的文档类,使用方法
+% 略有不同,这里给出这三种文档类的最小使用示例。
+%
+% 下面这份 \TeX{} 文档展示了 \cls{sjtuthesis} 文档类的基本用法,一般需要指定中英文名称。
+% 该文档将包含中英文封面,页眉为文档主题及章节名称。
+% \begin{latex}[moretexcs={\sjtusetup,\maketitle,\tableofcontents*,\chapter},
+% morekeywords={\frontmatter,\mainmatter}, emph={[1]sjtuthesis,document},
+% emph={[2]info},emph={[3]type,zh,en,title,author}]
+% \documentclass[type=master]{sjtuthesis}
+% \sjtusetup{
+% info = {
+% zh/title = {上海交通大学学位论文模板示例文档},
+% en/title = {A Sample Document for SJTU Thesis Template},
+% zh/author = {某某},
+% en/author = {Mo Mo},
+% }
+% }
+% \begin{document}
+% \maketitle
+% \frontmatter
+% \tableofcontents*
+% \mainmatter
+% \chapter{欢迎}
+% \section{欢迎使用 SJTUThesis}
+% 你好,\LaTeX{}!
+% \end{document}
+% \end{latex}
+%
+% 下面这份 \TeX{} 文档展示了 \cls{sjtureport} 文档类的基本用法,建议使用标准命令定义中文名称。
+% 该文档将包含标题页,页眉为校标图片、文档主题及章节名称。
+% \begin{latex}[moretexcs={\subject,\keywords,\maketitle,\chapter},
+% emph={[1]sjtureport,document}]
+% \documentclass{sjtureport}
+% \title{上海交通大学报告模板示例文档}
+% \author{某某}
+% \subject{XX期末课程论文}
+% \keywords{上海交大, 饮水思源, 爱国荣校}
+% \begin{document}
+% \maketitle
+% \chapter{欢迎}
+% \section{欢迎使用 SJTUReport}
+% 你好,\LaTeX{}!
+% \end{document}
+% \end{latex}
+%
+% 下面这份 \TeX{} 文档展示了 \cls{sjtuarticle} 文档类的基本用法,建议使用标准命令定义中文名称,
+% 不能够使用 \tn{chapter} 这一级。该文档包含标题栏,页眉为校标图片、文档主题及章节名称。
+% \begin{latex}[moretexcs={\maketitle}, emph={[1]sjtuarticle,document}]
+% \documentclass{sjtuarticle}
+% \title{示例文档}
+% \author{某某}
+% \begin{document}
+% \maketitle
+% \section{欢迎使用 SJTUArticle}
+% 你好,\LaTeX{}!
+% \end{document}
+% \end{latex}
+%
+% \subsection{编译文档}
+%
+% 文档类推荐使用 \XeLaTeX{} 或 \LuaLaTeX{} 编译,同时也支持 \pdfTeX{} 引擎。为了
+% 生成正确的目录、脚注以及交叉引用,至少需要连续编译两次。
+%
+% 在实际使用中,一般推荐使用自动生成工具 \pkg{latexmk} 编译文档。\pkg{latexmk}
+% 命令可以自动进行多步编译,直到交叉引用都被解决。
+% 假设您的 \TeX{} 源文件名为 \file{main.tex},
+% 可在命令行中执行如下命令使用 \XeLaTeX{} 编译文档
+% \begin{shell}[morekeywords={latexmk},emph={-xelatex}]
+% latexmk -xelatex main
+% \end{shell}
+% 也可通过修改 \file{latexmkrc} 配置文件来控制 \pkg{latexmk} 的行为,
+% 具体可以参考 \pkg{latexmk} 文档。
+%
+% \section{文档配置}
+%
+% 本模板中的选项、命令或环境可以分为以下三类:
+% \begin{itemize}
+% \item 名字后面带有 \rexptarget\rexpstar{} 的,表示只能在 \cls{sjtuthesis} 文档类中使用;
+% \item 名字后面带有 \exptarget\expstar{} 的,表示只能在 \cls{sjtureport} 和 \cls{sjtuarticle} 文档类中使用;
+% \item 名字后面不带有特殊符号的,一般表示在 \cls{sjtuthesis}、\cls{sjtureport} 和 \cls{sjtuarticle} 文档类中都可以使用,特殊情况另作说明。
+% \end{itemize}
+%
+% \subsection{文档类选项}
+%
+% 本节所指“文档类选项”是指需要在引入文档类的时候指定的选项:
+%
+% \begin{latex}[emph={[1]sjtuthesis}]
+% \documentclass(*\oarg{文档类选项}*){sjtuthesis}
+% \end{latex}
+%
+% 部分选项采用 \meta{key}|=|\meta{value} 的形式,需要使用逗号分隔各选项。
+% 当 \meta{value} 省略时,将采用默认值。在下文的说明中,将用\textbf{粗体}表示默认值。
+%
+% \subsubsection{通用选项}
+%
+% \begin{function}[rEXP,updated=2022-12-03]{type}
+% \begin{syntax}
+% \OPT{type} = <bachelor|(master)|doctor>
+% \end{syntax}
+% 论文类型。三种选项分别代表学士学位论文、硕士学位论文、博士学位论文。
+% \end{function}
+%
+% \begin{function}[updated=2023-03-23]{lang}
+% \begin{syntax}
+% \OPT{lang} = <(zh)|en|de|ja>
+% \end{syntax}
+% 论文主要语言。可选中文、英文、德文或日文,该选项会改变文档中的一些标题的名字。
+% 下文中 \meta{lang} 可以指定为这些选项中的其中之一。
+% \end{function}
+%
+% \begin{function}{draft, final}
+% 是否开启草稿模式。
+% \opt{draft} 开启草稿模式,所有的图片将不会被加载,超过边界的区域将会被涂上黑色色块。
+% \opt{final} 关闭草稿模式。
+% 默认为 \opt{final}。
+% \end{function}
+%
+% \begin{function}[rEXP]{review}
+% 盲审模式。开启盲审模式将隐去作者姓名、导师姓名、班级、学号等个人信息,
+% 删去版权使用授权书、原创性声明和致谢页。默认关闭。
+% \end{function}
+%
+% \subsubsection{页面设置}
+%
+% \begin{function}{oneside, twoside}
+% 指明论文的单双面模式。
+% \opt{oneside} 为单面模式,
+% \opt{twoside} 为双面模式。
+% \begin{itemize}
+% \item 在 \cls{sjtuthesis} 文档类中,默认为 \opt{twoside}。
+% \item 在 \cls{sjtureport} 和 \cls{sjtuarticle} 文档类中,默认为 \opt{oneside}。
+% \end{itemize}
+% \end{function}
+%
+% \begin{function}{openright, openany}
+% 指明论文是否奇数页开章。
+% \opt{openright} 为从奇数页开始新章,
+% \opt{openany} 为从任意页开始新章。
+% \begin{itemize}
+% \item 在 \cls{sjtuthesis} 文档类中,默认为 \opt{openright}。
+% \item 在 \cls{sjtureport} 文档类中,默认为 \opt{openany}。
+% \item 在 \cls{sjtuarticle} 文档类中,该选项不可用。
+% \end{itemize}
+% \end{function}
+%
+% \begin{function}[EXP,added=2022-12-23]{titlepage, notitlepage}
+% 指明论文的标题形式。
+% \opt{titlepage} 为使用标题页。
+% \opt{notitlepage} 为使用标题块。
+% \begin{itemize}
+% \item 在 \cls{sjtuthesis} 文档类中,该选项不可用,只能使用标题页。
+% \item 在 \cls{sjtureport} 文档类中,默认为 \opt{titlepage}。
+% \item 在 \cls{sjtuarticle} 文档类中,默认为 \opt{notitlepage}。
+% \end{itemize}
+% \end{function}
+%
+% \subsubsection{字体选项}
+% \label{sec:fontsetup}
+%
+% \begin{function}[updated=2022-12-18]{zihao}
+% \begin{syntax}
+% \OPT{zihao} = <(-4)|5>
+% \end{syntax}
+% 论文默认字号,可以设定为小四号或五号。
+% \begin{itemize}
+% \item 在 \cls{sjtuthesis} 和 \cls{sjtureport} 文档类中默认为小四号;
+% \item 在 \cls{sjtuarticle} 文档类中默认为五号。
+% \end{itemize}
+% \end{function}
+%
+% \begin{function}[added=2023-10-24]{linespread}
+% \begin{syntax}
+% \OPT{linespread} = <数值>
+% \end{syntax}
+% 设置行距倍数。
+% \begin{itemize}
+% \item 在 \cls{sjtuthesis} 文档类中默认不调整行距倍数;
+% \item 在 \cls{sjtuarticle} 和 \cls{sjtureport} 文档类中默认为 1.3。
+% \end{itemize}
+% \end{function}
+%
+% \begin{function}[added=2023-10-24]{baselineskip}
+% \begin{syntax}
+% \OPT{baselineskip} = <长度|false>
+% \end{syntax}
+% 正文基线间距。
+% \begin{itemize}
+% \item 在 \cls{sjtuthesis} 文档类中,默认为 20 磅。
+% \item 在 \cls{sjtureport} 和 \cls{sjtuarticle} 文档类中,默认为 \opt{false};
+% 此时正文基线间距为字号的 1.2 倍。
+% \end{itemize}
+% \end{function}
+%
+% \begin{function}{cjk-font}
+% \begin{syntax}
+% \OPT{cjk-font} = <(auto)|(fandol)|windows|mac|ubuntu|adobe|founder|none>
+% \end{syntax}
+% 指定 CJK 字体集。\sjtutex{} 预定义了一些 CJK 字体组合,
+% 具体配置见表 \ref{tab:cjkfonts}。
+% 默认情况下会根据操作系统自动配置:
+% Windows 系统默认使用 \opt{windows},
+% macOS 系统默认使用 \opt{mac},
+% Linux 系统默认使用 \opt{fandol}。
+% 找不到对应定义的 CJK 字体集时的回退选项为 \opt{fandol}。
+%
+% \textbf{仅} \opt{windows} 和 \opt{founder} 字体集支持 \pdfLaTeX{} 直接生成 PDF。
+% 其他 CJK 字体集使用 \pdfTeX{} 引擎需要先通过 \LaTeX{} 生成 DVI,
+% 然后再使用 DVIPDFM\textit{x} 转换为 PDF。
+% \end{function}
+%
+% \begin{table}[ht]
+% \centering\small
+% \setlength\leftskip{0pt plus 1 fil minus \marginparwidth}
+% \begin{threeparttable}
+% \caption{CJK 字体配置}
+% \label{tab:cjkfonts}
+% \tabcolsep=3pt
+% \begin{tabular}{ccccccc}
+% \toprule
+% & \strong{宋体} & \strong{黑体} & \strong{仿宋} & \strong{楷体} & \strong{明朝体}\tnote{c} & \strong{哥特体}\tnote{c} \\
+% \midrule
+% |fandol|\tnote{a} & Fandol 宋体 & Fandol 黑体 & Fandol 仿宋 & Fandol 楷体 & HaranoAjiMincho & HaranoAjiGothic \\
+% |windows| & (中易)宋体 & (中易)黑体 & (中易)仿宋 & (中易)楷体 & MS Mincho & MS Gothic \\
+% |mac| & (华文)宋体-简 & (华文)黑体-简 & 华文仿宋 & (华文)楷体-简 & Hiragino Mincho ProN & Hiragino Kaku Gothic ProN \\
+% |ubuntu| & Noto Serif CJK SC & Noto Sans CJK SC & --- & 文鼎 PL 简中楷 & Noto Serif CJK JP & Noto Sans CJK JP \\
+% |adobe| & Adobe 宋体 & Adobe 黑体 & Adobe 仿宋 & Adobe 楷体 & Kozuka Mincho Pr6N & Kozuka Gothic Pr6N \\
+% |founder|\tnote{b} & 方正书宋 & 方正黑体 & 方正仿宋 & 方正楷体 & IPAMincho & IPAGothic \\
+% \bottomrule
+% \end{tabular}
+% \begin{tablenotes}
+% \item[a] 发行版中自带的 Fandol 中文字库容易出现缺字的情况;
+% 我们建议 Linux 用户使用 \opt{ubuntu} 选项或自行配置合适的字体;参见
+% \href{https://github.com/sjtug/SJTUThesis/wiki/在线使用说明}
+% {Wiki 页面《在线使用说明》}。
+% \item[b] 配置 \opt{founder} 选项使用方正简繁扩展版(即 GBK 版)字体。
+% \item[c] 日文模板才需要日文明朝体与哥特体;日文字体使用 \pkg{fontspec}
+% 宏包设置,故日文模板不支持 \pdfTeX{} 引擎,请使用 \XeLaTeX{} 或
+% \LuaLaTeX{} 编译。
+% \end{tablenotes}
+% \end{threeparttable}
+% \end{table}
+%
+% \begin{function}{text-font}
+% \begin{syntax}
+% \OPT{text-font} = <(newtx)|times|stixtwo|xits|newpx|cambria|newcm|lm|libertinus|none>
+% \end{syntax}
+% 指定西文字体集。\sjtutex{} 预定义了一些西文字体组合,
+% 具体配置见表 \ref{tab:latinfonts}。
+% 找不到定义的西文字体集时的回退选项为 \opt{newtx}。
+% \end{function}
+%
+% \begin{function}{math-font}
+% \begin{syntax}
+% \OPT{math-font} = <(auto)|(newtx)|times|stixtwo|xits|newpx|cambria|newcm|lm|libertinus|none>
+% \end{syntax}
+% 指定数学字体集。\sjtutex{} 预定义了一些数学字体组合,
+% 具体配置见表 \ref{tab:latinfonts} 数学字体列。
+% 默认跟随西文字体 \opt{text-font} 的设置。
+% 找不到定义的数学字体集时的回退选项为 \opt{newtx}。
+%
+% \opt{xits},\opt{newcm},\opt{cambria} 选项仅支持 \XeLaTeX/\LuaLaTeX{} 编译。
+% \end{function}
+%
+% \begin{table}[ht]
+% \centering\small
+% \begin{threeparttable}
+% \caption{西文字体与数学字体配置}
+% \label{tab:latinfonts}
+% \begin{tabular}{ccccc}
+% \toprule
+% & \strong{正文字体} & \strong{无衬线字体} & \strong{等宽字体} & \strong{数学字体} \\
+% \midrule
+% |newtx| & TG Termes X\tnote{a} & TG Heros & TG Cursor & newtx \\
+% \multirow{2}{*}{|times|} & Times New Roman\tnote{b} & Arial & Courier New & \multirow{2}{*}{mathptmx} \\
+% & Times\tnote{c} & Helvetica & Courier & \\
+% |stixtwo| & STIX Two Text & TG Heros & TG Cursor & STIX Two Math \\
+% |xits| & XITS & TG Heros & TG Cursor & XITS Math \\
+% |newpx| & TG Pagella X & TG Heros & TG Cursor & newpx \\
+% |cambria| & Cambria & Calibri & Consolas & Cambria Math \\
+% |newcm| & New CM\tnote{d} & New CM Sans & New CM Mono & New CM Math \\
+% |lm| & LM Roman\tnote{e} & LM Sans & LM Mono & LM Math \\
+% |libertinus| & Libertinus Serif & Libertinus Sans & LM Mono & Libertinus Math \\
+% \bottomrule
+% \end{tabular}
+% \begin{tablenotes}
+% \item[a] “TG”是 TeX Gyre 的缩写。
+% \item[b] 本行中,Times New Roman、Arial 和 Courier New 是商业字体,
+% 在 Windows 和 macOS 系统上均默认安装。
+% \item[c] 使用 \pdfTeX{} 引擎时,实际使用对应字体的 Type 1 开源版本。
+% \item[d] “CM”是 Computer Modern 的缩写。
+% \item[e] “LM”是 Latin Modern 的缩写。
+% \end{tablenotes}
+% \end{threeparttable}
+% \end{table}
+%
+% \begin{function}[added=2022-12-03,updated=2023-01-05]{math-style}
+% \begin{syntax}
+% \OPT{math-style} = <(ISO)|TeX>
+% \end{syntax}
+% 数学符号样式。该选项将影响 \opt{uppercase-greek}、\opt{integral}、
+% \opt{integral-limits} 选项。
+% 默认遵循 ISO 80000-2 标准设置,即斜体的大写希腊字母、直立的积分号
+% 以及积分号上下限置于上下方。
+% 用户也可以逐项修改数学样式。
+% \end{function}
+%
+% \begin{function}[added=2023-01-05]{uppercase-greek}
+% \begin{syntax}
+% \OPT{uppercase-greek} = <slanted|upright>
+% \end{syntax}
+% 大写希腊字母的正/斜体。
+% \end{function}
+%
+% \begin{function}[added=2023-01-05]{integral}
+% \begin{syntax}
+% \OPT{integral} = <slanted|upright>
+% \end{syntax}
+% 积分号的正/斜体。
+% \end{function}
+%
+% \begin{function}[added=2023-01-05]{integral-limits}
+% \begin{syntax}
+% \OPT{integral-limits} = <true|false>
+% \end{syntax}
+% 行间公式中积分号上下限的位置,
+% \opt{true} 使得上下限在积分号上下方,
+% \opt{false} 使得上下限在积分号右侧。
+% 该选项只影响行间公式,行内公式统一居右侧,不受影响。
+% \end{function}
+%
+% \subsection{论文信息设置}
+%
+% \begin{function}{\sjtusetup}
+% \begin{syntax}
+% \TNA{sjtusetup}\marg{键值列表}
+% \end{syntax}
+% 本模板提供了一系列选项,可由您自行配置。载入文档类之后,以下
+% 所有选项均可通过统一的命令 \tn{sjtusetup} 来设置。
+% \end{function}
+%
+% \tn{sjtusetup} 的参数是一组由(英文)逗号隔开的选项列表,列表中的选项通常是
+% \meta{key}|=|\meta{value} 的形式。对于同一项,后面的设置将会覆盖前面的设置。在
+% 下文的说明中,将用\textbf{粗体}表示默认值。\tn{sjtusetup} 支持不同类型以及多种
+% 层次的选项设定。键值列表中,“|=|”左右的空格不影响设置;但需注意,参数列表中不
+% 可以出现空行。
+%
+% \begin{latex}[moretexcs={\sjtusetup}, emph={[2]info,style,name},
+% emph={[3]zh,en,title,author,float-num-sep,achv}]
+% \sjtusetup{
+% info = {
+% zh/title = {上海交通大学学位论文模板示例文档},
+% en/title = {A Sample Document for SJTU Thesis Template},
+% zh/author = {某某},
+% en/author = {Mo Mo},
+% },
+% style = {
+% float-num-sep = {-},
+% },
+% name = {
+% achv = {攻读学位期间完成的论文},
+% },
+% }
+% \end{latex}
+%
+% \subsubsection{信息域}
+%
+% \begin{function}[updated=2023-03-14]{info}
+% \begin{syntax}
+% \OPS{info} = \marg{键值列表}
+% \end{syntax}
+% 该选项包含许多子项目,用于录入论文信息。具体内容见下。
+% \begin{itemize}
+% \item 在 \cls{sjtuthesis} 文档类中,推荐使用带语言代码前缀 \meta{lang}
+% (比如 \opt{zh} 或 \opt{en})的键来设定对应语言的论文信息,见第
+% \ref{sec:sjtuthesiskey} 节;省略语言前缀不带“*”的项目表示对应的中文
+% 字段、带“*”的项目表示对应的英文字段属于老用法,仍然兼容但请及时更新
+% 至新用法。
+% \item 在 \cls{sjtureport} 和 \cls{sjtuarticle} 文档类中,不需要使用语言代
+% 码前缀。此时推荐直接使用标准接口来设定这些信息,这些标准接口不属于键
+% 值列表,应当直接写在导言区内,见第 \ref{sec:sjtureportcmd} 节。
+% \end{itemize}
+% \end{function}
+%
+% \paragraph{适用于 \cls{sjtuthesis} 文档类的键}
+% \label{sec:sjtuthesiskey}
+%
+% \begin{function}[rEXP,updated=2023-03-14]{info/<lang>/title}
+% \begin{syntax}
+% \OPT{\meta{lang}}/\OPT{title} = \marg{标题}
+% \end{syntax}
+% 标题。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2023-03-14]{info/<lang>/display-title}
+% \begin{syntax}
+% \OPT{\meta{lang}}/\OPT{display-title} = \marg{标题页标题}
+% \end{syntax}
+% 标题页中的题目。默认为跟随对应语言的标题。
+% 如果标题过长,可以尝试使用“|\\|”手动断行。
+% \end{function}
+%
+% \begin{function}[rEXP,added=2022-12-17,updated=2023-03-14]{info/<lang>/subject}
+% \begin{syntax}
+% \OPT{\meta{lang}}/\OPT{subject} = \marg{主题}
+% \end{syntax}
+% 文档主题。一般显示在中文标题页校徽下方。
+% 默认值类似于 “上海交通大学学士学位论文” 或 “A Dissertation Submitted to
+% Shanghai Jiao Tong University for the Degree of Bachelor”。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2023-03-14]{info/<lang>/keywords}
+% \begin{syntax}
+% \OPT{\meta{lang}}/\OPT{keywords} = \marg{中文关键字}
+% \end{syntax}
+% 关键字列表。各关键字之间需使用英文逗号隔开。
+% 为防止歧义,可以用分组括号“|{...}|”把各字段括起来。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2023-03-14]{info/<lang>/author}
+% \begin{syntax}
+% \OPT{\meta{lang}}/\OPT{author} = \marg{姓名}
+% \end{syntax}
+% 作者姓名。
+% \end{function}
+%
+% \begin{function}[rEXP]{info/id}
+% \begin{syntax}
+% \OPT{id} = \marg{学号}
+% \end{syntax}
+% 学号。该键不需要语言前缀。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2023-03-14]{info/<lang>/supervisor,
+% info/<lang>/assoc-supervisor,info/<lang>/co-supervisor}
+% \begin{syntax}
+% \OPT{\meta{lang}}/\OPT{supervisor} = \marg{导师姓名}
+% \OPT{\meta{lang}}/\OPT{assoc-supervisor} = \marg{副导师姓名}
+% \OPT{\meta{lang}}/\OPT{co-supervisor} = \marg{联合导师姓名}
+% \end{syntax}
+% 导师、副导师、联合导师姓名。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2023-03-14]{info/<lang>/degree}
+% \begin{syntax}
+% \OPT{\meta{lang}}/\OPT{degree} = \marg{学位名称}
+% \end{syntax}
+% 申请学位中英文名称。
+% 包括申请的学位类别和级别,如“工学硕士”、“理学博士”等。
+% 学士论文无需标注。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2023-03-14]{info/<lang>/department}
+% \begin{syntax}
+% \OPT{\meta{lang}}/\OPT{department} = \marg{院系名称}
+% \end{syntax}
+% 院系名称。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2023-03-14]{info/<lang>/major}
+% \begin{syntax}
+% \OPT{\meta{lang}}/\OPT{major} = \marg{专业名称}
+% \end{syntax}
+% 专业名称。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2023-03-14]{info/<lang>/fund}
+% \begin{syntax}
+% \OPT{\meta{lang}}/\OPT{fund} = \marg{资助基金名称}
+% \end{syntax}
+% 资助基金列表。各资助基金名称之间需使用英文逗号隔开。
+% 为防止歧义,可以用分组括号“|{...}|”把各字段括起来。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2023-02-25]{info/date}
+% \begin{syntax}
+% \OPT{date} = \marg{ISO 日期}
+% \end{syntax}
+% 日期。默认值为文档编译日期。也可以自己指定,要求使用 ISO 格式,
+% 即 |yyyy-mm-dd| 或 |yyyy-mm|,否则设定无效。该键语言前缀不是必须的。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2023-03-14]{info/<lang>/display-date}
+% \begin{syntax}
+% \OPT{\meta{lang}}/\OPT{display-date} = \marg{日期文字}
+% \end{syntax}
+% 显示日期,可以显示不同于标准日期格式的日期,日期文字将会被原样输出。
+% 设定该键时,将会覆盖 \opt{info/date} 键在对应语言下的设定。
+% \end{function}
+%
+% \paragraph{适用于 \cls{sjtureport} 和 \cls{sjtuarticle} 文档类的命令}
+% \label{sec:sjtureportcmd}
+%
+% \begin{function}[EXP,added=2022-12-17,updated=2023-03-14]{\title}
+% \begin{syntax}
+% \TNA{title}\marg{标题}
+% \end{syntax}
+% 设置标题,覆盖 \opt{info/title} 键的值。
+% \end{function}
+%
+% \begin{function}[EXP,added=2022-12-17,updated=2023-03-14]{\author}
+% \begin{syntax}
+% \TNA{author}\marg{姓名}
+% \end{syntax}
+% 设置作者姓名,覆盖 \opt{info/author} 键的值。
+% \end{function}
+%
+% \begin{function}[EXP,added=2022-12-17,updated=2023-03-14]{\date}
+% \begin{syntax}
+% \TNA{date}\marg{日期}
+% \end{syntax}
+% 设置日期,覆盖 \opt{info/display-date} 键的值。
+% 日期会被原样显示。
+% \end{function}
+%
+% \begin{function}[EXP,added=2023-03-14]{\subject}
+% \begin{syntax}
+% \TNA{subject}\marg{主题}
+% \end{syntax}
+% 文档主题。覆盖 \opt{info/subject} 键的值。
+% \end{function}
+%
+% \begin{function}[EXP,added=2023-03-14]{\keywords}
+% \begin{syntax}
+% \TNA{keywords}\marg{关键词}
+% \end{syntax}
+% 文档关键词,使用英文逗号隔开不同的关键词。覆盖 \opt{info/keywords} 键的值。
+% \end{function}
+%
+% \subsubsection{样式域}
+%
+% \begin{function}{style}
+% \begin{syntax}
+% \OPS{style} = \marg{键值列表}
+% \end{syntax}
+% 该选项包含许多子项目,用于设置论文样式。具体内容见下。
+% \end{function}
+%
+% \begin{function}[added=2024-01-10]{style/indent-first}
+% \begin{syntax}
+% \OPT{indent-first} = <(true)|false>
+% \end{syntax}
+% 章节标题后首段是否缩进。
+% \end{function}
+%
+% \begin{function}[added=2023-11-30]{style/equation-font}
+% \begin{syntax}
+% \OPT{equation-font} = \marg{字体设置}
+% \end{syntax}
+% 行间数学公式的字体设置,该选项主要用于调整行间公式的行距,
+% 不建议修改字号字形。
+% \cls{sjtuthesis} 中默认数学公式的行距为字号的 1.2 倍。
+% \end{function}
+%
+% \begin{function}[added=2022-12-03,updated=2022-12-27]{style/float-font}
+% \begin{syntax}
+% \OPT{float-font} = \marg{字体设置}
+% \end{syntax}
+% 图、表等浮动体的额外字体设置。
+% 默认为 |\zihao{5}|,五号字。
+% \end{function}
+%
+% \begin{function}[added=2022-12-20]{style/caption-font}
+% \begin{syntax}
+% \OPT{caption-font} = \marg{字体设置}
+% \end{syntax}
+% 题注字体。
+% 默认为 |\zihao{5}\bfseries|,粗体五号字。
+% \end{function}
+%
+% \begin{function}[added=2022-12-20]{style/subcaption-font}
+% \begin{syntax}
+% \OPT{subcaption-font} = \marg{字体设置}
+% \end{syntax}
+% 子图题注字体。
+% 默认为 |\zihao{5}\normalfont|,正常字重五号字。
+% \end{function}
+%
+% \begin{function}[added=2023-03-28]{style/fnmark-style}
+% \begin{syntax}
+% \OPT{fnmark-style} = <plain|circled>
+% \end{syntax}
+% 脚注数字编号样式。
+% \opt{plain} 表示使用普通数字编号;
+% \opt{circled} 表示使用带圈数字编号。
+% 在 \opt{zh} 和 \opt{ja} 语言设置中,默认为 \opt{circled};
+% 在 \opt{en} 和 \opt{de} 语言设置中,默认为 \opt{plain}。
+%
+% 使用带圈数字编号时,由于超过 50 的带圈数字没有对应的 Unicode 码位,
+% 所以每页脚注最好不要超过 50 个。
+% 带圈数字默认使用 CJK 字体。通常情况下默认字体不一定包含所有带圈数字的字符,
+% 此时可以设置 \opt{fnmark-font} 选项给带圈数字设置合适的字体。
+% \end{function}
+%
+% \begin{function}[added=2022-12-03,updated=2023-03-28]{style/fnmark-font}
+% \begin{syntax}
+% \OPT{fnmark-font} = <haranoaji|\marg{字体设置}>
+% \end{syntax}
+% 脚注编号的额外字体设置。
+% 默认为空。
+% 可以使用预设 \opt{haranoaji},支持在 Unicode 引擎中使用 HaranoAjiMincho 字体
+% 中的带圈数字。
+% \end{function}
+%
+% \begin{function}[added=2023-12-02]{style/num-sep}
+% \begin{syntax}
+% \OPT{num-sep} = \marg{分隔符}
+% \end{syntax}
+% 图、表、公式以及定理编号中的分隔符。该选项将统一设定 \opt{float-num-sep}、
+% \opt{equation-num-sep}、\opt{theorem-num-sep} 选项。
+% 用户也可以逐项修改编号分隔符。
+% 默认为 \opt{.} 句点。
+% \end{function}
+%
+% \begin{function}[updated=2023-11-29]{style/float-num-sep}
+% \begin{syntax}
+% \OPT{float-num-sep} = \marg{分隔符}
+% \end{syntax}
+% 图、表等浮动体编号中的分隔符。
+% \end{function}
+%
+% \begin{function}[updated=2023-11-29]{style/equation-num-sep}
+% \begin{syntax}
+% \OPT{equation-num-sep} = \marg{分隔符}
+% \end{syntax}
+% 公式编号中的分隔符。
+% \end{function}
+%
+% \begin{function}[added=2023-12-02]{style/theorem-num-sep}
+% \begin{syntax}
+% \OPT{theorem-num-sep} = \marg{分隔符}
+% \end{syntax}
+% 定理编号中的分隔符。
+% \end{function}
+%
+% \begin{function}[added=2022-12-20,updated=2023-03-14]{style/header-uppercase}
+% \begin{syntax}
+% \OPT{header-uppercase} = <true|(false)>
+% \end{syntax}
+% 页眉英文字母是否大写。默认为 \opt{false}。
+% \end{function}
+%
+% \begin{function}[added=2022-12-20]{style/header-font}
+% \begin{syntax}
+% \OPT{header-font} = \marg{页眉字体}
+% \end{syntax}
+% 页眉字体。
+% \begin{itemize}
+% \item 在 \cls{sjtuthesis} 文档类中,默认为 |\zihao{-5}|,小五号字。
+% \item 在 \cls{sjtureport} 和 \cls{sjtuarticle} 文档类中,默认为 |\zihao{-5}\sffamily|,小五号字黑体。
+% \end{itemize}
+% \end{function}
+%
+% \begin{function}[added=2022-12-20]{style/footer-font}
+% \begin{syntax}
+% \OPT{footer-font} = \marg{页脚字体}
+% \end{syntax}
+% 页脚字体。默认为 |\zihao{-5}|,小五号字。
+% \end{function}
+%
+% \begin{function}[added=2022-12-03]{style/page-number}
+% \begin{syntax}
+% \OPT{page-number} = \marg{页码设置}
+% \end{syntax}
+% 设置页码的显示样式,其中 |#1| 代表当前页码。
+% 默认为 |{#1}|,即仅显示页码本身。
+% \end{function}
+%
+% \begin{function}[added=2023-11-30]{style/keywords-format}
+% \begin{syntax}
+% \OPT{keywords-format} = <(plain)|hang>
+% \end{syntax}
+% 设置关键词格式。默认为 \opt{plain} 无缩进的普通段落,另可选 \opt{hang} 悬挂格式。
+% \end{function}
+%
+% \subsubsection{名称域}
+%
+% \begin{function}{name}
+% \begin{syntax}
+% \OPS{name} = \marg{键值列表}
+% \end{syntax}
+% 选项包含许多子项目,用于设置论文中一些标题的名称。部分选项只能在 \cls{sjtuthesis} 中使用。
+% 具体内容见表 \ref{tab:names}。
+% \end{function}
+%
+% \begin{function}[updated=2023-03-18]{name/contents,name/listfigure,name/listtable,
+% name/figure,name/table,name/abstract,name/index,name/appendix,name/proof,name/bib,
+% name/figure*,name/table*,name/algorithm,name/listalgorithm,
+% name/abbr,name/nom,name/ack,name/resume,name/digest,name/achv}
+% \end{function}
+%
+% \begingroup
+% \vspace{-48ex}
+% \small \tabcolsep=3pt
+% \begin{longtable}{l|p{7em}|>{\raggedright\arraybackslash}p{9em}|p{11em}|p{8em}}
+% \caption{\opt{name} 选项的默认设置} \label{tab:names} \\
+% \toprule
+% \strong{选项} & \strong{|lang = zh|} & \strong{|lang = en|} & \strong{|lang = de|} & \strong{|lang = ja|} \\
+% \midrule
+% \endfirsthead
+% \multicolumn{5}{r}{续表~\thetable} \\
+% \toprule
+% \strong{选项} & \strong{|lang = zh|} & \strong{|lang = en|} & \strong{|lang = de|} & \strong{|lang = ja|} \\
+% \midrule
+% \endhead
+% \bottomrule
+% \multicolumn{5}{r}{续下页}
+% \endfoot
+% \bottomrule
+% \endlastfoot
+% |contents| & 目录 & Contents & Inhaltsverzeichnis & 目次 \\
+% |listfigure| & 插图 & List of Figures & Abbildungsverzeichnis & 図目次 \\
+% |listtable| & 表格 & List of Tables & Tabellenverzeichnis & 表目次 \\
+% |figure| & 图 & Figure & Abbildung & 図 \\
+% |table| & 表 & Table & Tabelle & 表 \\
+% |abstract| \rexpstar & 摘要 & Abstract & Zusammenfassung & 概要 \\
+% |index| & 索引 & Index & Index & 索引 \\
+% |appendix| & 附录 & Appendix & Anhang & 付録 \\
+% |proof| & 证明 & Proof & Beweis & 证明 \\
+% |bib| & 参考文献 & Bibliography & Literaturverzeichnis & 参考文献 \\
+% \midrule
+% |figure*| & Figure & 图 & Figure & Figure \\
+% |table*| & Table & 表 & Table & Table \\
+% |algorithm| & 算法 & Algorithm & Algorithmus & アルゴリズム \\
+% |listalgorithm| & 算法 & List of Algorithms & Algorithmenverzeichnis & アルゴリズム目次 \\
+% |abbr| \rexpstar & 缩略语对照表 & Abbreviation & Abkürzungsverzeichnis & 略語表 \\
+% |nom| \rexpstar & 主要符号对照表 & Nomenclature & Symbolverzeichnis & 記号表 \\
+% |ack| \rexpstar & 致谢 & Acknowledgements & Danksagungen & 謝辞 \\
+% |resume| \rexpstar & 个人简历 & Resume & Lebenslauf & 履歴書 \\
+% |digest| \rexpstar & 大摘要 & Digest & Kurzfassung & 要約 \\
+% |achv| \rexpstar & 学术论文和科研成果目录 & List of Research Achievements & Forschungsleistungen & 研究業績書 \\
+% \end{longtable}
+% \endgroup
+%
+% \section{内容编写}
+%
+% \begin{function}{document}
+% \begin{syntax}
+% \BEV{document}
+% \ \meta{文档内容}
+% \EEV{document}
+% \end{syntax}
+% 在文档开始后进行内容编写,文档内容由 |document| 环境包裹。
+% \end{function}
+%
+% \subsection{标题页和声明页}
+%
+% \begin{function}[updated=2022-12-03]{\maketitle}
+% \begin{syntax}
+% \TNA{maketitle}
+% \end{syntax}
+% 生成标题。
+% \begin{itemize}
+% \item 在 \cls{sjtuthesis} 文档类中,生成标题页。
+% \item 在 \cls{sjtureport} 和 \cls{sjtuarticle} 文档类中,
+% \begin{itemize}
+% \item 若处于 \opt{titlepage} 文档类选项中,生成标题页。\cls{sjtureport} 文档类默认。
+% \item 若处于 \opt{notitlepage} 文档类选项中,生成标题块。\cls{sjtuarticle} 文档类默认。
+% \end{itemize}
+% \end{itemize}
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2022-12-20]{\copyrightpage}
+% \begin{syntax}
+% \TNA{copyrightpage}
+% \TNA{copyrightpage}\oarg{授权书扫描件}
+% \end{syntax}
+% 生成空白版权使用授权书。
+% 接受一个可选参数用于插入版权使用授权书扫描件,使用可选参数时需要手动加载 \pkg{pdfpages} 宏包。
+% \end{function}
+%
+% \subsection{前文部分}
+%
+% \begin{function}[rEXP]{\frontmatter}
+% \begin{syntax}
+% \TNB{frontmatter}
+% \end{syntax}
+% 声明前文部分开始。
+% \end{function}
+%
+% \begin{function}[updated=2023-11-29]{abstract}
+% \begin{syntax}
+% \BEV{abstract}\oarg{lang}
+% \ \meta{摘要}
+% \EEV{abstract}
+% \BEV{abstract}
+% \ \meta{摘要}
+% \EEV{abstract}
+% \end{syntax}
+% 摘要环境。会在结尾添加关键词。
+% \begin{itemize}
+% \item \cls{sjtuthesis} 文档类中,可以设置可选参数指定摘要的语言,
+% 默认为 \opt{zh}。
+% \item \cls{sjtuarticle} 和 \cls{sjtureport} 文档类中,不需要可选参数。
+% \end{itemize}
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2023-11-29]{abstract*}
+% \cls{sjtuthesis} 文档类中使用带星号的 \env{abstract*} 环境不会出现在目录中。
+% \end{function}
+%
+% \begin{function}{\tableofcontents,\tableofcontents*,\listoffigures,\listoffigures*,
+% \listoftables,\listoftables*,\listofalgorithms,\listofalgorithms*}
+% 目录、插图、表格和算法等索引命令如表 \ref{tab:list} 所示,将其插入到期望的
+% 位置即可。带*的命令表示对应的索引表不会出现在目录中。
+% \begin{table}[H]
+% \centering\small
+% \begin{threeparttable}
+% \caption{目录和索引表}
+% \label{tab:list}
+% \begin{tabular}{lp{4cm}lp{4cm}}
+% \toprule
+% \strong{用途} & \strong{命令} & \strong{用途} & \strong{命令} \\
+% \midrule
+% 目录 & \tn{tableofcontents} & 插图索引 & \tn{listoffigures} \\
+% & \tn{tableofcontents*} & & \tn{listoffigures*} \\
+% \midrule
+% 表格索引 & \tn{listoftables} & 算法索引\tnote{a} & \tn{listofalgorithms} \\
+% & \tn{listoftables*} & & \tn{listofalgorithms*} \\
+% \bottomrule
+% \end{tabular}
+% \begin{tablenotes}
+% \item[a] 启用 \pkg{algorithm2e} 或 \pkg{algorithm} 后有效。
+% \end{tablenotes}
+% \end{threeparttable}
+% \end{table}
+% \end{function}
+%
+% \subsection{正文部分}
+%
+% \begin{function}[rEXP]{\mainmatter}
+% \begin{syntax}
+% \TNB{mainmatter}
+% \end{syntax}
+% 声明正文部分开始。正文部分是论文的核心,您可以分章节撰写。
+% 如有需求,也可以采用多文件编译的方式。
+% \end{function}
+%
+% \begin{function}[updated=2022-12-03]{\footnote}
+% \begin{syntax}
+% \TNA{footnote}\oarg{脚注编号}\marg{脚注文字}
+% \end{syntax}
+% 插入脚注。其中脚注编号参数是可选的,一般不需要输入。
+% \end{function}
+%
+% \begin{function}{assumption,axiom,conjecture,corollary,definition,example,
+% exercise,lemma,problem,proposition,theorem}
+% \sjtutex{} 预定义了一系列数学环境。在启用 \pkg{ntheorem} 或 \pkg{amsthm}
+% 宏包后有效,环境如表 \ref{tab:theorems} 所示。
+% \begin{table}[H]
+% \centering
+% \small
+% \caption{预定义的数学环境}
+% \label{tab:theorems}
+% \begin{tabular}{*{7}{l}}
+% \toprule
+% \env{assumption} & \env{axiom} & \env{conjecture} & \env{corollary} & \env{definition} & \env{example} & \env{exercise} \\
+% 假设 & 公理 & 猜想 & 推论 & 定义 & 例 & 练习 \\
+% \midrule
+% \env{lemma} & \env{problem} & \env{proof} & \env{proposition} & \env{remark} & \env{solution} & \env{theorem} \\
+% 引理 & 问题 & 证明 & 命题 & 注 & 解 & 定理 \\
+% \bottomrule
+% \end{tabular}
+% \end{table}
+% \end{function}
+%
+% \begin{function}[added=2023-10-24]{\setbaselineskip}
+% \begin{syntax}
+% \TNA{setbaselineskip}\marg{长度}
+% \end{syntax}
+% 设置当前的基线间距,一般在字号命令之后使用。
+% \end{function}
+%
+% \begin{function}{\appendix}
+% \begin{syntax}
+% \TNA{appendix}
+% \end{syntax}
+% 附录由 \tn{appendix} 命令开启,然后像正文一样书写。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2022-03-02]{nomenclature,nomenclature*}
+% \begin{syntax}
+% \BEV{nomenclature}\oarg{标题}
+% \ \meta{符号对照表}
+% \EEV{nomenclature}
+% \end{syntax}
+% 符号对照表环境。带星号的版本不会出现在目录中。可以使用可选参数手动设置标题。
+% 符号对照表环境仅设置标题,内部实现可由用户自行决定。
+% 可以使用 \pkg{longtable},也可以使用 \pkg{nomencl} 宏包。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2022-03-02]{abbreviation,abbreviation*}
+% \begin{syntax}
+% \BEV{abbreviation}\oarg{标题}
+% \ \meta{缩略语对照表}
+% \EEV{abbreviation}
+% \end{syntax}
+% 缩略语对照表环境。带星号的版本不会出现在目录中。可以使用可选参数手动设置标题。
+% 缩略语对照表环境仅设置标题,内部实现可由用户自行决定。
+% \end{function}
+%
+% \subsection{后文部分}
+%
+% \begin{function}[rEXP]{\backmatter}
+% \begin{syntax}
+% \TNB{backmatter}
+% \end{syntax}
+% 声明后文部分开始。 后文部分包含致谢等。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2022-02-24]{acknowledgements}
+% \begin{syntax}
+% \BEV{acknowledgements}\oarg{标题}
+% \ \meta{致谢内容}
+% \EEV{acknowledgements}
+% \end{syntax}
+% 致谢环境。盲审模式下致谢将被隐去。可以使用可选参数手动设置标题。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2022-02-24]{achievements}
+% \begin{syntax}
+% \BEV{achievements}\oarg{标题}
+% \ \meta{获得的科研成果}
+% \EEV{achievements}
+% \end{syntax}
+% 科研成果环境,可以使用可选参数手动设置标题。内部请配合使用下面的附录用文献列表环境
+% \env{bibliolist} 和 \env{bibliolist*}。你可以在该环境中使用带星号的节次命令
+% 以分隔不同的类型的成果(比如学术论文、专利等);你也可以使用多个 \env{achievements}
+% 环境,配合不同的可选参数作为标题,展示不同类型的成果。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2022-03-23]{bibliolist,bibliolist*}
+% \begin{syntax}
+% \BEV{bibliolist}\marg{最长条目编号}
+% \ \TNA{item} \meta{文献条目}
+% \EEV{bibliolist}
+% \BEV{bibliolist*}\marg{最长条目编号}
+% \ \TNA{item} \meta{文献条目(隐去姓名)}
+% \EEV{bibliolist*}
+% \end{syntax}
+% 附录用文献环境,只允许在 \env{achievements} 环境中使用。
+% 需要指定最长条目的编号作为参数,比如 \opt{99};
+% 如果将该强制参数被指定为空,将不显示编号,每条以悬挂缩进做区分。
+% 环境内部使用 \tn{item} 来分隔各条目,在同一个 \env{achievements} 环境内、不同的
+% \env{bibliolist} 或 \env{bibliolist*} 环境中编号连续递增、不会间断。
+% 普通模式下显示 \env{bibliolist} 中的内容,盲审模式下显示 \env{bibliolist*} 中的内容。
+% \end{function}
+%
+% \begin{function}[rEXP,updated=2022-02-24]{resume}
+% \begin{syntax}
+% \BEV{resume}\oarg{标题}
+% \ \meta{简历内容}
+% \EEV{resume}
+% \end{syntax}
+% 简历环境。盲审模式下简历将被隐去。可以使用可选参数手动设置标题。
+% \end{function}
+%
+% \begin{function}[rEXP]{digest}
+% \begin{syntax}
+% \BEV{digest}\oarg{lang}
+% \ \meta{大摘要}
+% \EEV{digest}
+% \end{syntax}
+% 学士论文大摘要,使用可选参数设定语言,默认为 \opt{en}。
+% \end{function}
+%
+% \section{宏包依赖情况}
+%
+% 使用不同编译方式、指定不同选项,会导致宏包依赖情况有所不同。
+% 具体如下:
+% \begin{itemize}
+% \item 在任何情况下,文档类都会\emph{显式}调用以下宏包
+% (或文档类):
+% \begin{itemize}
+% \item \cls{ctexbook}、\cls{ctexrep} 和 \cls{ctexart},
+% 提供中文排版的通用框架。属于 \CTeX{} 宏集 \cite{CTeX}。
+% \item \pkg{mathtools},对 \LaTeX{} 的数学排版功能进行了全面扩展。
+% 是 \pkg{amsmath} 的扩充。
+% \item \pkg{geometry},用于调整页面尺寸。
+% \item \pkg{fancyhdr},处理页眉页脚。
+% \item \pkg{tocloft},设置目录格式。
+% \item \pkg{caption}、\cls{bicaption} 和 \cls{subcaption},用于设置题注。
+% \item \pkg{xcolor},提供彩色支持。
+% \item \pkg{graphicx},提供图形插入的接口。
+% \item \pkg{enumitem},设置列表环境格式。
+% \end{itemize}
+% \item \cls{sjtuthesis} 会调用 \pkg{xtemplate} 和 \pkg{array},用于辅助
+% 标题页等特殊页面的排版。
+% \item 部分西文与数学字体预设会调用相关的字体宏包,具体调用情况请参见对应的
+% 字体预设文件。
+% \item 部分数字字体预设会调用 \pkg{unicode-math} 处理 Unicode 编码的
+% OpenType 数学字体。在未启用 \pkg{unicode-math} 的情况下,会调用 \pkg{bm}
+% 来选择粗体数学符号。
+% \end{itemize}
+%
+% 这里只列出了本模板直接调用的宏包。这些宏包自身的调用情况,
+% 此处不再具体展开。如有需要,请参阅相关文档。
+%
+% \begin{thebibliography}{99}
+%
+% \addcontentsline{toc}{section}{\refname}
+%
+% \newcommand\urlprefix{\newline\hspace*{\fill}}
+% \let\OldUrl=\url
+% \renewcommand\url[2][]{{\small\textit{#1}~\OldUrl{#2}}}
+% \newcommand\CTANurl[2][]{{^^A
+% \small\textit{#1}~\href{https://mirror.ctan.org/#2}{\texttt{CTAN://#2}}}}
+%
+% \subsection*{图书}
+%
+% \bibitem{Knuth1986}
+% \textsc{Knuth D E}.
+% \newblock \textit{The \TeX book: Computers \& Typesetting, volume A}\allowbreak[M].
+% \newblock Boston: Addison--Wesley Publishing Company, 1986.
+% \urlprefix \CTANurl[源代码^^A
+% \footnote{此代码只可作为学习之用。未经 Knuth 本人同意,您不应当编译此文档。}:]^^A
+% {systems/knuth/dist/tex/texbook.tex}
+%
+% \bibitem{LiuHY2013}
+% 刘海洋.
+% \newblock \textit{\LaTeX{} 入门} [M].
+% \newblock 北京: 电子工业出版社, 2013
+%
+% \subsection*{标准、规范}
+%
+% \bibitem{gb-t-7713.1-2006}
+% 国务院学位委员会办公室, 全国信息与文献标准化技术委员会.
+% \newblock \textit{学位论文编写规则: GB/T 7713.1--2006}\allowbreak[S].
+% \newblock 北京: 中国标准出版社, 2007
+%
+% \bibitem{cy-t-35-2001}
+% 全国信息与文献标准化技术委员会第七分委员会, 中华人民共和国新闻出版总署.
+% \newblock \textit{科技文献的章节编号方法: CY/T 35--2001}\allowbreak[S].
+% \newblock [S.l. : s.n.], 2001.
+%
+% \bibitem{SJTUGS2023}
+% 上海交通大学研究生院.
+% \newblock \textit{上海交通大学博士、硕士学位论文撰写指南}\allowbreak[EB/OL].
+% \newblock (2023-11-03)[2023-12-04].
+% \urlprefix\url{https://www.gs.sjtu.edu.cn/post/detail/Z3MxNDc=}
+%
+% \subsection*{宏包、模版}
+%
+% \bibitem{source2e}
+% \textsc{Braams J}, \textsc{Carlisle D}, \textsc{Jeffrey A}, et~al.
+% \newblock \textit{The \LaTeXe{} Sources}\allowbreak[CP/OL].
+% \newblock (2023-11-01).
+% \urlprefix\url{https://ctan.org/pkg/latex}
+% \urlprefix\CTANurl[源代码:]{macros/latex/base/source2e.pdf}
+%
+% \bibitem{interface3}
+% \textsc{The \LaTeX{} Project}.
+% \newblock \textit{The \LaTeXiii{} Interfaces}\allowbreak[EB/OL].
+% \newblock (2023-11-09).
+% \urlprefix\url{https://ctan.org/pkg/l3kernel}
+% \urlprefix\CTANurl[文档:]{macros/latex/l3kernel/interface3.pdf}
+%
+% \bibitem{CTeX}
+% \textsc{CTEX.ORG}.
+% \newblock \textit{\CTeX{} 宏集手册}\allowbreak[EB/OL].
+% \newblock version 2.5.10,
+% \newblock (2022-07-14).
+% \urlprefix\url{https://ctan.org/pkg/ctex}
+% \urlprefix\CTANurl[文档及源代码:]{language/chinese/ctex/ctex.pdf}
+%
+% \bibitem{fduthesis}
+% 曾祥东.
+% \newblock \textit{fduthesis: 复旦大学论文模板}\allowbreak[EB/OL].
+% \newblock version 0.9a,
+% \newblock (2023-05-27).
+% \urlprefix\url{https://ctan.org/pkg/fduthesis}
+% \urlprefix\CTANurl[文档及源代码:]{macros/latex/contrib/fduthesis/fduthesis-code.pdf}
+%
+% \bibitem{thuthesis}
+% 清华大学 TUNA 协会.
+% \newblock \textit{\textsc{ThuThesis}:清华大学学位论文模板}\allowbreak[EB/OL].
+% \newblock version 7.4.0,
+% \newblock (2023-05-15).
+% \urlprefix\url{https://ctan.org/pkg/thuthesis}
+% \urlprefix\CTANurl[文档及源代码:]{macros/latex/contrib/thuthesis/thuthesis.pdf}
+%
+% \end{thebibliography}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \clearpage
+% \section{代码实现}
+%
+% \changes{v2.1}{2023/12/05}{同步 \LaTeX{} 2020/10/01,无需显式调用
+% \pkg{expl3} 和 \pkg{xparse} 宏包。}
+% 本模板使用 \LaTeXiii{} 语法编写,依赖 \pkg{expl3} 环境,
+% 并需调用 \pkg{l3packages} 中的相关宏包。
+%
+% \begin{macrocode}
+%<@@=sjtu>
+% \end{macrocode}
+%
+% \subsection{内部变量}
+%
+% \begin{variable}{\l_@@_tmp_bool,\l_@@_tmp_clist,\l_@@_tmp_dim,
+% \l_@@_tmp_skip,\l_@@_tmp_box}
+% 临时变量。
+% \begin{macrocode}
+%<*class>
+%<thesis>\bool_new:N \l_@@_tmp_bool
+%<thesis>\clist_new:N \l_@@_tmp_clist
+\dim_new:N \l_@@_tmp_dim
+\skip_new:N \l_@@_tmp_skip
+\box_new:N \l_@@_tmp_box
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_thesis_type_int}
+% 论文类型。
+% \begin{macrocode}
+%<thesis>\int_new:N \g_@@_thesis_type_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_lang_tl,\g_@@_lang_clist,
+% \c_@@_lang_de_tl,\c_@@_lang_ja_tl }
+% 论文语言。
+% \begin{macrocode}
+\tl_new:N \g_@@_lang_tl
+%<thesis>\clist_set:Nn \g_@@_lang_clist { zh, en }
+\tl_const:Nn \c_@@_lang_de_tl { de }
+\tl_const:Nn \c_@@_lang_ja_tl { ja }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+% {\g_@@_zihao_tl,\g_@@_font_size_int,\g_@@_font_size_dim,
+% \g_@@_baseline_skip_dim,\g_@@_fixed_baselineskip_bool,\g_@@_line_spread_fp}
+% 字号大小与行距。
+% \begin{macrocode}
+\tl_new:N \g_@@_zihao_tl
+\int_new:N \g_@@_font_size_int
+\dim_new:N \g_@@_font_size_dim
+\dim_new:N \g_@@_baseline_skip_dim
+\bool_new:N \g_@@_fixed_baselineskip_bool
+\fp_new:N \g_@@_line_spread_fp
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+% {\g_@@_text_font_tl,\g_@@_math_font_tl,\g_@@_cjk_font_tl}
+% 字体配置。
+% \begin{macrocode}
+\tl_new:N \g_@@_text_font_tl
+\tl_new:N \g_@@_math_font_tl
+\tl_new:N \g_@@_cjk_font_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_slanted_uppercase_greek_bool}
+% 大写希腊字母的正/斜体。
+% \begin{macrocode}
+\bool_new:N \g_@@_slanted_uppercase_greek_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_upright_integral_bool}
+% 积分号的正/斜体。
+% \begin{macrocode}
+\bool_new:N \g_@@_upright_integral_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_integral_limits_bool}
+% 积分号上下限的位置。
+% \begin{macrocode}
+\bool_new:N \g_@@_integral_limits_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_math_font_options_clist}
+% 传入数学字体宏包的选项列表。
+% \begin{macrocode}
+\clist_new:N \g_@@_math_font_options_clist
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_review_bool}
+% 盲审模式。
+% \begin{macrocode}
+%<thesis>\bool_new:N \g_@@_review_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_options_to_ctex_class_clist}
+% 保存由 \pkg{sjtutex} 传入 \pkg{ctex} 文档类的选项列表。
+% 默认 \pkg{ctex} 文档类的选项:
+% 使用 UTF8 编码,不调整基础类的版式以及不载入 \pkg{ctex} 字体预设配置。
+% \begin{macrocode}
+\clist_set:Nn \g_@@_options_to_ctex_class_clist
+ { a4paper, UTF8, scheme = plain, fontset = none }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_options_to_packages_clist}
+% 保存由传入其他宏包的选项列表。
+% \begin{macrocode}
+\clist_new:N \g_@@_options_to_packages_clist
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_twoside_bool}
+% 是否开启双页模式。
+% \begin{macrocode}
+\bool_new:N \g_@@_twoside_bool
+%<thesis>\bool_set_true:N \g_@@_twoside_bool
+%<!thesis>\bool_set_false:N \g_@@_twoside_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_openright_bool}
+% 是否在奇数页开始新章。
+% \begin{macrocode}
+%<!article>\bool_new:N \g_@@_openright_bool
+%<thesis>\bool_set_true:N \g_@@_openright_bool
+%<report>\bool_set_false:N \g_@@_openright_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_titlepage_bool}
+% 是否生成标题页。
+% \begin{macrocode}
+%<!thesis>\bool_new:N \g_@@_titlepage_bool
+%<report>\bool_set_true:N \g_@@_titlepage_bool
+%<article>\bool_set_false:N \g_@@_titlepage_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_draft_bool}
+% 是否开启草稿模式。
+% \begin{macrocode}
+\bool_new:N \g_@@_draft_bool
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[int]{\@@_deprecated_option:n,\@@_set_deprecated_option:n}
+% 对过时选项给出警告。
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_deprecated_option:n
+ { \msg_warning:nnn { sjtutex } { deprecated-option } }
+\cs_new_protected:Npn \@@_set_deprecated_option:n #1
+ {
+ \@@_deprecated_option:n { Option~ `#1'~ is~ set. }
+ \keys_set:nn { sjtu / option } {#1}
+ }
+\msg_new:nnn { sjtutex } { deprecated-option }
+ { Option~ `\l_keys_key_tl'~ is~ deprecated. \\ #1 }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{选项处理}
+%
+% 定义 |sjtu/option| 键值类。
+% \begin{macrocode}
+\keys_define:nn { sjtu / option }
+ {
+% \end{macrocode}
+%
+% \changes{v2.0}{2022/10/25}{\cls{sjtuthesis} 类型选项移除 \opt{course},
+% 不再支持课程论文。}
+% \begin{macro}{type}
+% 论文类型。
+% \begin{macrocode}
+%<*thesis>
+ type .choice: ,
+ type .value_required:n = true ,
+ type .choices:nn =
+ { bachelor, master, doctor }
+ { \int_gset_eq:NN \g_@@_thesis_type_int \l_keys_choice_int } ,
+ type .initial:n = { master } ,
+%</thesis>
+% \end{macrocode}
+% \end{macro}
+%
+% \changes{v2.0}{2023/03/19}{语言选项新增 \opt{ja},添加日文模板。}
+% \changes{v2.0}{2023/03/23}{语言选项新增 \opt{de},添加德文模板。}
+% \begin{macro}{lang}
+% 论文主要语言。
+% \begin{macrocode}
+ lang .choice: ,
+ lang .value_required:n = true ,
+ lang .choices:nn =
+ { zh, en, de, ja }
+ {
+ \tl_gset_eq:NN \g_@@_lang_tl \l_keys_choice_tl
+%<*thesis>
+ \clist_if_in:NnF \g_@@_lang_clist {#1}
+ { \clist_gput_right:Nn \g_@@_lang_clist {#1} }
+%</thesis>
+ } ,
+ lang .initial:n = { zh } ,
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{zihao}
+% 字号大小。
+% \begin{macrocode}
+ zihao .choice: ,
+ zihao .value_required:n = true ,
+ zihao / 5 .code:n =
+ {
+ \tl_gset:Nn \g_@@_zihao_tl {#1}
+ \int_gset:Nn \g_@@_font_size_int { 1 }
+ \dim_gset:Nn \g_@@_font_size_dim { 10.5 bp }
+ } ,
+ zihao / -4 .code:n =
+ {
+ \tl_gset:Nn \g_@@_zihao_tl {#1}
+ \int_gset:Nn \g_@@_font_size_int { 2 }
+ \dim_gset:Nn \g_@@_font_size_dim { 12 bp }
+ } ,
+%<!article> zihao .initial:n = { -4 } ,
+%<article> zihao .initial:n = { 5 } ,
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{linespread}
+% 行距倍数。
+% \begin{macrocode}
+ linespread .fp_gset:N = \g_@@_line_spread_fp ,
+ linespread .initial:n = { \c_nan_fp } ,
+ linespread .value_required:n = true ,
+% \end{macrocode}
+% \end{macro}
+%
+% \changes{v2.0}{2022/12/03}{添加 \opt{lineskip} 文档类选项。}
+% \changes{v2.1}{2023/10/24}{添加 \opt{baselineskip} 文档类选项,
+% 替换原 \opt{lineskip} 选项。}
+% \begin{macro}{baselineskip}
+% 正文基线间距。
+% \begin{macrocode}
+ baselineskip .choice: ,
+ baselineskip .value_required:n = true ,
+ baselineskip / false .code:n =
+ { \bool_gset_false:N \g_@@_fixed_baselineskip_bool } ,
+ baselineskip / unknown .code:n =
+ {
+ \bool_gset_true:N \g_@@_fixed_baselineskip_bool
+ \dim_gset:Nn \g_@@_baseline_skip_dim {#1}
+ } ,
+%<thesis> baselineskip .initial:n = { 20 bp } ,
+%<!thesis> baselineskip .initial:n = { false } ,
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{text-font,math-font,cjk-font}
+% 字体配置。
+% \begin{macrocode}
+ text-font .tl_gset:N = \g_@@_text_font_tl ,
+ text-font .initial:n = { newtx } ,
+ math-font .tl_gset:N = \g_@@_math_font_tl ,
+ cjk-font .tl_gset:N = \g_@@_cjk_font_tl ,
+% \end{macrocode}
+% \end{macro}
+%
+% \opt{fontset} 是过时选项。
+% \begin{macrocode}
+ fontset .code:n = { \@@_set_deprecated_option:n { cjk-font = #1 } } ,
+% \end{macrocode}
+%
+% \changes{v2.0}{2023/01/05}{添加 \opt{math-style} 文档类选项,默认值为 \opt{ISO}。}
+% \begin{macro}{math-style}
+% 数学符号样式。
+% \begin{macrocode}
+ math-style .choice: ,
+ math-style .value_required:n = true,
+ math-style / TeX .code:n =
+ {
+ \bool_gset_false:N \g_@@_slanted_uppercase_greek_bool
+ \bool_gset_false:N \g_@@_upright_integral_bool
+ \bool_gset_false:N \g_@@_integral_limits_bool
+ } ,
+ math-style / ISO .code:n =
+ {
+ \bool_gset_true:N \g_@@_slanted_uppercase_greek_bool
+ \bool_gset_true:N \g_@@_upright_integral_bool
+ \bool_gset_true:N \g_@@_integral_limits_bool
+ } ,
+ math-style .initial:n = { ISO } ,
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{uppercase-greek}
+% 大写希腊字母的正/斜体。
+% \begin{macrocode}
+ uppercase-greek .choice: ,
+ uppercase-greek .value_required:n = true ,
+ uppercase-greek / slanted .code:n =
+ { \bool_gset_true:N \g_@@_slanted_uppercase_greek_bool } ,
+ uppercase-greek / upright .code:n =
+ { \bool_gset_false:N \g_@@_slanted_uppercase_greek_bool } ,
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{integral}
+% 积分号的正/斜体。
+% \begin{macrocode}
+ integral .choice: ,
+ integral .value_required:n = true ,
+ integral / slanted .code:n =
+ { \bool_gset_false:N \g_@@_upright_integral_bool } ,
+ integral / upright .code:n =
+ { \bool_gset_true:N \g_@@_upright_integral_bool } ,
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{integral-limits}
+% 积分号上下限的位置。
+% \begin{macrocode}
+ integral-limits .choice: ,
+ integral-limits .value_required:n = true ,
+ integral-limits / false .code:n =
+ { \bool_gset_false:N \g_@@_integral_limits_bool } ,
+ integral-limits / true .code:n =
+ { \bool_gset_true:N \g_@@_integral_limits_bool } ,
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{oneside,twoside}
+% 单面或双面模式。
+% \begin{macrocode}
+ oneside .value_forbidden:n = true,
+ twoside .value_forbidden:n = true,
+ oneside .code:n =
+ { \bool_gset_false:N \g_@@_twoside_bool } ,
+ twoside .code:n =
+ { \bool_gset_true:N \g_@@_twoside_bool } ,
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{openany,openright}
+% 是否奇数页开章。
+% \begin{macrocode}
+%<*!article>
+ openany .value_forbidden:n = true,
+ openright .value_forbidden:n = true,
+ openany .code:n =
+ { \bool_gset_false:N \g_@@_openright_bool } ,
+ openright .code:n =
+ { \bool_gset_true:N \g_@@_openright_bool } ,
+%</!article>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{titlepage,notitlepage}
+% 是否生成标题页。
+% \begin{macrocode}
+%<*!thesis>
+ titlepage .value_forbidden:n = true,
+ notitlepage .value_forbidden:n = true,
+ titlepage .code:n =
+ { \bool_gset_true:N \g_@@_titlepage_bool } ,
+ notitlepage .code:n =
+ { \bool_gset_false:N \g_@@_titlepage_bool } ,
+%</!thesis>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{draft,final}
+% 是否开启草稿模式。
+% \begin{macrocode}
+ draft .value_forbidden:n = true,
+ final .value_forbidden:n = true,
+ draft .code:n =
+ { \bool_gset_true:N \g_@@_draft_bool } ,
+ final .code:n =
+ { \bool_gset_false:N \g_@@_draft_bool } ,
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{review}
+% 盲审模式。
+% \begin{macrocode}
+%<thesis> review .bool_gset:N = \g_@@_review_bool ,
+%<thesis> review .initial:n = false ,
+% \end{macrocode}
+% \end{macro}
+%
+% 处理未知选项。
+% \begin{macrocode}
+ unknown .code:n = { \msg_error:nn { sjtutex } { unknown-option } }
+ }
+\msg_new:nnn { sjtutex } { unknown-option }
+ { Class~ option~ "\l_keys_key_tl"~ is~ unknown. }
+% \end{macrocode}
+%
+% 将文档类选项传给 |sjtu/option|。
+% \begin{macrocode}
+\cs_if_exist:NTF \ProcessKeyOptions
+ { \ProcessKeyOptions [ sjtu / option ] }
+ {
+ \RequirePackage { l3keys2e }
+ \ProcessKeysOptions { sjtu / option }
+ }
+% \end{macrocode}
+% \cls{sjtureport} 和 \cls{sjtuarticle} 文档类默认使用 1.3 行距倍数。
+% \begin{macrocode}
+%<*!thesis>
+\bool_if:NF \g_@@_fixed_baselineskip_bool
+ {
+ \fp_if_nan:nT { \g_@@_line_spread_fp }
+ { \fp_set:Nn \g_@@_line_spread_fp { 1.3 } }
+ }
+%</!thesis>
+% \end{macrocode}
+%
+% 数字字体宏包选项。
+% \begin{macrocode}
+\clist_set:Nx \g_@@_math_font_options_clist
+ {
+ \bool_if:NT \g_@@_slanted_uppercase_greek_bool
+ { slantedGreek } ,
+ \bool_if:NT \g_@@_upright_integral_bool
+ { upint }
+ }
+% \end{macrocode}
+%
+% 追加全局选项。
+% \begin{macrocode}
+\clist_put_right:Nx \@classoptionslist
+ {
+ a4paper ,
+ \tl_if_eq:NNT \g_@@_lang_tl \c_@@_lang_de_tl
+ { german, ngerman } ,
+ \bool_if:NT \g_@@_integral_limits_bool
+ { intlimits } ,
+ \g_@@_math_font_options_clist
+ }
+% \end{macrocode}
+%
+% 设置传入 \pkg{ctex} 文档类的选项。
+% \begin{macrocode}
+\clist_put_right:Nx \g_@@_options_to_ctex_class_clist
+ {
+ zihao = \g_@@_zihao_tl ,
+ \fp_if_nan:nF { \g_@@_line_spread_fp }
+ { linespread = \fp_use:N \g_@@_line_spread_fp } ,
+ \bool_if:NTF \g_@@_twoside_bool
+ { twoside } { oneside } ,
+%<!article> \bool_if:NTF \g_@@_openright_bool
+%<!article> { openright } { openany } ,
+%<!thesis> \bool_if:NTF \g_@@_titlepage_bool
+%<!thesis> { titlepage } { notitlepage } ,
+ \bool_if:NTF \g_@@_draft_bool
+ { draft } { final }
+ }
+% \end{macrocode}
+%
+% \subsection{载入宏包、文档类}
+%
+% 将选项传入 \pkg{ctex} 文档类。
+% \begin{macrocode}
+\exp_args:No \PassOptionsToClass
+ { \g_@@_options_to_ctex_class_clist }
+%<thesis> { ctexbook }
+%<report> { ctexrep }
+%<article> { ctexart }
+% \end{macrocode}
+%
+% 传入各宏包选项。
+% \begin{macrocode}
+\clist_set:Nx \g_@@_options_to_packages_clist
+ {
+ { no-math } { fontspec } ,
+ { titles } { tocloft } ,
+ { list = off } { bicaption } ,
+ { warnings-off =
+ {
+ mathtools-overbracket,
+ mathtools-colon
+ }
+ } { unicode-math } ,
+ { amsmath, thmmarks } { ntheorem } ,
+%<!article> { chapter } { algorithm } ,
+%<!article> { algochapter } { algorithm2e } ,
+ {
+ \bool_if:NTF \g_@@_integral_limits_bool
+ { displaylimits } { nolimits }
+ } { cmupint }
+ }
+\clist_map_inline:Nn \g_@@_options_to_packages_clist
+ { \PassOptionsToPackage #1 }
+% \end{macrocode}
+%
+% 载入 \pkg{ctex} 文档类。
+% 在使用 \XeLaTeX{} 编译时,\pkg{ctex} 的底层将调用 \pkg{xeCJK}
+% 宏包;而在使用 \LuaLaTeX{} 编译时,则将调用 \pkg{LuaTeX-ja} 宏包。
+% 两种情况下 \pkg{ctex} 均会调用 \pkg{fontspec} 宏包。
+% \begin{macrocode}
+%<thesis>\LoadClass { ctexbook }
+%<report>\LoadClass { ctexrep }
+%<article>\LoadClass { ctexart }
+% \end{macrocode}
+%
+% 载入各宏包。
+% \begin{macrocode}
+\RequirePackage
+ {
+%<thesis> xtemplate,
+%<thesis> array,
+ mathtools,
+ geometry,
+ fancyhdr,
+ tocloft,
+ caption,
+ bicaption,
+ subcaption,
+ xcolor,
+ graphicx,
+ enumitem
+ }
+% \end{macrocode}
+%
+% \subsection{内部定义}
+%
+% \subsubsection{内部函数}
+%
+% \begin{macro}[int]{\cs_gset:cpo,\tl_const:Nv,
+% \clist_use:NV,\clist_use:cv,
+% \exp_args:NNnv,\exp_last_unbraced:ce,
+% \regex_match:neTF}
+% \LaTeX3{} 函数变体。
+% \begin{macrocode}
+\cs_generate_variant:Nn \cs_gset:Npn { cpo }
+\cs_generate_variant:Nn \tl_const:Nn { Nv }
+\cs_generate_variant:Nn \clist_use:Nn { NV, cv }
+\exp_args_generate:n { Nnv }
+\cs_generate_variant:Nn \exp_last_unbraced:Ne { ce }
+\prg_generate_conditional_variant:Nnn \regex_match:nn { ne } { T, TF }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_engine_case:nn}
+% 2 个参数依次为 \pdfTeX 和 \XeTeX/\LuaTeX。
+% \begin{macrocode}
+\cs_new:Npx \@@_engine_case:nn #1#2
+ {
+ \bool_lazy_or:nnTF
+ { \sys_if_engine_xetex_p: }
+ { \sys_if_engine_luatex_p: }
+ {#2}
+ { \sys_if_engine_pdftex:T {#1} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_engine_case:nnn}
+% 3 个参数依次为 \pdfTeX、 \XeTeX 和 \LuaTeX。
+% \begin{macrocode}
+\cs_new:Npx \@@_engine_case:nnn #1#2#3
+ {
+ \sys_if_engine_xetex:TF
+ {#2}
+ {
+ \sys_if_engine_luatex:TF
+ {#3}
+ { \sys_if_engine_pdftex:T {#1} }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_unicode_engine_case:nn}
+% 2 个参数依次为 \XeTeX 和 \LuaTeX。
+% \begin{macrocode}
+\cs_new:Npx \@@_unicode_engine_case:nn #1#2
+ {
+ \sys_if_engine_xetex:TF
+ {#1}
+ { \sys_if_engine_luatex:T {#2} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_unicode_char:n}
+% \begin{macrocode}
+\@@_engine_case:nn
+ {
+ \cs_new:Npn \@@_unicode_char:n #1
+ {
+ \exp_not:N \Unicode
+ { \int_div_truncate:nn {#1} { 256 } }
+ { \int_mod:nn {#1} { 256 } }
+ }
+ }
+ { \cs_new:Npn \@@_unicode_char:n #1 { \tex_Uchar:D #1 \scan_stop: } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_preto_cmd:Nn,\@@_appto_cmd:Nn}
+% 补丁工具,来自 \pkg{ctexpatch} 宏包,在宏的原本定义前后增加钩子。
+% \begin{macrocode}
+%<*!thesis>
+\cs_new_protected:Npn \@@_preto_cmd:Nn #1#2
+ {
+ \ctex_preto_cmd:NnnTF #1 { } {#2}
+ { } { \ctex_patch_failure:N #1 }
+ }
+\cs_new_protected:Npn \@@_appto_cmd:Nn #1#2
+ {
+ \ctex_appto_cmd:NnnTF #1 { } {#2}
+ { } { \ctex_patch_failure:N #1 }
+ }
+%</!thesis>
+% \end{macrocode}
+% \end{macro}
+%
+% \changes{v2.0.2}{2023/03/31}{区分 \texttt{dim} 与 \texttt{skip} 类型变量。}
+% \begin{macro}[int]{\@@_dim_set_to_wd:Nn,\@@_skip_add_to_wd:Nn}
+% 操作长度变量的辅助函数。
+% \begin{macrocode}
+%<*thesis>
+\cs_new:Npn \@@_dim_set_to_wd:Nn #1#2
+ {
+ \hbox_set:Nn \l_@@_tmp_box {#2}
+ \dim_set:Nn #1 { \box_wd:N \l_@@_tmp_box }
+ }
+%</thesis>
+\cs_new:Npn \@@_skip_add_to_wd:Nn #1#2
+ {
+ \hbox_set:Nn \l_@@_tmp_box {#2}
+ \skip_add:Nn #1 { \box_wd:N \l_@@_tmp_box }
+ }
+%<thesis>\cs_generate_variant:Nn \@@_dim_set_to_wd:Nn { Nv }
+\cs_generate_variant:Nn \@@_skip_add_to_wd:Nn { cv }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_cs_provide_eq:NN}
+% \begin{macrocode}
+\cs_new:Npn \@@_cs_provide_eq:NN #1#2
+ { \cs_if_exist:NF #1 { \cs_set_eq:NN #1 #2 } }
+\cs_generate_variant:Nn \@@_cs_provide_eq:NN { cc }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_vspace:N,\@@_vspace:n,
+% \@@_vspace_r:N,\@@_vspace_r:n}
+% 类似 \LaTeXe{} 中的 \tn{vspace} 和 \tn{vspace*}。
+% \begin{macrocode}
+%<*thesis>
+\cs_new_protected:Npn \@@_vspace:N #1
+ {
+ \skip_vertical:N #1
+ \skip_vertical:N \c_zero_skip
+ }
+\cs_new_protected:Npn \@@_vspace:n #1
+ {
+ \skip_set:Nn \l_@@_tmp_skip {#1}
+ \@@_vspace:N \l_@@_tmp_skip
+ }
+\cs_new_protected:Npn \@@_vspace_r:N #1
+ {
+ \dim_set_eq:NN \l_@@_tmp_dim \prevdepth
+ \hrule height \c_zero_dim
+ \nobreak
+ \skip_vertical:N #1
+ \skip_vertical:N \c_zero_skip
+ \dim_set_eq:NN \prevdepth \l_@@_tmp_dim
+ }
+\cs_new_protected:Npn \@@_vspace_r:n #1
+ {
+ \skip_set:Nn \l_@@_tmp_skip {#1}
+ \@@_vspace_r:N \l_@@_tmp_skip
+ }
+%</thesis>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_define_name:nn,\@@_define_name:nv,\@@_define_name:nnn,
+% \@@_define_name_from_clist:nnnn}
+% 定义默认名称的辅助函数。
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_define_name:nn #1#2
+ { \tl_const:cn { c_@@_name_ #1 _tl } {#2} }
+\cs_new_protected:Npn \@@_define_name:nnn #1#2#3
+ { \tl_const:cn { c_@@_name_ #2 _ #1 _tl } {#3} }
+%<*thesis>
+\cs_new_protected:Npn \@@_define_name_from_clist:nnnn #1#2#3#4
+ { \tl_const:cx { c_@@_name_ #2 _ #1 _tl } { \clist_item:nn {#4} {#3} } }
+\cs_generate_variant:Nn \@@_define_name:nn { nv }
+%</thesis>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_define_symbol:nn}
+% 定义符号的辅助函数。
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_define_symbol:nn #1#2
+ { \tl_const:cx { c_@@_symbol_ #1 _tl } { \@@_unicode_char:n {#2} } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_if_lang_valid:nTF}
+% 验证语言选项的函数。
+% \begin{macrocode}
+%<*thesis>
+\cs_new_protected:Npn \@@_if_lang_valid:nTF #1
+ { \clist_if_in:NnTF \g_@@_lang_clist {#1} }
+\msg_new:nnn { sjtutex } { lang-validation }
+ { Invalid~ language~ argument~ `#1'! }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{页面模板}
+%
+% 使用 \pkg{xtemplate} 构建页面模板,用于绘制标题页与版权页。
+%
+% 页面部件模板。
+% \begin{macrocode}
+\DeclareObjectType { sjtu } { 0 }
+\DeclareTemplateInterface { sjtu } { component } { 0 }
+ {
+ format : tokenlist = \c_empty_tl ,
+ content : tokenlist = \c_empty_tl ,
+ bottom-skip : skip = \c_zero_skip ,
+ align : choice { left, right, center, normal } = center
+ }
+\DeclareTemplateCode { sjtu } { component } { 0 }
+ {
+ format = \l_@@_component_format_tl ,
+ content = \l_@@_component_content_tl ,
+ bottom-skip = \l_@@_component_bottom_skip ,
+ align =
+ {
+ left =
+ \cs_set_eq:NN \l_@@_component_align: \raggedright ,
+ right =
+ \cs_set_eq:NN \l_@@_component_align: \raggedleft ,
+ center =
+ \cs_set_eq:NN \l_@@_component_align: \centering ,
+ normal =
+ \cs_set_eq:NN \l_@@_component_align: \prg_do_nothing:
+ }
+ }
+ {
+ \AssignTemplateKeys
+ \group_begin:
+ \l_@@_component_align:
+ \l_@@_component_format_tl
+ \l_@@_component_content_tl
+ \par
+ \group_end:
+ \@@_vspace:N \l_@@_component_bottom_skip
+ }
+% \end{macrocode}
+%
+% 页面模板。
+% \begin{macrocode}
+\DeclareTemplateInterface { sjtu } { page } { 0 }
+ {
+ bookmark : boolean = false ,
+ bookmark-text : tokenlist = \c_empty_tl ,
+ style : tokenlist = empty ,
+ format : tokenlist = \c_empty_tl ,
+ prefix : tokenlist ,
+ components : commalist ,
+ top-skip : skip = \c_zero_skip ,
+ bottom-skip : skip = \c_zero_skip
+ }
+\DeclareTemplateCode { sjtu } { page } { 0 }
+ {
+ bookmark = \l_@@_page_bookmark_bool ,
+ bookmark-text = \l_@@_page_bookmark_text_tl ,
+ style = \l_@@_page_style_tl ,
+ format = \l_@@_page_format_tl ,
+ prefix = \l_@@_page_prefix_tl ,
+ components = \l_@@_page_components_clist ,
+ top-skip = \l_@@_page_top_skip ,
+ bottom-skip = \l_@@_page_bottom_skip
+ }
+ {
+ \AssignTemplateKeys
+ \bool_if:NTF \g_@@_openright_bool
+ { \cleardoublepage } { \clearpage }
+ \bool_if:NT \l_@@_page_bookmark_bool
+ { \@@_pdf_bookmark:nn { 0 } { \l_@@_page_bookmark_text_tl } }
+ \exp_args:No \thispagestyle { \l_@@_page_style_tl }
+% \end{macrocode}
+% 移除页面顶部 \tn{vspace*} 的多余空白。
+% 见 \url{https://tex.stackexchange.com/questions/247513}。
+% \begin{macrocode}
+ \@@_vspace_r:N \l_@@_page_top_skip
+ \@@_vspace:n { - \tex_parskip:D }
+ \@@_vspace:n { - \tex_baselineskip:D }
+ \group_begin:
+ \l_@@_page_format_tl
+ \clist_map_inline:Nn \l_@@_page_components_clist
+ { \UseInstance { sjtu } { \l_@@_page_prefix_tl / ##1 } }
+ \group_end:
+ \@@_vspace:N \l_@@_page_bottom_skip
+ \clearpage
+ }
+% \end{macrocode}
+%
+% 辅助函数。
+% \begin{macrocode}
+\cs_new:Npn \@@_declare_component:nnn #1#2#3
+ { \DeclareInstance { sjtu } {#1/#2} { component } {#3} }
+\cs_new:Npn \@@_declare_page:nn #1#2
+ { \DeclareInstance { sjtu } {#1} { page } {#2} }
+%</thesis>
+% \end{macrocode}
+%
+% \subsection{字号行距}
+%
+% \begin{macro}[int]{\@@_set_font_size:nnNn}
+% \begin{macro}{\normalsize}
+% 重定义 \tn{normalsize},设置正文的基线间距。
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_set_font_size:nnNn #1#2#3#4
+ { \cs_set_protected:Npn #3 { \@setfontsize #3 {#1} {#2} #4 } }
+\tl_set:Nx \l_@@_font_size_tl
+ {
+ { \dim_to_decimal:n { \g_@@_font_size_dim } }
+ { \dim_to_decimal:n { \g_@@_baseline_skip_dim } }
+ }
+\bool_if:NT \g_@@_fixed_baselineskip_bool
+ {
+ \int_case:nn { \g_@@_font_size_int }
+ {
+ { 1 } {
+ \exp_after:wN \@@_set_font_size:nnNn \l_@@_font_size_tl
+ \normalsize
+ {
+ \abovedisplayskip 10\p@ \@plus2\p@ \@minus5\p@
+ \abovedisplayshortskip \z@ \@plus3\p@
+ \belowdisplayshortskip 6\p@ \@plus3\p@ \@minus3\p@
+ \belowdisplayskip \abovedisplayskip
+ \let\@listi\@listI
+ }
+ }
+ { 2 } {
+ \exp_after:wN \@@_set_font_size:nnNn \l_@@_font_size_tl
+ \normalsize
+ {
+ \abovedisplayskip 12\p@ \@plus3\p@ \@minus7\p@
+ \abovedisplayshortskip \z@ \@plus3\p@
+ \belowdisplayshortskip 6.5\p@ \@plus3.5\p@ \@minus3\p@
+ \belowdisplayskip \abovedisplayskip
+ \let\@listi\@listI
+ }
+ }
+ }
+ \normalsize
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\setbaselineskip}
+% 设置基线间距,在字号命令之后使用。
+% \begin{macrocode}
+\NewDocumentCommand \setbaselineskip { m }
+ { \fontsize { \f@size } {#1} \selectfont }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{字体配置}
+%
+% \begin{macro}[int]{\@@_fontset_error:nn}
+% 字库不可用时给出紧急错误信息,停止读取定义文件。
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_fontset_error:nn #1#2
+ { \msg_error:nnnn { sjtutex } { font-unavailable } {#1} {#2} }
+\msg_new:nnn { sjtutex } { font-unavailable }
+ { `#1-font~ =~ #2'~ is~ unavailable~ in~ current~ mode. }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_fontset_case:nn}
+% 2 个参数依次为 \pdfTeX 和 \XeTeX/\LuaTeX。
+% \begin{macrocode}
+\cs_new_eq:NN \@@_fontset_case:nn \@@_engine_case:nn
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_fontset_case:nnn}
+% 3 个参数依次为 \pdfTeX(生成 PDF)、\pdfTeX(生成 DVI) 和
+% \XeTeX/\LuaTeX。
+% \begin{macrocode}
+\cs_new:Npx \@@_fontset_case:nnn #1#2#3
+ {
+ \@@_engine_case:nn
+ { \sys_if_output_pdf:TF {#1} {#2} }
+ {#3}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_declare_math_symbol:nnNn}
+% \begin{macrocode}
+\cs_new_protected:Nn \@@_declare_math_symbol:nnNn
+ {
+ \cs_undefine:N #3
+ \DeclareMathSymbol {#3} {#1} {#2} {#4}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_set_slanted_greek:}
+% \begin{macrocode}
+\cs_new_protected:Nn \@@_set_slanted_greek:
+ {
+ \clist_const:Nn \c_@@_uppercase_greek_clist
+ { Gamma, Delta, Theta, Lambda, Xi, Pi, Sigma, Upsilon, Phi, Psi, Omega }
+ \clist_map_inline:Nn \c_@@_uppercase_greek_clist
+ {
+ \cs_set_eq:cc { up ##1 } { ##1 }
+ \cs_set_eq:cc { it ##1 } { var ##1 }
+ }
+ \bool_if:NT \g_@@_slanted_uppercase_greek_bool
+ {
+ \clist_map_inline:Nn \c_@@_uppercase_greek_clist
+ { \cs_set_eq:cc { ##1 } { it ##1 } }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_set_unimath_symbol:}
+% \begin{macrocode}
+\cs_new_protected:Nn \@@_set_unimath_symbol:
+ {
+ \clist_map_inline:nn
+ {
+ { increment } { upDelta } ,
+ { QED } { blacksquare }
+ }
+ { \@@_cs_provide_eq:cc ##1 }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% 如果没有指定数学字体,则根据西文字体设置匹配的数字字体。
+% \begin{macrocode}
+\tl_if_empty:NT \g_@@_math_font_tl
+ { \tl_gset_eq:NN \g_@@_math_font_tl \g_@@_text_font_tl }
+% \end{macrocode}
+%
+% 根据操作系统判断默认 CJK 字体配置。
+% \begin{macrocode}
+\tl_if_empty:NT \g_@@_cjk_font_tl
+ {
+ \sys_if_platform_windows:TF
+ { \tl_gset:Nn \g_@@_cjk_font_tl { windows } }
+ {
+ \ctex_if_platform_macos:TF
+ { \tl_gset:Nn \g_@@_cjk_font_tl { mac } }
+ { \tl_gset:Nn \g_@@_cjk_font_tl { fandol } }
+ }
+ }
+% \end{macrocode}
+%
+% \begin{macro}[int]{\@@_load_font:nn,\@@_load_fontset:}
+% 如果字体配置文件不存在,则载入默认值,并给出警告。
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_load_font:nn #1#2
+ {
+ \str_if_eq:eeF { \tl_use:c { g_@@_ #1 _font_tl } } { none }
+ {
+ \file_if_exist:nF
+ { sjtu- #1 -font- \tl_use:c { g_@@_ #1 _font_tl } .def }
+ {
+ \msg_warning:nnnn { sjtutex } { invalid-font } {#1} {#2}
+ \tl_gset:cn { g_@@_ #1 _font_tl } {#2}
+ }
+ \ctex_file_input:n
+ { sjtu- #1 -font- \tl_use:c { g_@@_ #1 _font_tl } .def }
+ }
+ }
+\msg_new:nnn { sjtutex } { invalid-font }
+ {
+ Invalid~ value~ `#1-font~ =~ \tl_use:c { g_@@_ #1 _font_tl }~ '! \\\\
+ Using~ `#2'~ instead.
+ }
+\cs_new_protected:Nn \@@_load_fontset:
+ {
+ \clist_map_inline:nn
+ {
+ { math } { newtx },
+ { text } { newtx },
+ { cjk } { fandol }
+ }
+ { \@@_load_font:nn ##1 }
+ }
+\@onlypreamble \@@_load_font:nn
+\@onlypreamble \@@_load_fontset:
+%</class>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{西文与数学字体}
+%
+% \changes{v2.0.3}{2023/09/25}{新增 \opt{libertinus} 字体配置。}
+% \begin{macrocode}
+%<*font&(math|text)>
+%<*stixtwo>
+\@@_fontset_case:nn
+ {
+%<*math>
+ \DeclareSizeFunction { sub } { \sub@sfcnt \@font@info }
+ \PassOptionsToPackage { notext } { stix2 }
+ \RequirePackage { stix2 }
+ \clist_map_inline:nn
+ {
+ \upalpha { "0B } ,
+ \upbeta { "0C } ,
+ \upgamma { "0D } ,
+ \updelta { "0E } ,
+ \upepsilon { "0F } ,
+ \upzeta { "10 } ,
+ \upeta { "11 } ,
+ \uptheta { "12 } ,
+ \upiota { "13 } ,
+ \upkappa { "14 } ,
+ \uplambda { "15 } ,
+ \upmu { "16 } ,
+ \upnu { "17 } ,
+ \upxi { "18 } ,
+ \uppi { "19 } ,
+ \uprho { "1A } ,
+ \upsigma { "1B } ,
+ \uptau { "1C } ,
+ \upupsilon { "1D } ,
+ \upphi { "1E } ,
+ \upchi { "1F } ,
+ \uppsi { "20 } ,
+ \upomega { "21 } ,
+ \upvarepsilon { "22 } ,
+ \upvartheta { "23 } ,
+ \upvarpi { "24 } ,
+ \upvarrho { "25 } ,
+ \upvarsigma { "26 } ,
+ \upvarphi { "27 }
+ }
+ { \@@_declare_math_symbol:nnNn { \stix@lcgc } { operators } #1 }
+ \@@_set_slanted_greek:
+%</math>
+%<*text>
+ \tl_set:Nn \encodingdefault { T1 }
+ \DeclareEncodingSubset { TS1 } { ? } { 0 }
+ \UndeclareTextCommand { \textpertenthousand } { T1 }
+ \DeclareTextSymbolDefault { \textpertenthousand } { TS1 }
+ \tl_set:Nn \rmdefault { stix2 }
+ \tl_set:Nn \qhv@scale { 0.94 }
+ \tl_set:Nn \sfdefault { qhv }
+ \tl_set:Nn \ttdefault { qcr }
+%</text>
+ }
+ {
+%<*math>
+ \RequirePackage { unicode-math }
+ \bool_if:NTF \g_@@_upright_integral_bool
+ {
+ \setmathfont { STIXTwoMath-Regular.otf }
+ [ StylisticSet = 8 ]
+ }
+ { \setmathfont { STIXTwoMath-Regular.otf } }
+ \setmathfont { STIXTwoMath-Regular.otf }
+ [
+ range = { scr, bfscr },
+ StylisticSet = 1
+ ]
+%</math>
+%<math> \setmathrm
+%<text> \setmainfont
+ { STIXTwoText }
+ [
+ Extension = .otf,
+ UprightFont = *-Regular,
+ BoldFont = *-Bold,
+ ItalicFont = *-Italic,
+ BoldItalicFont = *-BoldItalic
+ ]
+%</stixtwo>
+%<*xits>
+\@@_fontset_case:nn
+%<math> { \@@_fontset_error:nn { math } { xits } }
+%<text> { \@@_fontset_error:nn { text } { xits } }
+ {
+%<*math>
+ \RequirePackage { unicode-math }
+ \bool_if:NTF \g_@@_upright_integral_bool
+ {
+ \setmathfont { XITSMath-Regular }
+ [
+ Extension = .otf,
+ BoldFont = XITSMath-Bold,
+ StylisticSet = 8
+ ]
+ }
+ {
+ \setmathfont { XITSMath-Regular }
+ [
+ Extension = .otf,
+ BoldFont = XITSMath-Bold,
+ ]
+ }
+ \setmathfont { XITSMath-Regular.otf }
+ [
+ range = { cal, bfcal },
+ StylisticSet = 1
+ ]
+%</math>
+%<math> \setmathrm
+%<text> \setmainfont
+ { XITS }
+ [
+ Extension = .otf,
+ UprightFont = *-Regular,
+ BoldFont = *-Bold,
+ ItalicFont = *-Italic,
+ BoldItalicFont = *-BoldItalic
+ ]
+%</xits>
+%<*newtx|newpx>
+%<*math>
+\tl_set_eq:NN \l_@@_save_encodingdefault_tl \encodingdefault
+\tl_set_eq:NN \l_@@_save_rmdefault_tl \rmdefault
+\tl_set_eq:NN \l_@@_save_sfdefault_tl \sfdefault
+\tl_set_eq:NN \l_@@_save_ttdefault_tl \ttdefault
+\tl_set:Nn \encodingdefault { OT1 }
+%<newtx>\tl_set:Nn \rmdefault { ntxtlf }
+%<newpx>\tl_set:Nn \rmdefault { zplTLF }
+\tl_set:Nn \qhv@scale { 0.94 }
+\tl_set:Nn \sfdefault { qhv }
+\tl_set:Nn \ttdefault { qcr }
+%<newtx>\RequirePackage { newtxmath }
+%<newpx>\RequirePackage { newpxmath }
+\tl_set_eq:NN \encodingdefault \l_@@_save_encodingdefault_tl
+\tl_set_eq:NN \rmdefault \l_@@_save_rmdefault_tl
+\tl_set_eq:NN \sfdefault \l_@@_save_sfdefault_tl
+\tl_set_eq:NN \ttdefault \l_@@_save_ttdefault_tl
+\@@_set_unimath_symbol:
+%</math>
+%<*text>
+\@@_fontset_case:nn
+ {
+ \tl_set:Nn \encodingdefault { T1 }
+%<newtx> \RequirePackage { newtxtext }
+%<newpx> \RequirePackage { newpxtext }
+ \tl_set:Nn \ttdefault { qcr }
+ }
+ {
+ \setmainfont
+%<newtx> { TeXGyreTermesX }
+%<newpx> { TeXGyrePagellaX }
+ [
+ Extension = .otf,
+ UprightFont = *-Regular,
+ BoldFont = *-Bold,
+ ItalicFont = *-Italic,
+ BoldItalicFont = *-BoldItalic
+ ]
+%</text>
+%</newtx|newpx>
+%<*text&(newtx|newpx)|stixtwo|xits>
+%<math> \setmathsf
+%<text> \setsansfont
+ { texgyreheros }
+ [
+ Extension = .otf,
+ UprightFont = *-regular,
+ BoldFont = *-bold,
+ ItalicFont = *-italic,
+ BoldItalicFont = *-bolditalic,
+ Scale = 0.94,
+ ]
+%<math> \setmathtt
+%<text> \setmonofont
+ { texgyrecursor }
+ [
+ Extension = .otf,
+ UprightFont = *-regular,
+ BoldFont = *-bold,
+ ItalicFont = *-italic,
+ BoldItalicFont = *-bolditalic,
+ Ligatures = CommonOff
+ ]
+ }
+%</text&(newtx|newpx)|stixtwo|xits>
+%<*lm>
+%<*text>
+\@@_fontset_case:nn
+ {
+ \tl_set:Nn \encodingdefault { T1 }
+ \tl_set:Nn \rmdefault { lmr }
+ \tl_set:Nn \sfdefault { lmss }
+ \tl_set:Nn \ttdefault { lmtt }
+ } { }
+%</text>
+%<*math>
+\RequirePackage { amssymb, upgreek }
+\SetSymbolFont { operators } { normal } { OT1 } { lmr } { m } { n }
+\SetSymbolFont { letters } { normal } { OML } { lmm } { m } { it }
+\SetSymbolFont { symbols } { normal } { OMS } { lmsy } { m } { n }
+\SetSymbolFont { largesymbols } { normal } { OMX } { lmex } { m } { n }
+\SetSymbolFont { operators } { bold } { OT1 } { lmr } { bx } { n }
+\SetSymbolFont { letters } { bold } { OML } { lmm } { b } { it }
+\SetSymbolFont { symbols } { bold } { OMS } { lmsy } { b } { n }
+\SetSymbolFont { largesymbols } { bold } { OMX } { lmex } { m } { n }
+\SetMathAlphabet { \mathbf } { normal } { OT1 } { lmr } { bx } { n }
+\SetMathAlphabet { \mathsf } { normal } { OT1 } { lmss } { m } { n }
+\SetMathAlphabet { \mathit } { normal } { OT1 } { lmr } { m } { it }
+\SetMathAlphabet { \mathtt } { normal } { OT1 } { lmtt } { m } { n }
+\SetMathAlphabet { \mathbf } { bold } { OT1 } { lmr } { bx } { n }
+\SetMathAlphabet { \mathsf } { bold } { OT1 } { lmss } { bx } { n }
+\SetMathAlphabet { \mathit } { bold } { OT1 } { lmr } { bx } { it }
+\SetMathAlphabet { \mathtt } { bold } { OT1 } { lmtt } { m } { n }
+\bool_if:NT \g_@@_upright_integral_bool
+ { \RequirePackage { cmupint } }
+\@@_set_slanted_greek:
+\@@_set_unimath_symbol:
+%</math>
+%</lm>
+%<*libertinus>
+\@@_fontset_case:nn
+ {
+%<*text>
+ \tl_set:Nn \encodingdefault { T1 }
+ \tl_set:Nn \rmdefault { LibertinusSerif-TLF }
+ \tl_set:Nn \sfdefault { LibertinusSans-TLF }
+ \tl_set:Nn \ttdefault { lmtt }
+%</text>
+%<*math>
+ \exp_args:No \PassOptionsToPackage
+ { \g_@@_math_font_options_clist } { libertinust1math }
+ \RequirePackage { libertinust1math }
+%</math>
+ }
+ {
+%<*math>
+ \RequirePackage { unicode-math }
+ \bool_if:NTF \g_@@_upright_integral_bool
+ { \setmathfont { LibertinusMath-Regular.otf } }
+ {
+ \setmathfont { LibertinusMath-Regular.otf }
+ [ StylisticSet = 8 ]
+ }
+ \setmathfont { latinmodern-math.otf } [ range = \checkmark ]
+%</math>
+%<math> \setmathrm
+%<text> \setmainfont
+ { LibertinusSerif }
+ [
+ Extension = .otf,
+ UprightFont = *-Regular,
+ BoldFont = *-Bold,
+ ItalicFont = *-Italic,
+ BoldItalicFont = *-BoldItalic,
+ SlantedFont = *-Regular,
+ BoldSlantedFont = *-Bold,
+ SlantedFeatures = { FakeSlant = 0.2 },
+ BoldSlantedFeatures = { FakeSlant = 0.2 }
+ ]
+%<math> \setmathsf
+%<text> \setsansfont
+ { LibertinusSans }
+ [
+ Extension = .otf,
+ UprightFont = *-Regular,
+ BoldFont = *-Bold,
+ ItalicFont = *-Italic,
+ BoldItalicFont = *-Italic,
+ BoldItalicFeatures = { FakeBold = 3 },
+ SlantedFont = *-Regular,
+ BoldSlantedFont = *-Bold,
+ SlantedFeatures = { FakeSlant = 0.2 },
+ BoldSlantedFeatures = { FakeSlant = 0.2 }
+ ]
+ }
+%</libertinus>
+%<*times>
+%<*math>
+\PassOptionsToPackage { Symbol } { upgreek }
+\RequirePackage { amssymb, upgreek }
+\tl_set_eq:NN \l_@@_save_rmdefault_tl \rmdefault
+ \RequirePackage { mathptmx }
+\tl_set_eq:NN \rmdefault \l_@@_save_rmdefault_tl
+\tl_set:Nn \Hv@scale { 0.94 }
+\DeclareMathAlphabet { \mathsf } { OT1 } { phv } { m } { n }
+\DeclareMathAlphabet { \mathtt } { OT1 } { pcr } { m } { n }
+\SetMathAlphabet { \mathsf } { bold } { OT1 } { phv } { b } { n }
+\SetMathAlphabet { \mathtt } { bold } { OT1 } { pcr } { b } { n }
+\DeclareSymbolFont { SJTU@ptm } { OML } { ptmcm } { m } { it }
+\@@_declare_math_symbol:nnNn { \mathord } { SJTU@ptm } \upvarsigma { "26 }
+\bool_if:NT \g_@@_upright_integral_bool
+ { \RequirePackage { cmupint } }
+\@@_set_unimath_symbol:
+%</math>
+%<*text>
+\@@_fontset_case:nn
+ {
+ \tl_set:Nn \encodingdefault { T1 }
+ \tl_set:Nn \rmdefault { ptm }
+ \tl_set:Nn \Hv@scale { 0.94 }
+ \tl_set:Nn \sfdefault { phv }
+ \tl_set:Nn \ttdefault { pcr }
+ }
+ {
+ \setmainfont { Times~New~Roman } [ Ligatures = Rare ]
+ \setsansfont { Arial } [ Scale = 0.94 ]
+ \setmonofont { Courier~New }
+ }
+%</text>
+%</times>
+%<*newcm>
+\@@_fontset_case:nn
+%<math> { \@@_fontset_error:nn { math } { newcm } }
+%<text> { \@@_fontset_error:nn { text } { newcm } }
+ {
+%<*math>
+ \RequirePackage { unicode-math }
+ \bool_if:NTF \g_@@_upright_integral_bool
+ {
+ \setmathfont { NewCMMath-Book.otf }
+ [ StylisticSet = 2 ]
+ }
+ { \setmathfont { NewCMMath-Book.otf } }
+ \setmathfont { NewCMMath-Book.otf }
+ [
+ range = { scr, bfscr },
+ StylisticSet = 1
+ ]
+%</math>
+%<math> \setmathrm
+%<text> \setmainfont
+ { NewCM10 }
+ [
+ Extension = .otf,
+ SizeFeatures =
+ {
+ {
+ Size = -9,
+ Font = NewCM08-Book,
+ ItalicFont = NewCM08-BookItalic,
+ SlantedFont = NewCM08-Book,
+ },
+ { Size = 9- }
+ },
+ UprightFont = *-Book,
+ BoldFont = *-Bold,
+ ItalicFont = *-BookItalic,
+ BoldItalicFont = *-BoldItalic,
+ SlantedFont = *-Book,
+ BoldSlantedFont = *-Bold,
+ SlantedFeatures = { FakeSlant = 0.25 },
+ BoldSlantedFeatures = { FakeSlant = 0.25 }
+ ]
+%<math> \setmathsf
+%<text> \setsansfont
+ { NewCMSans10 }
+ [
+ Extension = .otf,
+ SizeFeatures =
+ {
+ {
+ Size = -9,
+ Font = NewCMSans08-Book,
+ ItalicFont = NewCMSans08-BookOblique,
+ },
+ { Size = 9- }
+ },
+ UprightFont = *-Book,
+ BoldFont = *-Bold,
+ ItalicFont = *-BookOblique,
+ BoldItalicFont = *-BoldOblique
+ ]
+%<math> \setmathtt
+%<text> \setmonofont
+ { NewCMMono10 }
+ [
+ Extension = .otf,
+ UprightFont = *-Book,
+ BoldFont = *-Bold,
+ ItalicFont = *-BookItalic,
+ BoldItalicFont = *-BoldOblique,
+ SlantedFont = *-Book,
+ SlantedFeatures = { FakeSlant = 0.25 },
+ BoldSlantedFont = *-Bold,
+ BoldSlantedFeatures = { FakeSlant = 0.25 }
+ ]
+ }
+%</newcm>
+%<*cambria>
+\@@_fontset_case:nn
+%<math> { \@@_fontset_error:nn { math } { cambria } }
+%<text> { \@@_fontset_error:nn { text } { cambria } }
+ {
+%<*math>
+ \RequirePackage { unicode-math }
+ \setmathfont { Cambria~Math }
+ \setmathrm { Cambria }
+ \setmathsf { Calibri }
+ \setmathtt { Consolas } [ Scale = 0.95 ]
+%</math>
+%<*text>
+ \setmainfont { Cambria }
+ \setsansfont { Calibri }
+ \setmonofont { Consolas } [ Scale = 0.95 ]
+%</text>
+ }
+%</cambria>
+%</font&(math|text)>
+% \end{macrocode}
+%
+% \pkg{unicode-math} 宏包设置。
+% \begin{macrocode}
+%<*class>
+\ctex_at_end_package:nn { unicode-math }
+ {
+ \DeclareDocumentCommand \bm { m }
+ { { \symbf {#1} } }
+ \DeclareDocumentCommand \boldsymbol { m }
+ { { \symbf {#1} } }
+ \bool_if:NTF \g_@@_slanted_uppercase_greek_bool
+ { \keys_set:nn { unicode-math } { math-style = ISO } }
+ { \keys_set:nn { unicode-math } { math-style = TeX } }
+ \bool_if:NTF \g_@@_integral_limits_bool
+ { \removenolimits } { \addnolimits }
+ {
+ \int\iint\iiint\iiiint\oint\oiint\oiiint
+ \intclockwise\varointclockwise\ointctrclockwise\sumint
+ \intbar\intBar\fint\cirfnint\awint\rppolint
+ \scpolint\npolint\pointint\sqint\intlarhk\intx
+ \intcap\intcup\upint\lowint
+ }
+ }
+% \end{macrocode}
+%
+% 若未使用 \pkg{unicode-math} 配置数学字体,则自动调用 \pkg{bm}。
+% \begin{macrocode}
+\ctex_at_end_preamble:n
+ {
+ \@ifpackageloaded { unicode-math }
+ { } { \RequirePackage { bm } }
+ }
+%</class>
+% \end{macrocode}
+%
+% \subsubsection{CJK 字体}
+%
+% 在字体未提供对应粗体的情况下,允许使用伪粗。
+% \begin{macrocode}
+%<*font&cjk>
+%<*windows>
+%<*und>
+\tl_if_eq:NNTF \g_@@_lang_tl \c_@@_lang_ja_tl
+ { \ctex_file_input:n { sjtu-cjk-font-windows-ja.def } }
+ { \ctex_file_input:n { sjtu-cjk-font-windows-zh.def } }
+%</und>
+%<*zh|ja>
+\@@_fontset_case:nn
+%<*zh>
+ {
+ \ctex_load_zhmap:nnnn { zhsong } { zhhei } { zhfs } { windows }
+ \ctex_punct_set:n { windows }
+ \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong }
+ \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei }
+ \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai }
+ }
+%</zh>
+%<ja> { \@@_fontset_error:nn { cjk } { windows } }
+ {
+%<*zh>
+ \setCJKmainfont { SimSun }
+ [ AutoFakeBold = 3 , ItalicFont = KaiTi ]
+ \setCJKsansfont { SimHei } [ AutoFakeBold = 3 ]
+ \setCJKmonofont { FangSong }
+%</zh>
+%<*ja>
+ \setCJKmainfont { MS~Mincho } [ AutoFakeBold = 3 ]
+ \setCJKsansfont { MS~Gothic } [ AutoFakeBold = 3 ]
+ \setCJKmonofont { MS~Mincho }
+ \setCJKfamilyfont { jamin } { MS~Mincho } [ AutoFakeBold = 3 ]
+ \setCJKfamilyfont { jagoth } { MS~Gothic } [ AutoFakeBold = 3 ]
+%</ja>
+ \setCJKfamilyfont { zhsong } { SimSun }
+ [ AutoFakeBold = 3 , ItalicFont = KaiTi ]
+ \setCJKfamilyfont { zhhei } { SimHei } [ AutoFakeBold = 3 ]
+ \setCJKfamilyfont { zhkai } { KaiTi }
+ \setCJKfamilyfont { zhfs } { FangSong }
+ }
+%</zh|ja>
+%</windows>
+%<*mac>
+%<*und>
+\tl_if_eq:NNTF \g_@@_lang_tl \c_@@_lang_ja_tl
+ { \ctex_file_input:n { sjtu-cjk-font-mac-ja.def } }
+ { \ctex_file_input:n { sjtu-cjk-font-mac-zh.def } }
+%</und>
+%<*zh|ja>
+%<zh>\@@_fontset_case:nnn
+%<ja>\@@_fontset_case:nn
+ { \@@_fontset_error:nn { cjk } { mac } }
+%<*zh>
+ {
+ \ctex_load_zhmap:nnnn { zhsong } { zhhei } { zhfs } { mac }
+ \ctex_punct_set:n { mac }
+ \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong }
+ \ctex_punct_map_family:nn { \CJKsfdefault } { zhpf }
+ \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhpf }
+ \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai }
+ }
+%</zh>
+ {
+%<*zh>
+ \setCJKmainfont { Songti~SC }
+ [
+ UprightFont = *~Light ,
+ BoldFont = *~Bold ,
+ ItalicFont = Kaiti~SC~Regular ,
+ BoldItalicFont = Kaiti~SC~Bold
+ ]
+ \setCJKsansfont { Heiti~SC }
+ [
+ UprightFont = *~Medium ,
+ AutoFakeBold = 3
+ ]
+ \setCJKmonofont { STFangsong }
+%</zh>
+%<*ja>
+ \setCJKmainfont { HiraMinProN }
+ [
+ UprightFont = *-W3 ,
+ BoldFont = *-W6
+ ]
+ \setCJKsansfont { HiraKakuProN }
+ [
+ UprightFont = *-W3 ,
+ BoldFont = *-W6
+ ]
+ \setCJKmonofont { HiraMinProN-W3 }
+ \setCJKfamilyfont { jamin } { HiraMinProN }
+ [
+ UprightFont = *-W3 ,
+ BoldFont = *-W6
+ ]
+ \setCJKfamilyfont { jagoth } { HiraKakuProN }
+ [
+ UprightFont = *-W3 ,
+ BoldFont = *-W6
+ ]
+%</ja>
+ \setCJKfamilyfont { zhsong } { Songti~SC }
+ [
+ UprightFont = *~Light ,
+ BoldFont = *~Bold ,
+ ItalicFont = Kaiti~SC~Regular ,
+ BoldItalicFont = Kaiti~SC~Bold
+ ]
+ \setCJKfamilyfont { zhhei } { Heiti~SC }
+ [
+ UprightFont = *~Medium ,
+ AutoFakeBold = 3
+ ]
+ \setCJKfamilyfont { zhfs } { STFangsong }
+ \setCJKfamilyfont { zhkai } { Kaiti~SC }
+ [
+ UprightFont = *~Regular ,
+ BoldFont = *~Bold
+ ]
+ }
+%</zh|ja>
+%</mac>
+%<*ubuntu>
+%<*und>
+\tl_if_eq:NNTF \g_@@_lang_tl \c_@@_lang_ja_tl
+ { \ctex_file_input:n { sjtu-cjk-font-ubuntu-ja.def } }
+ { \ctex_file_input:n { sjtu-cjk-font-ubuntu-zh.def } }
+%</und>
+%<*zh|ja>
+%<zh>\@@_fontset_case:nnn
+%<ja>\@@_fontset_case:nn
+ { \@@_fontset_error:nn { cjk } { ubuntu } }
+%<*zh>
+ {
+ \ctex_load_zhmap:nnnn { zhsong } { zhhei } { zhsong } { ubuntu }
+ \ctex_punct_set:n { ubuntu }
+ \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong }
+ \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei }
+ \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai }
+ }
+%</zh>
+ {
+%<*zh>
+ \setCJKmainfont { Noto~Serif~CJK~SC }
+ [
+ UprightFont = *~Light ,
+ BoldFont = *~Bold ,
+ ItalicFont = AR~PL~KaitiM~GB
+ ]
+ \setCJKsansfont { Noto~Sans~CJK~SC }
+ [
+ UprightFont = *~Medium ,
+ BoldFont = *~Bold
+ ]
+ \setCJKmonofont { Noto~Serif~CJK~SC }
+ [
+ UprightFont = *~Light ,
+ BoldFont = *~Bold
+ ]
+%</zh>
+%<*ja>
+ \setCJKmainfont { Noto~Serif~CJK~JP }
+ [
+ UprightFont = *~Light ,
+ BoldFont = *~Bold
+ ]
+ \setCJKsansfont { Noto~Sans~CJK~JP }
+ [
+ UprightFont = *~Medium ,
+ BoldFont = *~Bold
+ ]
+ \setCJKmonofont { Noto~Serif~CJK~JP }
+ [
+ UprightFont = *~Light ,
+ BoldFont = *~Bold
+ ]
+ \setCJKfamilyfont { jamin } { Noto~Serif~CJK~JP }
+ [
+ UprightFont = *~Light ,
+ BoldFont = *~Bold
+ ]
+ \setCJKfamilyfont { jagoth } { Noto~Sans~CJK~JP }
+ [
+ UprightFont = *~Medium ,
+ BoldFont = *~Bold
+ ]
+%</ja>
+ \setCJKfamilyfont { zhsong } { Noto~Serif~CJK~SC }
+ [
+ UprightFont = *~Light ,
+ BoldFont = *~Bold ,
+ ItalicFont = AR~PL~KaitiM~GB
+ ]
+ \setCJKfamilyfont { zhhei } { Noto~Sans~CJK~SC }
+ [
+ UprightFont = *~Medium ,
+ BoldFont = *~Bold
+ ]
+ \setCJKfamilyfont { zhfs } { Noto~Sans~Mono~CJK~JP }
+ \setCJKfamilyfont { zhkai } { AR~PL~KaitiM~GB }
+ }
+%</zh|ja>
+%</ubuntu>
+%<*adobe>
+%<*und>
+\tl_if_eq:NNTF \g_@@_lang_tl \c_@@_lang_ja_tl
+ { \ctex_file_input:n { sjtu-cjk-font-adobe-ja.def } }
+ { \ctex_file_input:n { sjtu-cjk-font-adobe-zh.def } }
+%</und>
+%<*zh|ja>
+%<zh>\@@_fontset_case:nnn
+%<ja>\@@_fontset_case:nn
+ { \@@_fontset_error:nn { cjk } { adobe } }
+%<*zh>
+ {
+ \ctex_load_zhmap:nnnn { zhsong } { zhhei } { zhfs } { adobe }
+ \ctex_punct_set:n { adobe }
+ \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong }
+ \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei }
+ \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai }
+ }
+%</zh>
+ {
+%<*zh>
+ \setCJKmainfont { AdobeSongStd-Light }
+ [ AutoFakeBold = 3 , ItalicFont = AdobeKaitiStd-Regular ]
+ \setCJKsansfont { AdobeHeitiStd-Regular } [ AutoFakeBold = 3 ]
+ \setCJKmonofont { AdobeFangsongStd-Regular }
+%</zh>
+%<*ja>
+ \setCJKmainfont { KozMinPr6N }
+ [
+ UprightFont = *-Light ,
+ BoldFont = *-Bold
+ ]
+ \setCJKsansfont { KozGoPr6N }
+ [
+ UprightFont = *-Medium ,
+ BoldFont = *-Bold
+ ]
+ \setCJKmonofont { KozMinPr6N-Light }
+ \setCJKfamilyfont { jamin } { KozMinPr6N }
+ [
+ UprightFont = *-Light ,
+ BoldFont = *-Bold
+ ]
+ \setCJKfamilyfont { jagoth } { KozGoPr6N }
+ [
+ UprightFont = *-Medium ,
+ BoldFont = *-Bold
+ ]
+%</ja>
+ \setCJKfamilyfont { zhsong } { AdobeSongStd-Light }
+ [ AutoFakeBold = 3 , ItalicFont = AdobeKaitiStd-Regular ]
+ \setCJKfamilyfont { zhhei } { AdobeHeitiStd-Regular } [ AutoFakeBold = 3 ]
+ \setCJKfamilyfont { zhfs } { AdobeFangsongStd-Regular }
+ \setCJKfamilyfont { zhkai } { AdobeKaitiStd-Regular }
+ }
+%</zh|ja>
+%</adobe>
+%<*fandol>
+%<*und>
+\tl_if_eq:NNTF \g_@@_lang_tl \c_@@_lang_ja_tl
+ { \ctex_file_input:n { sjtu-cjk-font-fandol-ja.def } }
+ { \ctex_file_input:n { sjtu-cjk-font-fandol-zh.def } }
+%</und>
+%<*zh|ja>
+%<zh>\@@_fontset_case:nnn
+%<ja>\@@_fontset_case:nn
+ { \@@_fontset_error:nn { cjk } { fandol } }
+%<*zh>
+ {
+ \ctex_load_zhmap:nnnn { zhsong } { zhhei } { zhfs } { fandol }
+ \ctex_punct_set:n { fandol }
+ \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong }
+ \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei }
+ \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai }
+ }
+%</zh>
+ {
+%<*zh>
+ \setCJKmainfont { FandolSong }
+ [
+ Extension = .otf ,
+ UprightFont = *-Regular ,
+ BoldFont = *-Bold ,
+ ItalicFont = FandolKai-Regular
+ ]
+ \setCJKsansfont { FandolHei }
+ [
+ Extension = .otf ,
+ UprightFont = *-Regular ,
+ BoldFont = *-Bold
+ ]
+ \setCJKmonofont { FandolFang }
+ [
+ Extension = .otf ,
+ UprightFont = *-Regular
+ ]
+%</zh>
+%<*ja>
+ \setCJKmainfont { HaranoAjiMincho }
+ [
+ Extension = .otf ,
+ UprightFont = *-Regular ,
+ BoldFont = *-Bold
+ ]
+ \setCJKsansfont { HaranoAjiGothic }
+ [
+ Extension = .otf ,
+ UprightFont = *-Medium ,
+ BoldFont = *-Bold
+ ]
+ \setCJKmonofont { HaranoAjiGothic }
+ [
+ Extension = .otf ,
+ UprightFont = *-Regular
+ ]
+ \setCJKfamilyfont { jamin } { HaranoAjiMincho }
+ [
+ Extension = .otf ,
+ UprightFont = *-Regular ,
+ BoldFont = *-Bold
+ ]
+ \setCJKfamilyfont { jagoth } { HaranoAjiGothic }
+ [
+ Extension = .otf ,
+ UprightFont = *-Medium ,
+ BoldFont = *-Bold
+ ]
+%</ja>
+ \setCJKfamilyfont { zhsong } { FandolSong }
+ [
+ Extension = .otf ,
+ UprightFont = *-Regular ,
+ BoldFont = *-Bold ,
+ ItalicFont = FandolKai-Regular
+ ]
+ \setCJKfamilyfont { zhhei } { FandolHei }
+ [
+ Extension = .otf ,
+ UprightFont = *-Regular,
+ BoldFont = *-Bold
+ ]
+ \setCJKfamilyfont { zhfs } { FandolFang }
+ [
+ Extension = .otf ,
+ UprightFont = *-Regular
+ ]
+ \setCJKfamilyfont { zhkai } { FandolKai }
+ [
+ Extension = .otf ,
+ UprightFont = *-Regular
+ ]
+ }
+%</zh|ja>
+%</fandol>
+%<*founder>
+%<*und>
+\tl_if_eq:NNTF \g_@@_lang_tl \c_@@_lang_ja_tl
+ { \ctex_file_input:n { sjtu-cjk-font-founder-ja.def } }
+ { \ctex_file_input:n { sjtu-cjk-font-founder-zh.def } }
+%</und>
+%<*zh|ja>
+\@@_fontset_case:nn
+%<*zh>
+ {
+ \ctex_load_zhmap:nnnn { zhsong } { zhhei } { zhfs } { founder }
+ \ctex_punct_set:n { founder }
+ \ctex_punct_map_family:nn { \CJKrmdefault } { zhsong }
+ \ctex_punct_map_bfseries:nn { \CJKrmdefault } { zhhei }
+ \ctex_punct_map_itshape:nn { \CJKrmdefault } { zhkai }
+ }
+%</zh>
+%<ja> { \@@_fontset_error:nn { cjk } { founder } }
+ {
+%<*zh>
+ \setCJKmainfont { FZShuSong-Z01 }
+ [ AutoFakeBold = 3 , ItalicFont = FZKai-Z03 ]
+ \setCJKsansfont { FZHei-B01 } [ AutoFakeBold = 3 ]
+ \setCJKmonofont { FZFangSong-Z02 }
+%</zh>
+%<*ja>
+ \setCJKmainfont { ipam.ttf } [ AutoFakeBold = 3 ]
+ \setCJKsansfont { ipag.ttf } [ AutoFakeBold = 3 ]
+ \setCJKmonofont { ipag.ttf }
+ \setCJKfamilyfont { jamin } { ipam.ttf } [ AutoFakeBold = 3 ]
+ \setCJKfamilyfont { jagoth } { ipag.ttf } [ AutoFakeBold = 3 ]
+%</ja>
+ \setCJKfamilyfont { zhsong } { FZShuSong-Z01 }
+ [ AutoFakeBold = 3 , ItalicFont = FZKai-Z03 ]
+ \setCJKfamilyfont { zhhei } { FZHei-B01 } [ AutoFakeBold = 3 ]
+ \setCJKfamilyfont { zhkai } { FZKai-Z03 }
+ \setCJKfamilyfont { zhfs } { FZFangSong-Z02 }
+ }
+%</zh|ja>
+%</founder>
+%<*!und>
+\NewDocumentCommand \songti { } { \CJKfamily { zhsong } }
+\NewDocumentCommand \heiti { } { \CJKfamily { zhhei } }
+%<!ubuntu>\NewDocumentCommand \fangsong { } { \CJKfamily { zhfs } }
+\NewDocumentCommand \kaishu { } { \CJKfamily { zhkai } }
+%<ja>\NewDocumentCommand \mincho { } { \CJKfamily { jamin } }
+%<ja>\NewDocumentCommand \gothic { } { \CJKfamily { jagoth } }
+%</!und>
+%</font&cjk>
+% \end{macrocode}
+%
+% \begin{macro}{\CJKrmfamily,\CJKsffamily,\CJKttfamily}
+% 只改变 CJK 字体族的命令。
+% \begin{macrocode}
+%<*class>
+\NewDocumentCommand \CJKrmfamily { } { \CJKfamily { \CJKrmdefault } }
+\NewDocumentCommand \CJKsffamily { } { \CJKfamily { \CJKsfdefault } }
+\NewDocumentCommand \CJKttfamily { } { \CJKfamily { \CJKttdefault } }
+% \end{macrocode}
+% \end{macro}
+%
+% 带圈数字使用 CJK 字体。
+% \begin{macrocode}
+\@@_unicode_engine_case:nn
+ {
+ \xeCJK_declare_char_class:nn { CJK }
+ { "24EA, "2460->"2473, "3251->"32BF, "25A1 }
+ }
+ {
+ \ltjdefcharrange { 99 }
+ { "24EA, "2460-"2473, "3251-"32BF, "25A1 }
+ \ltjsetparameter { jacharrange = { +99 } }
+ }
+% \end{macrocode}
+%
+% \changes{v2.0.2}{2023/04/01}{延迟载入字体配置,修复 \pkg{unicode-math}
+% 设置不生效的问题。}
+% 载入字体配置。
+% \begin{macrocode}
+\@@_load_fontset:
+% \end{macrocode}
+%
+% \subsection{名称设置}
+%
+% 定义 |sjtu/name| 键值类。
+%
+% 设置标准文档类中已定义的名称。
+% \begin{macrocode}
+\keys_define:nn { sjtu / name }
+ {
+ contents .meta:nn = { ctex } { contentsname = {#1} } ,
+ listfigure .meta:nn = { ctex } { listfigurename = {#1} } ,
+ listtable .meta:nn = { ctex } { listtablename = {#1} } ,
+ figure .meta:nn = { ctex } { figurename = {#1} } ,
+ table .meta:nn = { ctex } { tablename = {#1} } ,
+%<!thesis> abstract .meta:nn = { ctex } { abstractname = {#1} } ,
+ index .meta:nn = { ctex } { indexname = {#1} } ,
+ appendix .meta:nn = { ctex } { appendixname = {#1} } ,
+ proof .meta:nn = { ctex } { proofname = {#1} } ,
+ bib .meta:nn = { ctex } { bibname = {#1} } ,
+ part .tl_set:N = \partname ,
+%<!article> chapter .tl_set:N = \chaptername ,
+% \end{macrocode}
+%
+% \changes{v2.0}{2022/12/28}{简化 \opt{sjtu/name} 中键的名称:\opt{abbr},
+% \opt{nom}, \opt{ack}, \opt{achv}。}
+% 标准文档类中未定义的名称。
+% \begin{macrocode}
+ figure* .tl_set:N = \SJTU@figurename@bi@second ,
+ figure* .initial:n = { 图 } ,
+ table* .tl_set:N = \SJTU@tablename@bi@second ,
+ table* .initial:n = { 表 } ,
+ algorithm .tl_set:N = \SJTU@algorithmname ,
+ algorithm .initial:n = { Algorithm } ,
+ listalgorithm .tl_set:N = \SJTU@listalgorithmname ,
+ listalgorithm .initial:n = { List~of~Algorithms } ,
+%<*thesis>
+ abbr .tl_set:N = \SJTU@abbrname ,
+ abbr .initial:n = { Abbreviations } ,
+ nom .tl_set:N = \SJTU@nomname ,
+ nom .initial:n = { Nomenclature } ,
+ ack .tl_set:N = \SJTU@ackname ,
+ ack .initial:n = { Acknowledgements } ,
+ resume .tl_set:N = \SJTU@resumename ,
+ resume .initial:n = { Resume } ,
+ digest .tl_set:N = \SJTU@digestname ,
+ digest .initial:n = { Digest } ,
+ achv .tl_set:N = \SJTU@achvname ,
+ achv .initial:n = { List~of~Research~Achievements },
+%</thesis>
+ }
+%</class>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*scheme>
+%<*zh>
+\keys_set_known:nn { sjtu / name }
+ {
+ contents = { 目 \protect \quad 录 } ,
+ listfigure = { 插 \protect \quad 图 } ,
+ listtable = { 表 \protect \quad 格 } ,
+ figure = { 图 } ,
+ table = { 表 } ,
+ abstract = { 摘 \protect \quad 要 } ,
+ index = { 索 \protect \quad 引 } ,
+ appendix = { 附录 } ,
+ proof = { 证明 } ,
+ bib = { 参考文献 } ,
+ figure* = { Figure } ,
+ table* = { Table } ,
+ algorithm = { 算法 } ,
+ listalgorithm = { 算 \protect \quad 法 } ,
+ abbr = { 缩略语对照表 } ,
+ nom = { 符号对照表 } ,
+ ack = { 致 \protect \quad 谢 } ,
+ resume = { 个人简历 } ,
+ digest = { 大摘要 } ,
+ achv = { 学术论文和科研成果目录 }
+ }
+%</zh>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*de>
+\keys_set_known:nn { sjtu / name }
+ {
+ contents = { Inhaltsverzeichnis } ,
+ listfigure = { Abbildungsverzeichnis } ,
+ listtable = { Tabellenverzeichnis } ,
+ figure = { Abbildung } ,
+ table = { Tabelle } ,
+ abstract = { Zusammenfassung } ,
+ index = { Index } ,
+ appendix = { Anhang } ,
+ proof = { Beweis } ,
+ bib = { Literaturverzeichnis } ,
+ part = { Teil } ,
+ chapter = { Kapitel } ,
+ figure* = { Figure } ,
+ table* = { Table } ,
+ algorithm = { Algorithmus } ,
+ listalgorithm = { Algorithmenverzeichnis } ,
+ abbr = { Abkürzungsverzeichnis } ,
+ nom = { Symbolverzeichnis } ,
+ ack = { Danksagungen } ,
+ resume = { Lebenslauf } ,
+ digest = { Kurzfassung } ,
+ achv = { Forschungsleistungen }
+ }
+%</de>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*ja>
+\keys_set_known:nn { sjtu / name }
+ {
+ contents = { 目 \protect \quad 次 } ,
+ listfigure = { 図目次 } ,
+ listtable = { 表目次 } ,
+ figure = { 図 } ,
+ table = { 表 } ,
+ abstract = { 概 \protect \quad 要 } ,
+ index = { 索 \protect \quad 引 } ,
+ appendix = { 付録 } ,
+ proof = { 证明 } ,
+ bib = { 参考文献 } ,
+ figure* = { Figure } ,
+ table* = { Table } ,
+ algorithm = { アルゴリズム } ,
+ listalgorithm = { アルゴリズム目次 } ,
+ abbr = { 略語表 } ,
+ nom = { 記号表 } ,
+ ack = { 謝 \protect \quad 辞 } ,
+ resume = { 履歴書 } ,
+ digest = { 要 \protect \quad 約 } ,
+ achv = { 研究業績書 }
+ }
+%</ja>
+%</scheme>
+% \end{macrocode}
+%
+% 载入名称配置。
+% \begin{macrocode}
+%<*class>
+%<*thesis>
+\clist_map_inline:Nn \g_@@_lang_clist
+ { \file_input:n { sjtu-name-thesis- #1 .def } }
+\clist_map_inline:nn
+ { title_page, declaration, abstract }
+ { \@@_define_name:nv {#1} { c_@@_name_ #1 _ \g_@@_lang_tl _tl } }
+%</thesis>
+%<!thesis>\file_input:n { sjtu-name-generic- \g_@@_lang_tl .def }
+% \end{macrocode}
+%
+% \subsection{页面设置}
+%
+% 利用 \pkg{geometry} 宏包设置页面边距以及页眉高度。
+% \begin{macrocode}
+\geometry
+ {
+ top = 3.5 cm,
+ bottom = 4.0 cm,
+ left = 2.5 cm,
+ right = 2.5 cm,
+%<thesis> bindingoffset = 0.5 cm,
+ headheight = 1.5 cm,
+ headsep = 0.5 cm,
+ footskip = 1.0 cm
+ }
+% \end{macrocode}
+%
+% \changes{v2.0.3}{2023/09/24}{学位论文页面纵向顶部对齐。}
+% 学位论文页面纵向顶部对齐。
+% \begin{macrocode}
+%<*thesis>
+\AtEndOfClass { \raggedbottom }
+%</thesis>
+% \end{macrocode}
+%
+% \subsection{页眉页脚}
+%
+% \pkg{ctex} 宏包使用 \opt{heading} 选项后,会把页面格式设置为 |headings|。
+% 因此必须在 \pkg{ctex} 调用之后重新设置 \tn{pagestyle} 为 |fancy|。
+% \begin{macrocode}
+\pagestyle { fancy }
+% \end{macrocode}
+%
+% 清除所有页眉页脚。
+% \begin{macrocode}
+\fancyhf { }
+% \end{macrocode}
+%
+% \begin{macro}{style/header-font,style/footer-font}
+% 设置页眉页脚字体。
+% \begin{macrocode}
+\keys_define:nn { sjtu / style }
+ {
+ header-font .tl_set:N = \l_@@_style_header_font_tl ,
+%<thesis> header-font .initial:n = \zihao { -5 } \setbaselineskip { 12 bp } ,
+%<!thesis> header-font .initial:n = \zihao { -5 } \sffamily ,
+ footer-font .tl_set:N = \l_@@_style_footer_font_tl ,
+%<thesis> footer-font .initial:n = \zihao { -5 } \setbaselineskip { 12 bp }
+%<!thesis> footer-font .initial:n = \zihao { -5 }
+ }
+\fancyheadinit { \l_@@_style_header_font_tl }
+\fancyfootinit { \l_@@_style_footer_font_tl }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{style/header-uppercase}
+% \begin{macro}[int]{\@@_nouppercase:n}
+% 页眉西文是否大写。
+% \begin{macrocode}
+\keys_define:nn { sjtu / style }
+ {
+ header-uppercase .choice: ,
+ header-uppercase / true .code:n =
+ { \cs_set_eq:NN \@@_nouppercase:n \use:n } ,
+ header-uppercase / false .code:n =
+ { \cs_set:Nn \@@_nouppercase:n { \nouppercase {##1} } } ,
+ header-uppercase .default:n = { true } ,
+ header-uppercase .initial:n = { false }
+ }
+\cs_generate_variant:Nn \@@_nouppercase:n { V }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{style/page-number}
+% \begin{macro}[int]{\@@_page:n}
+% 页脚页码格式。
+% \begin{macrocode}
+\cs_new:Nn \@@_thepage: { \thepage }
+\keys_define:nn { sjtu / style }
+ {
+ page-number .cs_set:Np = \@@_page:n #1 ,
+ page-number .initial:n = { {#1} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% 设置页眉内容。
+% \begin{macrocode}
+\tl_set:Nn \l_@@_header_tl
+ {
+%<*thesis>
+ {
+ \@@_set_cjk_default_zh: \normalfont
+ \l_@@_info_subject_zh_tl
+ }
+%</thesis>
+%<*!thesis>
+ \includegraphics [ height = 1.2 cm ]
+ { sjtu-vi-logo-small-red.pdf }
+%</!thesis>
+ }
+%<thesis>\tl_set:Nn \l_@@_leftmark_tl { \leftmark }
+%<!thesis>\tl_set:Nn \l_@@_leftmark_tl { \l_@@_info_subject_tl }
+\tl_set:Nn \l_@@_rightmark_tl { \leftmark }
+% \end{macrocode}
+%
+% 设置页眉页脚。
+% \begin{macrocode}
+\bool_if:NTF \g_@@_twoside_bool
+ {
+ \fancyhead [ LO, RE ] { \l_@@_header_tl }
+ \fancyhead [ LE ] { \@@_nouppercase:V \l_@@_leftmark_tl }
+ \fancyhead [ RO ] { \@@_nouppercase:V \l_@@_rightmark_tl }
+ }
+ {
+ \fancyhead [ L ] { \l_@@_header_tl }
+ \fancyhead [ R ] { \@@_nouppercase:V \l_@@_rightmark_tl }
+ }
+\fancyfoot [ C ] { \@@_page:n { \@@_thepage: } }
+% \end{macrocode}
+%
+% \begin{macro}{\headrule}
+% \cls{sjtuthesis} 的页眉线。
+% \begin{macrocode}
+%<*thesis>
+\cs_set:Npn \headrule
+ {
+ \hrule height 2.25 pt width \headwidth
+ \skip_vertical:n { 0.75 pt }
+ \hrule height 0.75 pt width \headwidth
+ \skip_vertical:n { -3.75 pt }
+ }
+%</thesis>
+% \end{macrocode}
+% \end{macro}
+%
+% 重定义 |plain| 样式。
+% \begin{macrocode}
+%<*!thesis>
+\bool_if:NTF \g_@@_twoside_bool
+ {
+ \fancypagestyle { plain }
+ {
+ \fancyhead [ LE, RO ] { }
+ \tl_set:Nn \headrulewidth { 0 pt }
+ }
+ }
+ {
+ \fancypagestyle { plain }
+ {
+ \fancyhead [ R ] { }
+ \tl_set:Nn \headrulewidth { 0 pt }
+ }
+ }
+%</!thesis>
+% \end{macrocode}
+%
+% |SJTU@null| 样式,不对当前页面样式做任何修改。
+% \begin{macrocode}
+\cs_new_eq:NN \ps@SJTU@null \prg_do_nothing:
+% \end{macrocode}
+%
+% \begin{macro}{\cleardoublepage}
+% 空白页清空页眉页脚。
+% \begin{macrocode}
+\RenewDocumentCommand \cleardoublepage { }
+ {
+ \clearpage
+ \bool_if:NT \g_@@_twoside_bool
+ {
+ \int_if_odd:nF \c@page
+ { \hbox:n { } \thispagestyle { empty } \newpage }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{页码设置}
+%
+% 文档初始页码编码设置。
+% \begin{macrocode}
+%<thesis>\pagenumbering { Alph }
+% \end{macrocode}
+%
+% \begin{macro}{\frontmatter}
+% 前置部分使用大写罗马数字编码。
+% \begin{macrocode}
+%<*thesis>
+\RenewDocumentCommand \frontmatter { }
+ {
+ \cleardoublepage
+ \@mainmatterfalse
+ \pagenumbering { Roman }
+ }
+%</thesis>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{章节标题结构}
+%
+% 设置章节标题样式。
+% \begin{macrocode}
+%<*!article>
+\ctex_set:nn { chapter }
+ {
+ pagestyle = SJTU@null ,
+ fixskip = true ,
+%<*thesis>
+ beforeskip = 27 bp ,
+ afterskip = 27 bp ,
+ format = \zihao { 3 } \setbaselineskip{ 20 bp } \bfseries
+ \CJKsffamily \centering ,
+%</thesis>
+%<*report>
+ beforeskip = 30 pt ,
+ afterskip = 24 pt ,
+ format = \Large \bfseries \CJKsffamily \centering ,
+%</report>
+ nameformat = ,
+ titleformat = ,
+ lofskip = \c_zero_skip ,
+ lotskip = \c_zero_skip ,
+ aftername = \quad
+ }
+%</!article>
+%</class>
+%<*scheme&(zh|ja)>
+\keys_set_known:nn { ctex / chapter }
+ { name = { 第 \space , \space 章 } }
+%</scheme&(zh|ja)>
+%<*class>
+\ctex_set:nn { section }
+%<*thesis>
+ {
+ beforeskip = 24 bp ,
+ afterskip = 6 bp ,
+ format = \zihao { 4 } \setbaselineskip { 18 bp } \bfseries
+ \CJKsffamily
+ }
+%</thesis>
+%<!thesis> { format = \large \bfseries \CJKsffamily }
+\ctex_set:nn { subsection }
+%<*thesis>
+ {
+ beforeskip = 12 bp ,
+ afterskip = 6 bp ,
+ format = \zihao { -4 } \setbaselineskip { 16 bp } \bfseries
+ \CJKsffamily
+ }
+%</thesis>
+%<!thesis> { format = \normalsize \bfseries \CJKsffamily }
+\ctex_set:nn { subsubsection }
+%<*thesis>
+ {
+ beforeskip = 6 bp ,
+ afterskip = 6 bp ,
+ format = \zihao { -4 } \setbaselineskip { 16 bp } \normalfont
+ }
+%</thesis>
+%<!thesis> { format = \normalsize \normalfont }
+\ctex_set:n { secnumdepth = 3 }
+% \end{macrocode}
+%
+% \changes{v2.1}{2024/01/10}{新增 \opt{style/indent-first} 选项。}
+% \begin{macro}{style/indent-first}
+% 章节标题后首段是否缩进。
+% \begin{macrocode}
+\keys_define:nn { sjtu / style }
+ {
+ indent-first .choice: ,
+ indent-first .choices:nn =
+ { true, false }
+ {
+ \clist_map_inline:nn
+ {
+%<article> part,
+%<!article> chapter,
+ section, subsection, subsubsection,
+ paragraph, subparagraph
+ }
+ { \ctex_set:nn {####1} { afterindent = #1 } }
+ } ,
+ indent-first .default:n = { true } ,
+ indent-first .initial:n = { true }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\SJTU@head,\@@_head_aux_s:nn,\@@_head_aux_s:nx,
+% \@@_pdf_bookmark:nn,\@@_phantom_section:}
+% 定义一个灵活的章节标题命令专门处理不同的需求。
+% \begin{macrocode}
+\NewDocumentCommand \SJTU@head { s O{#3} m O{#2} }
+ {
+%<!article> \CTEX@chapter@break
+ \IfBooleanTF {#1}
+ { \tl_if_empty:nF {#4} { \@@_pdf_bookmark:nn { 0 } {#4} } }
+ {
+ \@@_phantom_section:
+%<!article> \addcontentsline { toc } { chapter } {#4}
+%<article> \addcontentsline { toc } { section } {#4}
+ }
+ \cs_set_eq:NN \@@_orig_ctex_gettitle:n \CTEX@gettitle
+ \cs_set:Npn \CTEX@gettitle ##1 { \@@_orig_ctex_gettitle:n {#2} }
+%<!article> \chapter* {#3}
+%<article> \section* {#3}
+ \cs_set_eq:NN \CTEX@gettitle \@@_orig_ctex_gettitle:n
+ \@mkboth { \MakeUppercase {#2} } { \MakeUppercase {#2} }
+ }
+%<*thesis>
+\cs_new:Npn \@@_head_aux_s:nn #1#2
+ { \SJTU@head* [#1] {#2} }
+\cs_generate_variant:Nn \@@_head_aux_s:nn { nx }
+%</thesis>
+\cs_new_eq:NN \@@_pdf_bookmark:nn \use_none:nn
+\cs_new_eq:NN \@@_phantom_section: \prg_do_nothing:
+%</class>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{段落}
+%
+% 设置全文首行缩进。
+% \begin{macrocode}
+%<*scheme>
+\ctex_if_autoindent_touched:F
+%<zh> { \ctex_set:n { autoindent = true } }
+%<en|de> { \ctex_set:n { autoindent = 1.5 em } }
+%<ja> { \ctex_set:n { autoindent = 1 } }
+% \end{macrocode}
+%
+% \begin{macro}{\verse,\quotation}
+% 修改诗歌和引用环境的缩进。
+% \begin{macrocode}
+%<zh|ja>\ctex_patch_cmd:Nnn \verse { -1.5em } { -2 \ccwd }
+%<zh|ja>\ctex_patch_cmd:Nnn \verse { 1.5em } { 2 \ccwd }
+\ctex_patch_cmd:Nnn \quotation { 1.5em } { \parindent }
+%</scheme>
+% \end{macrocode}
+% \end{macro}
+%
+% 使用 \pkg{enumitem} 调整默认列表环境的间距。
+% \begin{macrocode}
+%<*class>
+\setlist { nosep }
+% \end{macrocode}
+%
+% \subsection{数学公式}
+%
+% \changes{v2.1}{2023/11/30}{新增 \opt{style/equation-font} 选项。}
+% \begin{macro}{style/equation-font}
+% 设置行间数学公式的字体。
+% \begin{macrocode}
+\keys_define:nn { sjtu / style }
+ {
+ equation-font .tl_set:N = \SJTU@style@equation@font ,
+%<thesis> equation-font .initial:x = \exp_not:N \linespread { }
+%<thesis> \exp_not:N \zihao { \g_@@_zihao_tl }
+%<!thesis> equation-font .initial:V = \c_empty_tl
+ }
+\clist_map_inline:nn
+ {
+ array, matrix, pmatrix, bmatrix, Bmatrix, vmatrix, Vmatrix,
+ matrix*, pmatrix*, bmatrix*, Bmatrix*, vmatrix*, Vmatrix*,
+ cases, cases*, dcases, dcases*, rcases, rcases*, drcases, drcases*,
+ aligned, alignedat, gathered, multlined, lgathered, rgathered
+ }
+ { \AtBeginEnvironment {#1} { \SJTU@style@equation@font } }
+\clist_map_inline:nn
+ { \start@gather, \start@align, \start@multline }
+ {
+ \ctex_patch_cmd:Nnn #1
+ { \collect@body }
+ {
+ \SJTU@style@equation@font
+ \collect@body
+ }
+ }
+\ctex_patch_cmd:Nnn \gather@split
+ { \spread@equation }
+ {
+ \SJTU@style@equation@font
+ \spread@equation
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{浮动体}
+%
+% 下面这组命令使浮动对象的缺省值稍微宽松一点,从而防止幅度对象占据过多的
+% 文本页面,也可以防止在很大空白的浮动页上放置很小的图形。
+% \begin{macrocode}
+\tl_set:Nn \textfraction { 0.15 }
+\tl_set:Nn \topfraction { 0.85 }
+\tl_set:Nn \bottomfraction { 0.65 }
+\tl_set:Nn \floatpagefraction { 0.60 }
+% \end{macrocode}
+%
+% \begin{macro}{style/float-font}
+% 设置浮动体内的字体。
+% \begin{macrocode}
+\keys_define:nn { sjtu / style }
+ {
+ float-font .tl_set:N = \SJTU@style@float@font ,
+%<thesis> float-font .initial:n = \zihao { 5 } \setbaselineskip { 14 bp }
+%<!thesis> float-font .initial:n = \zihao { 5 }
+ }
+\ctex_patch_cmd:Nnn \@floatboxreset
+ { \normalsize } { \SJTU@style@float@font }
+% \end{macrocode}
+% \end{macro}
+%
+% \changes{v2.1}{2023/11/29}{更新题注格式。}
+% \begin{macro}{style/caption-font,style/subcaption-font}
+% 题注格式。
+% \begin{macrocode}
+\keys_define:nn { sjtu / style }
+ {
+% \end{macrocode}
+%
+% \pkg{bicaption} 中双语标题之间的间距受 \pkg{caption} 字体定义 \opt{normalsize}
+% 的影响,这里我们直接重定义 \opt{normalsize}。
+% \begin{macrocode}
+ caption-font .code:n =
+ { \DeclareCaptionFont { normalsize } {#1} } ,
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<thesis> caption-font .initial:n = \zihao { 5 } \setbaselineskip { 14 bp }
+%<thesis> \bfseries ,
+%<!thesis> caption-font .initial:n = \zihao { 5 } \bfseries ,
+ subcaption-font .code:n =
+ { \DeclareCaptionFont { SJTU@sub@font } {#1} } ,
+%<thesis> subcaption-font .initial:n = \zihao { 5 } \setbaselineskip { 14 bp }
+%<thesis> \normalfont
+%<!thesis> subcaption-font .initial:n = \zihao { 5 } \normalfont
+ }
+\captionsetup
+ {
+ bi-slc = off ,
+ labelsep = quad ,
+%<thesis> skip = 6 bp
+ }
+\captionsetup [ sub ]
+ {
+ bi-slc = on ,
+ font = SJTU@sub@font ,
+ format = hang
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% 双语题注。
+% \begin{macrocode}
+\DeclareCaptionOption { bi-second-names } [ ]
+ {
+ \tl_set:Nn \figurename { \SJTU@figurename@bi@second }
+ \tl_set:Nn \tablename { \SJTU@tablename@bi@second }
+ }
+\captionsetup [ bi-second ] { bi-second-names }
+% \end{macrocode}
+%
+% \changes{v2.1}{2023/12/02}{新增 \opt{style/num-sep}、
+% \opt{style/theorem-num-sep} 选项。}
+% \begin{macro}{style/num-sep,style/float-num-sep,
+% style/equation-num-sep,style/theorem-num-sep}
+% 图、表、公式以及定理编号中的分隔符。
+% \begin{macrocode}
+\keys_define:nn { sjtu / style }
+ {
+ num-sep .code:n =
+ {
+ \tl_set:Nn \SJTU@style@fl@num@sep {#1}
+ \tl_set:Nn \SJTU@style@eq@num@sep {#1}
+ \tl_set:Nn \@thmcountersep {#1}
+ } ,
+ num-sep .initial:n = { . } ,
+ float-num-sep .tl_set:N = \SJTU@style@fl@num@sep ,
+ equation-num-sep .tl_set:N = \SJTU@style@eq@num@sep ,
+ theorem-num-sep .tl_set:N = \@thmcountersep
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\SJTU@counterwithin}
+% \begin{macrocode}
+\NewDocumentCommand \SJTU@counterwithin
+ { s O{ \SJTU@style@fl@num@sep } O{ \arabic } m m }
+ {
+ \@ifbothcounters {#4} {#5}
+ {
+ \@addtoreset {#4} {#5}
+ \IfBooleanF {#1}
+ {
+ \cs_gset:cpo { the #4 }
+ { \cs:w the #5 \cs_end: #2 #3 {#4} }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% 定义图、表、公式的编号格式。
+% \begin{macrocode}
+%<*!article>
+\SJTU@counterwithin { figure } { chapter }
+\SJTU@counterwithin { table } { chapter }
+\SJTU@counterwithin [ \SJTU@style@eq@num@sep ] { equation } { chapter }
+%</!article>
+% \end{macrocode}
+%
+% \begin{macro}[int]{\l_@@_counter_without_chapter_clist}
+% 大摘要中不需要随章编号的各计数器。
+% \begin{macrocode}
+%<*thesis>
+\clist_set:Nn \l_@@_counter_without_chapter_clist
+ { section, figure, table, equation }
+%</thesis>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{脚注}
+%
+% \begin{macro}[int]{\@@_makefnmark_plain:,\@@_thefootnote_plain:,
+% \@@_thempfootnote_plain:}
+% 储存原始的脚注相关命令。
+% \begin{macrocode}
+\cs_set_eq:NN \@@_makefnmark_plain: \@makefnmark
+\cs_set_eq:NN \@@_thefootnote_plain: \thefootnote
+\cs_set_eq:NN \@@_thempfootnote_plain: \thempfootnote
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_footnote_number:N}
+% 通过 Unicode 码位调用带圈数字。
+% \begin{macrocode}
+\cs_new:Npn \@@_footnote_number:N #1
+ {
+ \int_compare:nNnTF {#1} < { 21 }
+ { \@@_unicode_char:n { \int_eval:n { "2460 - 1 + #1 } } }
+ {
+ \int_compare:nNnTF {#1} < { 36 }
+ { \@@_unicode_char:n { \int_eval:n { "3251 - 21 + #1 } } }
+ {
+ \int_compare:nNnTF {#1} < { 51 }
+ { \@@_unicode_char:n { \int_eval:n { "32B1 - 36 + #1 } } }
+ { \msg_warning:nn { sjtutex } { too-many-footnotes } }
+ }
+ }
+ }
+\msg_new:nnn { sjtutex } { too-many-footnotes }
+ { Too~ many~ footnotes. }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_makefnmark_circled:}
+% 重定义内部脚注文字命令,使用带圈数字编号时,脚注不使用上标。
+% 见 \url{https://www.zhihu.com/question/53030087}。
+% \begin{macrocode}
+\cs_new:Nn \@@_makefnmark_circled: { \hbox:n { \@thefnmark } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{style/fnmark-font}
+% 脚注编号字体。
+% \begin{macrocode}
+\keys_define:nn { sjtu / style }
+ {
+ fnmark-font .choice: ,
+ fnmark-font / haranoaji .code:n =
+ {
+ \@@_engine_case:nn
+ { \tl_set_eq:NN \l_@@_style_fnmark_font_tl \c_empty_tl }
+ {
+ \tl_set:Nn \l_@@_style_fnmark_font_tl
+ {
+ \CJKfontspec { HaranoAjiMincho }
+ [
+ Extension = .otf ,
+ UprightFont = *-Regular ,
+ BoldFont = *-Bold
+ ]
+ }
+ }
+ } ,
+ fnmark-font / unknown .tl_set:N = \l_@@_style_fnmark_font_tl ,
+ fnmark-font .initial:V = \c_empty_tl
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_thefootnote_circled:,\@@_thempfootnote_circled:}
+% 使用带圈数字编号脚注。
+% \begin{macrocode}
+\cs_new:Nn \@@_thefootnote_circled:
+ { { \l_@@_style_fnmark_font_tl \@@_footnote_number:N \c@footnote } }
+\cs_new:Nn \@@_thempfootnote_circled:
+ { { \l_@@_style_fnmark_font_tl \@@_footnote_number:N \c@mpfootnote } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{style/fnmark-style}
+% 脚注编号样式。
+% \begin{macrocode}
+\keys_define:nn { sjtu / style }
+ {
+ fnmark-style .choice: ,
+ fnmark-style / plain .code:n =
+ {
+ \cs_set_eq:NN \@@_makefnmark: \@@_makefnmark_plain:
+ \cs_set_eq:NN \thefootnote \@@_thefootnote_plain:
+ \cs_set_eq:NN \thempfootnote \@@_thempfootnote_plain:
+ } ,
+ fnmark-style / circled .code:n =
+ {
+ \cs_set_eq:NN \@@_makefnmark: \@@_makefnmark_circled:
+ \cs_set_eq:NN \thefootnote \@@_thefootnote_circled:
+ \cs_set_eq:NN \thempfootnote \@@_thempfootnote_circled:
+ }
+ }
+%</class>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%<*scheme>
+\keys_set:nn { sjtu / style }
+%<zh|ja> { fnmark-style = circled }
+%<en|de> { fnmark-style = plain }
+%</scheme>
+% \end{macrocode}
+%
+% 在导言末尾修改 \tn{@makefntext},支持使用 \pkg{footmisc} 修改脚注格式。
+% \begin{macrocode}
+%<*class>
+\ctex_at_end_preamble:n {
+ \cs_set_eq:NN \@@_orig_make_fntext:n \@makefntext
+ \cs_set:Npn \@makefntext #1
+ {
+ \group_begin:
+ \cs_set_eq:NN \@makefnmark \@@_makefnmark:
+ \@@_orig_make_fntext:n {#1}
+ \group_end:
+ }
+}
+% \end{macrocode}
+%
+% \subsection{信息录入}
+%
+% \changes{v2.0}{2022/12/17}{添加 \opt{display-date} 键。}
+% \changes{v2.0}{2022/12/23}{使用 \opt{assoc-supervisor} 键表示副导师,
+% 使用 \opt{co-supervisor} 键表示联合导师。}
+% \changes{v2.0}{2022/12/23}{添加 \opt{subject} 键。}
+% \changes{v2.0}{2023/03/17}{使用语言代码前缀区别不同语种的 \opt{sjtu/info} 键。}
+% \begin{macro}[int]{\@@_info_keys_define:n}
+% 定义 \cls{sjtuthesis} 不同语种 |sjtu/info| 键值类的辅助函数。
+% \begin{macrocode}
+%<*thesis>
+\cs_new:Npn \@@_info_keys_define:n #1
+ {
+ \clist_map_inline:nn
+ {
+ title, display_title, subject, author, date,
+ supervisor, assoc_supervisor, department,
+ co_supervisor, major, degree
+ }
+ { \tl_new:c { l_@@_info_ ##1 _ #1 _tl } }
+ \clist_map_inline:nn
+ { keywords, fund }
+ { \clist_new:c { l_@@_info_ ##1 _ #1 _clist } }
+ \keys_define:nn { sjtu }
+ { info / #1 .meta:nn = { sjtu / info / #1 } {##1} }
+ \keys_define:nn { sjtu / info }
+ { #1 .meta:nn = { sjtu / info / #1 } {##1} }
+ \keys_define:nn { sjtu / info / #1 }
+ {
+ title .code:n =
+ {
+ \tl_set:cn { l_@@_info_title_ #1 _tl } {##1}
+ \tl_if_empty:cT { l_@@_info_display_title_ #1 _tl }
+ { \tl_set:cn { l_@@_info_display_title_ #1 _tl } {##1} }
+ } ,
+ display-title .tl_set:c = l_@@_info_display_title_ #1 _tl ,
+ subject .tl_set:c = l_@@_info_subject_ #1 _tl ,
+ keywords .clist_set:c = l_@@_info_keywords_ #1 _clist ,
+ author .tl_set:c = l_@@_info_author_ #1 _tl ,
+ id .meta:nn = { sjtu / info } { id = {##1} } ,
+ supervisor .tl_set:c = l_@@_info_supervisor_ #1 _tl ,
+ assoc-supervisor .tl_set:c = l_@@_info_assoc_supervisor_ #1 _tl ,
+ co-supervisor .tl_set:c = l_@@_info_co_supervisor_ #1 _tl ,
+ degree .tl_set:c = l_@@_info_degree_ #1 _tl ,
+ department .tl_set:c = l_@@_info_department_ #1 _tl ,
+ major .tl_set:c = l_@@_info_major_ #1 _tl ,
+ fund .clist_set:c = l_@@_info_fund_ #1 _clist ,
+ date .meta:nn = { sjtu / info } { date = {##1} } ,
+ display-date .tl_set:c = l_@@_info_date_ #1 _tl ,
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_info_id_zh_tl}
+% 单独处理学号。
+% \begin{macrocode}
+\tl_new:N \l_@@_info_id_zh_tl
+\keys_define:nn { sjtu / info }
+ { id .tl_set:N = \l_@@_info_id_zh_tl }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_info_supervisors_clist}
+% 标题中需要显示的导师列表。
+% \begin{macrocode}
+\clist_set:Nn \l_@@_info_supervisors_clist { supervisor }
+% \end{macrocode}
+% \end{variable}
+%
+% 盲审模式下隐藏作者、导师姓名等信息。
+% \begin{macrocode}
+\ctex_at_end_preamble:n
+ {
+ \bool_if:NT \g_@@_review_bool
+ {
+ \clist_map_inline:Nn \g_@@_lang_clist
+ {
+ \clist_map_inline:nn
+ { author, supervisor, assoc_supervisor, co_supervisor }
+ { \tl_clear:c { l_@@_info_ ##1 _ #1 _tl } }
+ \clist_clear:c { l_@@_info_fund_ #1 _clist }
+ }
+ \tl_clear:N \l_@@_info_id_zh_tl
+ }
+ }
+%</thesis>
+%</class>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<lang&thesis&zh>\@@_info_keys_define:n { zh }
+%<lang&thesis&en>\@@_info_keys_define:n { en }
+%<lang&thesis&de>\@@_info_keys_define:n { de }
+%<lang&thesis&ja>\@@_info_keys_define:n { ja }
+% \end{macrocode}
+%
+% \begin{variable}{\l_@@_info_subject_tl,\l_@@_info_keywords_clist}
+% \begin{macrocode}
+%<*class&!thesis>
+\tl_new:N \l_@@_info_subject_tl
+\clist_new:N \l_@@_info_keywords_clist
+\keys_define:nn { sjtu / info }
+ {
+ title .tl_set:N = \@title ,
+ author .tl_set:N = \@author ,
+ display-date .tl_set:N = \@date ,
+ subject .tl_set:N = \l_@@_info_subject_tl ,
+ keywords .clist_set:N = \l_@@_info_keywords_clist ,
+ }
+%</class&!thesis>
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{多语言支持}
+%
+% \changes{v2.0.3}{2023/04/08}{更新学位论文初始英文主题。}
+% 初始化主题。
+% \begin{macrocode}
+%<*lang>
+%<*thesis>
+%<zh>\keys_define:nn { sjtu / info / zh }
+%<en>\keys_define:nn { sjtu / info / en }
+%<de>\keys_define:nn { sjtu / info / de }
+%<ja>\keys_define:nn { sjtu / info / ja }
+ {
+ subject .initial:x =
+ {
+%<*zh>
+ \exp_not:V \c_@@_name_univ_zh_tl
+ \exp_not:V \c_@@_name_degree_level_zh_tl
+ \exp_not:V \c_@@_name_thesis_zh_tl
+%</zh>
+%<*en>
+ A~ Dissertation~ Submitted~ to \exp_not:N \\
+ { \exp_not:V \c_@@_name_univ_en_tl }~ for~
+ the~ Degree~ of~ { \exp_not:V \c_@@_name_degree_level_en_tl }
+%</en>
+%<*de>
+ Eine~ Dissertation~ Eingereicht~ an \exp_not:N \\
+ der~ { \exp_not:V \c_@@_name_univ_de_tl }~ für~
+ { \exp_not:V \c_@@_name_degree_level_de_tl } titel
+%</de>
+%<*ja>
+ \exp_not:V \c_@@_name_univ_ja_tl
+ \exp_not:V \c_@@_name_degree_level_ja_tl
+ \exp_not:V \c_@@_name_thesis_ja_tl
+%</ja>
+ }
+ }
+%</thesis>
+% \end{macrocode}
+%
+% 将形如 |yyyy-mm-dd| 或 |yyyy-mm| 的 ISO 日期格式字符串转化为日期表示。
+%
+% \begin{macro}[int]{\@@_date_aux_zh:nnn,\@@_date_aux_zh:w,
+% \@@_date_aux_short_zh:nn,\@@_date_aux_short_zh:w}
+% 中文日期。
+% \begin{macrocode}
+%<*zh>
+\cs_new:Npn \@@_date_aux_zh:nnn #1#2#3
+ {
+ \int_to_arabic:n {#1} ~ { \exp_not:V \c_@@_name_year_zh_tl } ~
+ \int_to_arabic:n {#2} ~ { \exp_not:V \c_@@_name_month_zh_tl } ~
+ \int_to_arabic:n {#3} ~ { \exp_not:V \c_@@_name_day_zh_tl }
+ }
+\cs_new:Npn \@@_date_aux_zh:w #1-#2-#3 \q_stop
+ { \@@_date_aux_zh:nnn {#1} {#2} {#3} }
+\cs_new:Npn \@@_date_aux_short_zh:nn #1#2
+ {
+ \int_to_arabic:n {#1} ~ { \exp_not:V \c_@@_name_year_zh_tl } ~
+ \int_to_arabic:n {#2} ~ { \exp_not:V \c_@@_name_month_zh_tl }
+ }
+\cs_new:Npn \@@_date_aux_short_zh:w #1-#2 \q_stop
+ { \@@_date_aux_short_zh:nn {#1} {#2} }
+%</zh>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_ordinal_en:n}
+% 上标形式的序数词。
+% \begin{macrocode}
+%<*en>
+\cs_new:Npn \@@_ordinal_en:n #1
+ {
+ \int_to_arabic:n {#1}
+ \exp_not:N \textsuperscript
+ {
+ \int_case:nnF { \int_mod:nn {#1} { 100 } }
+ {
+ { 11 } { th }
+ { 12 } { th }
+ { 13 } { th }
+ }
+ {
+ \int_case:nnF { \int_mod:nn {#1} { 10 } }
+ {
+ { 1 } { st }
+ { 2 } { nd }
+ { 3 } { rd }
+ }
+ { th }
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_date_aux_en:nnn,\@@_date_aux_en:w,
+% \@@_date_aux_short_en:nn,\@@_date_aux_short_en:w}
+% 英文日期。
+% \begin{macrocode}
+\cs_new:Npn \@@_date_aux_en:nnn #1#2#3
+ {
+ \clist_item:Nn \c_@@_name_month_en_clist {#2} ~
+ \@@_ordinal_en:n {#3} ,~
+ \int_to_arabic:n {#1}
+ }
+\cs_new:Npn \@@_date_aux_en:w #1-#2-#3 \q_stop
+ { \@@_date_aux_en:nnn {#1} {#2} {#3} }
+\cs_new:Npn \@@_date_aux_short_en:nn #1#2
+ {
+ \clist_item:Nn \c_@@_name_month_en_clist {#2} ,~
+ \int_to_arabic:n {#1}
+ }
+\cs_new:Npn \@@_date_aux_short_en:w #1-#2 \q_stop
+ { \@@_date_aux_short_en:nn {#1} {#2} }
+%</en>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_date_aux_de:nnn,\@@_date_aux_de:w,
+% \@@_date_aux_short_de:nn,\@@_date_aux_short_de:w}
+% 德文日期。
+% \begin{macrocode}
+%<*de>
+\cs_new:Npn \@@_date_aux_de:nnn #1#2#3
+ {
+ \clist_item:Nn \c_@@_name_month_de_clist {#2} ~
+ {#3} ,~ \int_to_arabic:n {#1}
+ }
+\cs_new:Npn \@@_date_aux_de:w #1-#2-#3 \q_stop
+ { \@@_date_aux_de:nnn {#1} {#2} {#3} }
+\cs_new:Npn \@@_date_aux_short_de:nn #1#2
+ {
+ \clist_item:Nn \c_@@_name_month_de_clist {#2} ,~
+ \int_to_arabic:n {#1}
+ }
+\cs_new:Npn \@@_date_aux_short_de:w #1-#2 \q_stop
+ { \@@_date_aux_short_de:nn {#1} {#2} }
+%</de>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_date_aux_ja:nnn,\@@_date_aux_ja:w,
+% \@@_date_aux_short_ja:nn,\@@_date_aux_short_ja:w}
+% 日文日期。
+% \begin{macrocode}
+%<*ja>
+\cs_new:Npn \@@_date_aux_ja:nnn #1#2#3
+ {
+ \int_to_arabic:n {#1} ~ { \exp_not:V \c_@@_name_year_ja_tl } ~
+ \int_to_arabic:n {#2} ~ { \exp_not:V \c_@@_name_month_ja_tl } ~
+ \int_to_arabic:n {#3} ~ { \exp_not:V \c_@@_name_day_ja_tl }
+ }
+\cs_new:Npn \@@_date_aux_ja:w #1-#2-#3 \q_stop
+ { \@@_date_aux_ja:nnn {#1} {#2} {#3} }
+\cs_new:Npn \@@_date_aux_short_ja:nn #1#2
+ {
+ \int_to_arabic:n {#1} ~ { \exp_not:V \c_@@_name_year_ja_tl } ~
+ \int_to_arabic:n {#2} ~ { \exp_not:V \c_@@_name_month_ja_tl }
+ }
+\cs_new:Npn \@@_date_aux_short_ja:w #1-#2 \q_stop
+ { \@@_date_aux_short_ja:nn {#1} {#2} }
+%</ja>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_set_language_zh:,\@@_set_language_en:,
+% \@@_set_language_de:,\@@_set_language_ja:,
+% \@@_set_cjk_default_zh:,\@@_set_cjk_default_ja:}
+% 设置语言格式辅助命令
+% \begin{macrocode}
+%<*zh>
+\cs_new:Nn \@@_set_cjk_default_zh:
+ {
+ \tl_set:Nn \CJKrmdefault { zhsong }
+ \tl_set:Nn \CJKsfdefault { zhhei }
+ \tl_set:Nn \CJKttdefault { zhfs }
+ }
+\cs_new_protected:Nn \@@_set_language_zh:
+ {
+ \tl_set:Nn \languagename { chinese }
+ \ctex_set:n { autoindent = true }
+ \@@_set_cjk_default_zh:
+ \normalfont
+ }
+%</zh>
+%<*en|de>
+%<en>\cs_new_protected:Nn \@@_set_language_en:
+%<de>\cs_new_protected:Nn \@@_set_language_de:
+ {
+%<en> \tl_set:Nn \languagename { english }
+%<de> \tl_set:Nn \languagename { ngerman }
+ \ctex_set:n { autoindent = 1.5 em }
+ \normalfont
+ }
+%</en|de>
+%<*ja>
+\cs_new:Nn \@@_set_cjk_default_ja:
+ {
+ \tl_set:Nn \CJKrmdefault { jamin }
+ \tl_set:Nn \CJKsfdefault { jagoth }
+ \tl_set:Nn \CJKttdefault { jagoth }
+ }
+\cs_new_protected:Nn \@@_set_language_ja:
+ {
+ \tl_set:Nn \languagename { japanese }
+ \ctex_set:n { autoindent = 1 }
+ \@@_set_cjk_default_ja:
+ \normalfont
+ }
+%</ja>
+% \end{macrocode}
+% \end{macro}
+%
+% 标题页页面样式,页脚添加资助基金信息。
+% \begin{macrocode}
+%<*thesis>
+%<zh>\cs_new:Npn \ps@SJTU@fund@zh
+%<en>\cs_new:Npn \ps@SJTU@fund@en
+%<de>\cs_new:Npn \ps@SJTU@fund@de
+%<ja>\cs_new:Npn \ps@SJTU@fund@ja
+ {
+ \ps@empty
+ \cs_set:Npn \@oddfoot
+ {
+ \minipage [ t ] { \textwidth }
+ \centering \zihao { - 5 }
+%<zh> \clist_use:Nn \l_@@_info_fund_zh_clist { \par }
+%<en> \clist_use:Nn \l_@@_info_fund_en_clist { \par }
+%<de> \clist_use:Nn \l_@@_info_fund_de_clist { \par }
+%<ja> \clist_use:Nn \l_@@_info_fund_ja_clist { \par }
+ \endminipage
+ }
+ \cs_set_eq:NN \@evenfoot \@oddfoot
+ }
+%</thesis>
+%</lang>
+% \end{macrocode}
+%
+% 初始化语言名称。
+% \begin{macrocode}
+%<*scheme>
+%<zh>\tl_set:Nn \languagename { chinese }
+%<en>\tl_set:Nn \languagename { english }
+%<de>\tl_set:Nn \languagename { ngerman }
+%<ja>\tl_set:Nn \languagename { japanese }
+%</scheme>
+% \end{macrocode}
+%
+% 载入语言配置。
+% \begin{macrocode}
+%<*class>
+%<thesis>\clist_map_inline:Nn \g_@@_lang_clist
+%<thesis> { \file_input:n { sjtu-lang-thesis- #1 .def } }
+%<!thesis>\file_input:n { sjtu-lang-generic- \g_@@_lang_tl .def }
+\file_input:n { sjtu-scheme- \g_@@_lang_tl .def }
+% \end{macrocode}
+%
+% \begin{macro}{info/date}
+% 初始化日期。
+% \begin{macrocode}
+\keys_define:nn { sjtu / info }
+ {
+ date .code:n =
+ {
+ \regex_match:neTF { \d+-\d+-\d+ } {#1}
+ {
+%<*thesis>
+ \clist_map_inline:Nn \g_@@_lang_clist
+ {
+ \tl_set:cx { l_@@_info_date_ ##1 _tl }
+ { \exp_last_unbraced:ce { @@_date_aux_ ##1 :w } #1 \q_stop }
+ }
+%</thesis>
+%<*!thesis>
+ \tl_set:Nx \@date
+ {
+ \exp_last_unbraced:ce
+ { @@_date_aux_ \g_@@_lang_tl :w } #1 \q_stop
+ }
+%</!thesis>
+ }
+ {
+ \regex_match:neT { \d+-\d+ } {#1}
+ {
+%<*thesis>
+ \clist_map_inline:Nn \g_@@_lang_clist
+ {
+ \tl_set:cx { l_@@_info_date_ ##1 _tl }
+ { \exp_last_unbraced:ce { @@_date_aux_short_ ##1 :w } #1 \q_stop }
+ }
+%</thesis>
+%<*!thesis>
+ \tl_set:Nx \@date
+ {
+ \exp_last_unbraced:ce
+ { @@_date_aux_short_ \g_@@_lang_tl :w } #1 \q_stop
+ }
+%</!thesis>
+ }
+ }
+ } ,
+ date .initial:x =
+ {
+ \int_to_arabic:n { \c_sys_year_int } -
+ \int_to_arabic:n { \c_sys_month_int } -
+ \int_to_arabic:n { \c_sys_day_int }
+ }
+ }
+%<thesis>\tl_set:Nv \today { l_@@_info_date_ \g_@@_lang_tl _tl }
+%<!thesis>\tl_set:NV \today \@date
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{标题页}
+%
+% \subsubsection{定义内部函数}
+%
+% 汉字分散对齐的环境。
+% \begin{macrocode}
+%<*thesis>
+\@@_engine_case:nnn
+ {
+ \NewDocumentEnvironment { SJTU@CJK@FTS } { m b }
+ {
+ \mode_leave_vertical:
+ \bool_set_false:N \l_@@_tmp_bool
+ \cs_set_eq:NN \SJTU@CJK@FTS@Symbol \CJKsymbol
+ \cs_set:Npn \CJKsymbol ##1
+ {
+ \bool_if:NTF \l_@@_tmp_bool
+ { \hfil \SJTU@CJK@FTS@Symbol { ##1 } }
+ {
+ \SJTU@CJK@FTS@Symbol { ##1 }
+ \bool_set_true:N \l_@@_tmp_bool
+ }
+ }
+ \hbox_to_wd:nn {#1} {#2}
+ } { }
+ }
+ {
+ \NewDocumentEnvironment { SJTU@CJK@FTS } { m b }
+ {
+ \mode_leave_vertical:
+ \cs_set:Npn \CJKglue
+ { \skip_horizontal:n { \c_zero_dim plus 1 filll } }
+ \hbox_to_wd:nn {#1} {#2}
+ } { }
+ }
+ {
+ \NewDocumentEnvironment { SJTU@CJK@FTS } { m b }
+ {
+ \mode_leave_vertical:
+ \ltjsetparameter { kanjiskip = { \c_zero_dim plus 1 filll } }
+ \hbox_to_wd:nn {#1} {#2}
+ } { }
+ }
+% \end{macrocode}
+%
+% 汉字分散对齐的表格列说明符。
+% \begin{macrocode}
+\newcolumntype { \SJTU@CT@D } [ 1 ]
+ { >{ \begin { SJTU@CJK@FTS } {#1} } c <{ \end { SJTU@CJK@FTS } } }
+% \end{macrocode}
+%
+% \changes{v2.1}{2023/11/30}{标题页信息栏改用表格实现。}
+% \begin{macro}[int]{\@@_title_page_info_i:nnn,\@@_title_page_info_i:nxx,
+% \@@_title_page_info_ii:n}
+% 信息输出。
+% \begin{macrocode}
+\cs_new:Npn \@@_title_page_info_i:nnn #1#2#3
+ {
+ \clist_clear:N \l_@@_tmp_clist
+ \clist_map_inline:nn {#3}
+ {
+ \clist_put_right:Nx \l_@@_tmp_clist
+ {
+ \exp_not:o { \cs:w c_@@_name_ ##1 _ #1 _tl \cs_end: }
+ &
+ \exp_not:o { \cs:w l_@@_info_ ##1 _ #1 _tl \cs_end: }
+ }
+ }
+ \group_begin:
+ \tl_set:Nn \arraystretch { 1 }
+ \tabular {#2}
+ \clist_use:Nn \l_@@_tmp_clist { \\ }
+ \endtabular
+ \group_end:
+ }
+\cs_new:Npn \@@_title_page_info_ii:n #1
+ {
+ \tl_use:c { l_@@_info_department_ #1 _tl }
+ \skip_vertical:N \c_zero_skip
+ \tl_use:c { c_@@_name_univ_ #1 _tl }
+ \skip_vertical:N \c_zero_skip
+ \tl_use:c { c_@@_name_address_ #1 _tl }
+ \skip_vertical:N \c_zero_skip
+ \tl_use:c { l_@@_info_date_ #1 _tl }
+ }
+\cs_generate_variant:Nn \@@_title_page_info_i:nnn { nxx }
+%</thesis>
+%</class>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{构建标题页}
+%
+% \changes{v2.0}{2022/12/13}{启用新版封面。}
+% \changes{v2.0.2}{2023/04/01}{标题页日期底部增加空白。}
+% \begin{macrocode}
+%<*lang>
+%<*thesis>
+%<*zh>
+\clist_map_inline:nn
+ {
+ { logo }
+ {
+ content =
+ {
+ \includegraphics [ width = 3 cm ]
+ { sjtu-vi-badge-red.pdf }
+ }
+ },
+ { subject }
+ {
+ format = \zihao { -2 } \setbaselineskip { 30 bp } ,
+ content = \l_@@_info_subject_zh_tl ,
+ bottom-skip = \c_zero_dim plus 1 fill
+ },
+ { title }
+ {
+ format = \zihao { 2 } \setbaselineskip { 36 bp } \bfseries ,
+ content = \l_@@_info_display_title_zh_tl ,
+ bottom-skip = 30 bp plus 1 fill
+ },
+ { info }
+ {
+ format = \zihao { 4 } \setbaselineskip { 30 bp } \heiti ,
+ content =
+ {
+ \@@_title_page_info_i:nxx { zh }
+ {
+ \exp_not:N \SJTU@CT@D { 5 em }
+ @ { \exp_not:V \c_@@_name_info_sep_zh_tl }
+ >{ \exp_not:N \normalfont } l
+ }
+ {
+ author,
+ id,
+ \l_@@_info_supervisors_clist ,
+ department,
+ major,
+ \int_compare:nNnF { \g_@@_thesis_type_int } = { 1 }
+ { degree }
+ }
+ } ,
+ bottom-skip = 30 bp
+ },
+ { date }
+ {
+ format = \zihao { 4 } \setbaselineskip { 30 bp } \bfseries ,
+ content = \l_@@_info_date_zh_tl ,
+ }
+ }
+ {
+ \@@_declare_component:nnn { title / zh } #1
+ }
+\@@_declare_page:nn { title / zh }
+ {
+ bookmark = true ,
+ bookmark-text = \c_@@_name_title_page_tl ,
+ style = SJTU@fund@zh ,
+ format = \linespread { } \@@_set_language_zh: ,
+ prefix = title / zh ,
+ components = { logo, subject, title, info, date }
+ }
+%</zh>
+%<*en|de|ja>
+\clist_map_inline:nn
+ {
+ { subject }
+ {
+ format = \zihao { 4 } \setbaselineskip { 24 bp } \bfseries ,
+%<en> content = \l_@@_info_subject_en_tl ,
+%<de> content = \l_@@_info_subject_de_tl ,
+%<ja> content = \l_@@_info_subject_ja_tl ,
+ bottom-skip = \c_zero_dim plus 1 fill
+ },
+ { title }
+ {
+ format = \zihao { -2 } \setbaselineskip { 30 bp } \bfseries ,
+%<en> content = \MakeUppercase \l_@@_info_display_title_en_tl ,
+%<de> content = \MakeUppercase \l_@@_info_display_title_de_tl ,
+%<ja> content = \l_@@_info_display_title_ja_tl ,
+ bottom-skip = \c_zero_dim plus 1 fill
+ },
+ { info }
+ {
+ format = \zihao { 3 } \setbaselineskip { 30 bp } \bfseries ,
+ content =
+ {
+%<en> \@@_title_page_info_i:nxx { en }
+%<de> \@@_title_page_info_i:nxx { de }
+%<ja> \@@_title_page_info_i:nxx { ja }
+ {
+%<en> r @ { \exp_not:V \c_@@_name_info_sep_en_tl }
+%<de> r @ { \exp_not:V \c_@@_name_info_sep_de_tl }
+%<ja> r @ { \exp_not:V \c_@@_name_info_sep_ja_tl }
+ >{ \exp_not:N \normalfont } l
+ }
+ { author, \l_@@_info_supervisors_clist }
+ } ,
+ bottom-skip = 30 bp plus 1 fill
+ },
+ { date }
+ {
+ format = \zihao { 3 } \setbaselineskip { 30 bp } ,
+ content =
+%<en> { \@@_title_page_info_ii:n { en } } ,
+%<de> { \@@_title_page_info_ii:n { de } } ,
+%<ja> { \@@_title_page_info_ii:n { ja } } ,
+ },
+ }
+ {
+%<en> \@@_declare_component:nnn { title / en } #1
+%<de> \@@_declare_component:nnn { title / de } #1
+%<ja> \@@_declare_component:nnn { title / ja } #1
+ }
+%<*en>
+\@@_declare_page:nn { title / en }
+ {
+ style = SJTU@fund@en ,
+ format = \linespread { } \@@_set_language_en: ,
+ prefix = title / en ,
+ components = { subject, title, info, date }
+ }
+%</en>
+%<*de>
+\@@_declare_page:nn { title / de }
+ {
+ style = SJTU@fund@de ,
+ format = \linespread { } \@@_set_language_de: ,
+ prefix = title / de ,
+ components = { subject, title, info, date }
+ }
+%</de>
+%<*ja>
+\@@_declare_page:nn { title / ja }
+ {
+ style = SJTU@fund@ja ,
+ format = \linespread { } \@@_set_language_ja: ,
+ prefix = title / ja ,
+ components = { subject, title, info, date }
+ }
+%</ja>
+%</en|de|ja>
+%</thesis>
+%</lang>
+% \end{macrocode}
+%
+% \begin{macro}{\maketitle}
+% 生成标题页,输出前先确定需要显示的导师列表。
+% \begin{macrocode}
+%<*class>
+%<*thesis>
+\RenewDocumentCommand \maketitle { }
+ {
+ \clist_map_inline:nn
+ { assoc_supervisor, co_supervisor }
+ {
+ \tl_if_empty:cF { l_@@_info_ ##1 _zh_tl }
+ { \clist_put_right:Nn \l_@@_info_supervisors_clist {##1} }
+ }
+ \clist_map_inline:Nn \g_@@_lang_clist
+ { \UseInstance { sjtu } { title / ##1 } }
+ }
+%</thesis>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{原创性声明及使用授权书}
+%
+% \begin{macrocode}
+%<*thesis>
+\cs_new_protected:Npn \@@_signature:N #1
+ {
+ \parbox [ t ] { 12 em }
+ { #1 \c_@@_signature_text_zh_tl }
+ }
+\clist_map_inline:nn
+ {
+ { orig / title }
+ {
+ format = \zihao { 3 } \setbaselineskip { 30 bp }
+ \bfseries \heiti ,
+ content =
+ {
+ \c_@@_name_univ_zh_tl
+ \skip_vertical:N \c_zero_skip
+ \c_@@_name_thesis_zh_tl
+ \c_@@_name_orig_decl_zh_tl
+ } ,
+ bottom-skip = 12 bp
+ },
+ { orig / text }
+ {
+ format = \zihao { -4 } \setbaselineskip { 24 bp } ,
+ content = \c_@@_orig_decl_text_zh_tl ,
+ bottom-skip = 24 bp ,
+ align = normal
+ },
+ { orig / sign }
+ {
+ format = \zihao { 4 } \setbaselineskip { 30 bp } ,
+ content =
+ {
+ \@@_signature:N \c_@@_name_decl_author_zh_tl
+ \skip_horizontal:n { 4 em } \hbox:n { }
+ } ,
+ bottom-skip = \c_zero_dim plus 2 fill ,
+ align = right
+ },
+ { auth / title }
+ {
+ format = \zihao { 3 } \setbaselineskip { 30 bp }
+ \bfseries \heiti ,
+ content =
+ {
+ \c_@@_name_univ_zh_tl
+ \skip_vertical:N \c_zero_skip
+ \c_@@_name_thesis_zh_tl
+ \c_@@_name_auth_decl_zh_tl
+ } ,
+ bottom-skip = 12 bp
+ },
+ { auth / text }
+ {
+ format = \zihao { -4 } \setbaselineskip { 24 bp } ,
+ content = \c_@@_auth_decl_text_zh_tl ,
+ bottom-skip = 24 bp ,
+ align = normal
+ },
+ { auth / sign }
+ {
+ format = \zihao { 4 } \setbaselineskip { 30 bp } ,
+ content =
+ {
+ \@@_signature:N \c_@@_name_decl_author_zh_tl
+ \hfill
+ \@@_signature:N \c_@@_name_decl_supervisor_zh_tl
+ \skip_horizontal:n { 2 em } \hbox:n { }
+ } ,
+ bottom-skip = \c_zero_dim plus 1 fill ,
+ align = normal
+ }
+ }
+ {
+ \@@_declare_component:nnn { copyright } #1
+ }
+\@@_declare_page:nn { copyright }
+ {
+ bookmark = true ,
+ bookmark-text = \c_@@_name_declaration_tl ,
+ format = \linespread { } \@@_set_language_zh: ,
+ prefix = copyright ,
+ components =
+ {
+ orig / title, orig / text, orig / sign,
+ auth / title, auth / text, auth / sign
+ }
+ }
+\msg_new:nnn { sjtutex } { require-pdfpages }
+ {
+ Add~"\token_to_str:N \usepackage{pdfpages}"~ in~ your~ preamble \\
+ before~ inserting~ pages~ of~ external~ PDF.
+ }
+% \end{macrocode}
+%
+% \changes{v2.0}{2022/12/20}{不再自动载入 \pkg{pdfpages} 宏包。}
+% \begin{macro}{\copyrightpage}
+% \begin{macrocode}
+\NewDocumentCommand \copyrightpage { O{ } }
+ {
+ \bool_if:NF \g_@@_review_bool
+ {
+ \tl_if_blank:nTF {#1}
+ { \UseInstance { sjtu } { copyright } }
+ {
+ \cs_if_exist:NTF \includepdf
+ {
+ \bool_if:NTF \g_@@_openright_bool
+ { \cleardoublepage } { \clearpage }
+ \@@_pdf_bookmark:nn { 0 } { \c_@@_name_declaration_tl }
+ \includepdf {#1}
+ }
+ {
+ \msg_warning:nn { sjtutex } { require-pdfpages }
+ \UseInstance { sjtu } { copyright }
+ }
+ }
+ }
+ }
+%</thesis>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{摘要}
+%
+% \changes{v2.1}{2023/11/30}{新增 \opt{style/keywords-format} 选项。}
+% \begin{macro}{style/keywords-format}
+% 关键词排版样式。
+% \begin{macrocode}
+\keys_define:nn { sjtu / style }
+ {
+ keywords-format .choice: ,
+ keywords-format / plain .code:n =
+ { \cs_set:Nn \@@_keywords_format:n { \noindent { \bfseries ##1 } } } ,
+ keywords-format / hang .code:n =
+ { \cs_set:Nn \@@_keywords_format:n { \@hangfrom { \bfseries ##1 } } } ,
+ keywords-format .initial:n = { plain }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \changes{v2.0}{2023/03/17}{\env{abstract} 环境新增指定语言的可选参数。}
+% \changes{v2.1}{2023/11/29}{\env{abstract} 环境添加目录条目,
+% \env{abstract*} 环境对应修改为不添加目录条目。}
+% \begin{macro}{abstract,abstract*}
+% 学位论文摘要环境。
+% \begin{macrocode}
+%<*thesis>
+\DeclareDocumentEnvironment { abstract } { O{ zh } +b }
+ {
+ \@@_if_lang_valid:nTF {#1}
+ {
+ \use:c { @@_set_language_ #1 : }
+ \exp_args:Nv \SJTU@head { c_@@_name_abstract_ #1 _tl }
+ #2
+ \clist_if_empty:cF { l_@@_info_keywords_ #1 _clist }
+ {
+ \par \mode_leave_vertical: \par
+ \@@_keywords_format:n
+ {
+ \tl_use:c { c_@@_name_keywords_ #1 _tl }
+ \tl_use:c { c_@@_name_info_sep_ #1 _tl }
+ }
+ \clist_use:cv { l_@@_info_keywords_ #1 _clist }
+ { c_@@_name_item_sep_ #1 _tl }
+ \par
+ }
+ }
+ { \msg_error:nnn { sjtutex } { lang-validation } {#1} }
+ } { }
+\DeclareDocumentEnvironment { abstract* } { O{ zh } +b }
+ {
+ \@@_if_lang_valid:nTF {#1}
+ {
+ \use:c { @@_set_language_ #1 : }
+ \exp_args:NNv \SJTU@head* { c_@@_name_abstract_ #1 _tl }
+ #2
+ \clist_if_empty:cF { l_@@_info_keywords_ #1 _clist }
+ {
+ \par \mode_leave_vertical: \par
+ \@@_keywords_format:n
+ {
+ \tl_use:c { c_@@_name_keywords_ #1 _tl }
+ \tl_use:c { c_@@_name_info_sep_ #1 _tl }
+ }
+ \clist_use:cv { l_@@_info_keywords_ #1 _clist }
+ { c_@@_name_item_sep_ #1 _tl }
+ \par
+ }
+ }
+ { \msg_error:nnn { sjtutex } { lang-validation } {#1} }
+ } { }
+%</thesis>
+% \end{macrocode}
+%
+% 修复通用模板摘要段首缩进。
+% \begin{macrocode}
+%<*!thesis>
+\bool_if:NT \g_@@_titlepage_bool
+ { \@@_appto_cmd:Nn \abstract { \par } }
+% \end{macrocode}
+%
+% 通用模板摘要后添加关键词。
+% \begin{macrocode}
+\@@_preto_cmd:Nn \endabstract
+ {
+ \clist_if_empty:NF \l_@@_info_keywords_clist
+ {
+ \par \mode_leave_vertical: \par
+ \@@_keywords_format:n
+ {
+ \c_@@_name_keywords_tl
+ \c_@@_name_info_sep_tl
+ }
+ \clist_use:NV \l_@@_info_keywords_clist \c_@@_name_item_sep_tl
+ \par
+ }
+ }
+%</!thesis>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{目录}
+%
+% \changes{v2.1}{2023/11/29}{\tn{tableofcontents} 添加目录条目,
+% \tn{tableofcontents*} 对应修改为不添加目录条目。}
+% \begin{macro}{\tableofcontents,\tableofcontents*}
+% 目录。
+% \begin{macrocode}
+\DeclareDocumentCommand \tableofcontents { s }
+ {
+ \IfBooleanTF {#1}
+ { \SJTU@head* { \contentsname } }
+ { \SJTU@head { \contentsname } }
+ \group_begin:
+ \cs_set:Npn \makebox [##1][##2]##3 { \, ##3 }
+ \@starttoc { toc }
+ \group_end:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\SJTU@listof}
+% \begin{macro}{\listoffigures,\listoffigures*,\listoftables,\listoftables*}
+% 图表索引。
+% \begin{macrocode}
+\NewDocumentCommand \SJTU@listof { m m s }
+ {
+ \IfBooleanTF {#3}
+ { \SJTU@head* {#1} }
+ { \SJTU@head {#1} }
+ \group_begin:
+ \cs_set:Npn \makebox [##1][##2]##3 { \, ##3 }
+ \exp_args:Nv \@starttoc { ext@ #2 }
+ \group_end:
+ }
+\DeclareDocumentCommand \listoffigures { }
+ { \SJTU@listof { \listfigurename } { figure } }
+\DeclareDocumentCommand \listoftables { }
+ { \SJTU@listof { \listtablename } { table } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+\tl_set:Nn \cftdotsep { 0.5 }
+%<!article>\tl_set:Nn \cftchapleader { \bfseries \cftdotfill { \cftdotsep } }
+%<*thesis>
+\clist_map_inline:nn
+ {
+ { cft before chap skip } { 10 bp plus 1 pt } ,
+ { cft chap numwidth } { 3.5 em } ,
+ { cft sec indent } { 2 em } ,
+ { cft sec numwidth } { 1.5 em } ,
+ { cft subsec indent } { 4 em } ,
+ { cft subsec numwidth } { 2.3 em }
+ }
+ { \skip_set:cn #1 }
+%</thesis>
+% \end{macrocode}
+%
+% \changes{v2.0.1}{2023/03/31}{插图、表格和算法等索引不缩进。}
+% \changes{v2.0.1}{2023/03/31}{调整插图、表格和算法等索引编号宽度。}
+% \begin{macro}[int]{\@@_update_cft_presnum:nn}
+% \begin{variable}{\l_@@_cft_presnum_clist}
+% 图表清单标题前添加名称。
+% \begin{macrocode}
+\clist_set:Nn \l_@@_cft_presnum_clist
+ {
+ { fig } { \figurename } ,
+ { tab } { \tablename }
+ }
+\cs_new:Npn \@@_update_cft_presnum:nn #1#2
+ {
+ \tl_set:cn { cft #1 presnum } { #2 \c_space_tl }
+ \skip_zero:c { cft #1 indent }
+%<article> \skip_set:cn { cft #1 numwidth } { 1.8 em }
+%<!article> \skip_set:cn { cft #1 numwidth } { 2.8 em }
+ \@@_skip_add_to_wd:cv { cft #1 numwidth } { cft #1 presnum }
+ }
+\ctex_at_end_preamble:n
+ {
+ \clist_map_inline:Nn \l_@@_cft_presnum_clist
+ { \@@_update_cft_presnum:nn #1 }
+ }
+% \end{macrocode}
+% \end{variable}
+% \end{macro}
+%
+% \subsection{预定义环境}
+%
+% \begin{macro}{abbreviation,abbreviation*}
+% 缩略语对照表。
+% \begin{macrocode}
+%<*thesis>
+\NewDocumentEnvironment { abbreviation } { O{ \SJTU@abbrname } }
+ {
+ \chapter {#1}
+ \tl_clear:N \SJTU@style@float@font
+ } { }
+\NewDocumentEnvironment { abbreviation* } { O{ \SJTU@abbrname } }
+ {
+ \SJTU@head* {#1}
+ \tl_clear:N \SJTU@style@float@font
+ } { }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{nomenclature,nomenclature*}
+% 符号对照表。
+% \begin{macrocode}
+\NewDocumentEnvironment { nomenclature } { O{ \SJTU@nomname } }
+ {
+ \chapter {#1}
+ \tl_clear:N \SJTU@style@float@font
+ } { }
+\NewDocumentEnvironment { nomenclature* } { O{ \SJTU@nomname } }
+ {
+ \SJTU@head* {#1}
+ \tl_clear:N \SJTU@style@float@font
+ } { }
+% \end{macrocode}
+% \end{macro}
+%
+% \changes{v2.0}{2023/03/17}{移除 \env{summary} 环境。}
+%
+% \begin{macro}{acknowledgements}
+% 致谢,盲审模式下隐藏致谢。
+% \begin{macrocode}
+\NewDocumentEnvironment { acknowledgements } { O{ \SJTU@ackname } +b }
+ {
+ \bool_if:NF \g_@@_review_bool
+ {
+ \SJTU@head {#1}
+ #2
+ }
+ } { }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{achievements,bibliolist,bibliolist*}
+% 发表论文与学术成果。
+% \begin{macrocode}
+\newcounter { SJTU@bib }
+\NewDocumentEnvironment { @bibliolist } { m }
+ {
+ \cs_if_exist_use:N \bibfont
+ \list
+ {
+ \tl_if_blank:nTF {#1}
+ { \hfill }
+ { \@biblabel { \arabic{ SJTU@bib } } }
+ }
+ {
+ \tl_if_blank:nTF {#1}
+ {
+ \skip_if_exist:NTF \bibhang
+ { \dim_set_eq:NN \leftmargin \bibhang }
+ { \dim_set:Nn \leftmargin { 1 em } }
+ \dim_set:Nn \itemindent { - \leftmargin }
+ }
+ {
+ \@@_dim_set_to_wd:Nn \labelwidth { \@biblabel {#1} }
+ \dim_set_eq:NN \leftmargin \labelwidth
+ \dim_add:Nn \leftmargin { \labelsep }
+ }
+ \skip_if_exist:NTF \bibitemsep
+ {
+ \skip_set_eq:NN \itemsep \bibitemsep
+ \skip_if_exist:NT \bibparsep
+ { \skip_set_eq:NN \parsep \bibparsep }
+ }
+ {
+ \skip_if_exist:NT \bibsep
+ {
+ \skip_set_eq:NN \itemsep \bibsep
+ \skip_zero:N \parsep
+ }
+ }
+ \@nmbrlisttrue
+ \tl_set:Nn \@listctr { SJTU@bib }
+ \cs_set:Npn \p@SJTU@bib { }
+ \cs_set:Npn \theSJTU@bib { \arabic { SJTU@bib } }
+ }
+ \sloppy
+ \int_set:Nn \clubpenalty { 4000 }
+ \int_set_eq:NN \@clubpenalty \clubpenalty
+ \int_set:Nn \widowpenalty { 4000 }
+ \char_set_sfcode:nn { `\. } { 1000 }
+ }
+ {
+ \cs_set:Npn \@noitemerr
+ { \msg_warning:nnn { sjtutex } { empty-environment } { bibliolist } }
+ \endlist
+ }
+\msg_new:nnn { sjtutex } { empty-environment }
+ { Empty~ `#1'~ environment. }
+\bool_new:N \l_@@_achievements_bool
+\NewDocumentEnvironment { achievements } { O{ \SJTU@achvname } }
+ {
+ \SJTU@head {#1}
+ \setcounter { SJTU@bib } { 0 }
+ \bool_set_true:N \l_@@_achievements_bool
+ } { }
+\NewDocumentEnvironment { bibliolist } { m +b }
+ {
+ \bool_if:NF \l_@@_achievements_bool
+ {
+ \msg_error:nnnn { sjtutex } { environment-validation }
+ { bibliolist } { achievements }
+ }
+ \bool_if:NF \g_@@_review_bool
+ {
+ \cs_set:Npn \@noitemerr { }
+ \begin { @bibliolist } {#1}
+ #2
+ \end { @bibliolist }
+ }
+ } { }
+\NewDocumentEnvironment { bibliolist* } { m +b }
+ {
+ \bool_if:NF \l_@@_achievements_bool
+ {
+ \msg_error:nnnn { sjtutex } { environment-validation }
+ { bibliolist* } { achievements }
+ }
+ \bool_if:NT \g_@@_review_bool
+ {
+ \cs_set:Npn \@noitemerr { }
+ \begin { @bibliolist } {#1}
+ #2
+ \end { @bibliolist }
+ }
+ } { }
+\msg_new:nnn { sjtutex } { environment-validation }
+ { `#1'~ is~ only~ valid~ in~ `#2'~ environment. }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{resume}
+% 简历。
+% \begin{macrocode}
+\NewDocumentEnvironment { resume } { O{ \SJTU@resumename } +b }
+ {
+ \bool_if:NF \g_@@_review_bool
+ {
+ \SJTU@head {#1}
+ #2
+ }
+ } { }
+% \end{macrocode}
+% \end{macro}
+%
+% \changes{v2.0}{2023/03/17}{\env{digest} 环境新增指定语言的可选参数。}
+% \begin{macro}{digest}
+% 大摘要。
+% \begin{macrocode}
+\NewDocumentEnvironment { digest } { O{ en } +b }
+ {
+ \@@_if_lang_valid:nTF {#1}
+ {
+ \AtEndDocument
+ {
+ \use:c { @@_set_language_ #1 : }
+ \bool_if:NTF \g_@@_openright_bool
+ { \cleardoublepage } { \clearpage }
+ \pagenumbering { roman }
+ \cs_gset:Nn \@@_thepage: { \arabic { page } }
+ \cs_gset_eq:NN \addcontentsline \use_none:nnn
+ \clist_map_inline:Nn \l_@@_counter_without_chapter_clist
+ {
+ \counterwithout {##1} { chapter }
+ \setcounter {##1} { 0 }
+ }
+ \@@_head_aux_s:nx { \SJTU@digestname }
+ {
+ \exp_not:N \MakeUppercase
+ { \exp_not:v { l_@@_info_title_ #1 _tl } }
+ }
+ #2
+ }
+ }
+ { \msg_error:nnn { sjtutex } { lang-validation } {#1} }
+ } { }
+%</thesis>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{设置接口}
+%
+% \begin{macro}{\sjtusetup}
+% 用户设置接口。
+% \begin{macrocode}
+\NewDocumentCommand \sjtusetup { } { \keys_set:nn { sjtu } }
+% \end{macrocode}
+% \end{macro}
+%
+% \changes{v2.0}{2022/12/28}{重新制定 \opt{sjtu/style} 域中的接口。}
+% 定义元(meta)键值对。
+% \begin{macrocode}
+\keys_define:nn { sjtu }
+ {
+ style .meta:nn = { sjtu / style } {#1} ,
+ info .meta:nn = { sjtu / info } {#1} ,
+ name .meta:nn = { sjtu / name } {#1}
+ }
+% \end{macrocode}
+%
+% 兼容 \cls{sjtuthesis} 旧接口。
+% \begin{macrocode}
+%<*thesis>
+\keys_define:nn { sjtu / info }
+ {
+ title .meta:n = { zh / title = {#1} } ,
+ title* .meta:n = { en / title = {#1} } ,
+ display-title .meta:n = { zh / display-title = {#1} } ,
+ display-title* .meta:n = { en / display-title = {#1} } ,
+ subject .meta:n = { zh / subject = {#1} } ,
+ subject* .meta:n = { en / subject = {#1} } ,
+ keywords .meta:n = { zh / keywords = {#1} } ,
+ keywords* .meta:n = { en / keywords = {#1} } ,
+ author .meta:n = { zh / author = {#1} } ,
+ author* .meta:n = { en / author = {#1} } ,
+ supervisor .meta:n = { zh / supervisor = {#1} } ,
+ supervisor* .meta:n = { en / supervisor = {#1} } ,
+ assoc-supervisor .meta:n = { zh / assoc-supervisor = {#1} } ,
+ assoc-supervisor* .meta:n = { en / assoc-supervisor = {#1} } ,
+ co-supervisor .meta:n = { zh / co-supervisor = {#1} } ,
+ co-supervisor* .meta:n = { en / co-supervisor = {#1} } ,
+ degree .meta:n = { zh / degree = {#1} } ,
+ degree* .meta:n = { en / degree = {#1} } ,
+ department .meta:n = { zh / department = {#1} } ,
+ department* .meta:n = { en / department = {#1} } ,
+ major .meta:n = { zh / major = {#1} } ,
+ major* .meta:n = { en / major = {#1} } ,
+ fund .meta:n = { zh / fund = {#1} } ,
+ fund* .meta:n = { en / fund = {#1} } ,
+ display-date .meta:n = { zh / date = {#1} } ,
+ display-date* .meta:n = { en / date = {#1} }
+ }
+\keys_define:nn { sjtu / name }
+ {
+ abbreviation .meta:n = { abbr = {#1} } ,
+ nomenclature .meta:n = { nom = {#1} } ,
+ acknowledgements .meta:n = { ack = {#1} } ,
+ publications .meta:n = { achv = {#1} } ,
+ achievements .meta:n = { achv = {#1} }
+ }
+%</thesis>
+% \end{macrocode}
+%
+% \begin{macro}{\subject,\keywords}
+% 通用模板新接口。
+% \begin{macrocode}
+%<*!thesis>
+\NewDocumentCommand \subject { m }
+ { \keys_set:nn { sjtu / info } { subject = {#1} } }
+\NewDocumentCommand \keywords { m }
+ { \keys_set:nn { sjtu / info } { keywords = {#1} } }
+%</!thesis>
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{其他宏包的设置}
+%
+% \changes{v2.0.3}{2023/09/23}{移除 \pkg{listings} 宏包预设。}
+% 这些宏包并非格式要求,但是为了方便同学们使用,在这里进行简单设置。
+%
+% \subsubsection{\pkg{hyperref} 宏包}
+%
+% \begin{macrocode}
+\ctex_at_end_package:nn { hyperref }
+ {
+ \hypersetup
+ {
+ linktoc = all,
+ bookmarksdepth = 2,
+ bookmarksnumbered = true,
+ bookmarksopen = true,
+ bookmarksopenlevel = 1,
+ unicode = true,
+ psdextra = true,
+ breaklinks = true,
+ pdfdisplaydoctitle = true
+ }
+ \int_new:N \g_@@_bookmark_int
+ \cs_gset_protected:Npn \@@_pdf_bookmark:nn #1#2
+ {
+ \phantomsection
+ \int_gincr:N \g_@@_bookmark_int
+ \pdfbookmark [#1] {#2}
+ { sjtubookmark. \int_use:N \g_@@_bookmark_int }
+ }
+ \cs_gset_eq:NN \@@_phantom_section: \phantomsection
+ \pdfstringdefDisableCommands
+ {
+ \cs_set_eq:NN \\ \prg_do_nothing:
+ \cs_set_eq:NN \quad \c_empty_tl
+ \cs_set_eq:NN \qquad \c_empty_tl
+ \cs_set_eq:NN \hspace \use_none:n
+ }
+ \ctex_after_end_preamble:n
+ {
+ \hypersetup
+ {
+%<*thesis>
+ pdftitle = \l_@@_info_title_zh_tl ,
+ pdfauthor = \l_@@_info_author_zh_tl ,
+ pdfsubject = \l_@@_info_subject_zh_tl ,
+ pdfkeywords = \l_@@_info_keywords_zh_clist
+%</thesis>
+%<*!thesis>
+ pdftitle = \@title ,
+ pdfauthor = \@author ,
+ pdfsubject = \l_@@_info_subject_tl ,
+ pdfkeywords = \l_@@_info_keywords_clist
+%</!thesis>
+ }
+ }
+ }
+% \end{macrocode}
+%
+% \subsubsection{\pkg{threeparttable} 宏包}
+%
+% \begin{macrocode}
+\ctex_at_end_package:nn { threeparttable }
+ { \tl_put_right:Nn \TPTnoteSettings { \footnotesize } }
+% \end{macrocode}
+%
+% \subsubsection{\pkg{longtable} 宏包}
+%
+% \begin{macrocode}
+\ctex_at_end_package:nn { longtable }
+ { \AtBeginEnvironment { longtable } { \SJTU@style@float@font } }
+% \end{macrocode}
+%
+% \subsubsection{\pkg{amsthm} 宏包和 \pkg{ntheorem} 宏包}
+%
+% \begin{macrocode}
+\cs_new_protected:Nn \@@_new_theorems:
+ {
+ \clist_map_inline:nn
+ {
+ assumption, axiom, conjecture, corollary, definition, example,
+ exercise, lemma, problem, proposition, theorem
+ }
+%<!article> { \exp_args:Nnv \newtheorem {##1} { c_@@_name_ ##1 _tl } [ chapter ] }
+%<article> { \exp_args:Nnv \newtheorem {##1} { c_@@_name_ ##1 _tl } }
+ \clist_map_inline:nn
+ { remark, solution }
+ { \exp_args:NNnv \newtheorem* {##1} { c_@@_name_ ##1 _tl } }
+ }
+% \end{macrocode}
+%
+% \pkg{amsthm} 宏包。
+% \begin{macrocode}
+\ctex_at_begin_package:nn { amsthm }
+ {
+ \cs_if_exist:NT \openbox
+ {
+ \cs_new_eq:NN \@@_save_openbox: \openbox
+ \cs_undefine:N \openbox
+ }
+ }
+\ctex_at_end_package:nn { amsthm }
+ {
+ \@@_cs_provide_eq:NN \QED \openbox
+ \cs_if_exist:NT \@@_save_openbox:
+ { \cs_set_eq:NN \openbox \@@_save_openbox: }
+ \tl_set:Nn \qedsymbol { \ensuremath { \QED } }
+ \RenewDocumentEnvironment { proof } { O{ \proofname } }
+ {
+ \par \pushQED { \qed }
+ \normalfont \dim_zero:N \topsep
+ \trivlist
+ \item
+ [
+ \skip_horizontal:N \labelsep
+ \bfseries \CJKsffamily #1 \@addpunct { \enskip }
+ ]
+ \ignorespaces
+ }
+ { \popQED \endtrivlist \@endpefalse }
+ \newtheoremstyle { sjtu }
+ { } { } { \normalfont } { } { \bfseries \CJKsffamily } { } { \ccwd } { }
+ \theoremstyle { sjtu }
+ \@@_new_theorems:
+ }
+% \end{macrocode}
+%
+% \pkg{ntheorem} 宏包。
+% \begin{macrocode}
+\ctex_at_end_package:nn { ntheorem }
+ {
+ \@@_cs_provide_eq:NN \QED \c_empty_tl
+ \theoremheaderfont { \bfseries \CJKsffamily }
+ \theorembodyfont { \normalfont }
+ \theoremseparator { \enskip }
+ \theoremsymbol { \ensuremath { \QED } }
+ \qedsymbol { \ensuremath { \QED } }
+ \newtheorem* { proof } { \proofname }
+ \theoremsymbol { }
+ \@@_new_theorems:
+ }
+% \end{macrocode}
+%
+% \subsubsection{\pkg{algorithm} 宏包和 \pkg{algorithm2e} 宏包}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_newlistof:nnnnn #1#2#3#4#5
+ {
+ \exp_args:Nnv \newlistentry {#2} { ext@ #3 } { 0 }
+ \exp_args:Ne \newcounter { \tl_use:c { ext@ #3 } depth }
+ \exp_args:Ne \setcounter { \tl_use:c { ext@ #3 } depth } { 1 }
+ \clist_put_right:Nn \l_@@_cft_presnum_clist { {#2} {#4} }
+ \cs_set_eq:cc { l@ #3 } { l@ #2 }
+ \exp_args:Nc \DeclareDocumentCommand { listof #1 s } { }
+ { \SJTU@listof {#5} {#3} }
+%<!article> \SJTU@counterwithin { #3 } { chapter }
+%<thesis> \clist_put_right:Nn \l_@@_counter_without_chapter_clist {#3}
+ }
+% \end{macrocode}
+%
+% \pkg{algorithm} 宏包。
+% \begin{macrocode}
+\ctex_at_end_package:nn { algorithm }
+ {
+ \tl_set:Nn \fname@algorithm { \SJTU@algorithmname }
+ \tl_set:Nn \listalgorithmname { \SJTU@listalgorithmname }
+ \@@_newlistof:nnnnn { algorithm } { alg } { algorithm }
+ { \fname@algorithm } { \listalgorithmname }
+ }
+% \end{macrocode}
+%
+% \pkg{algorithm2e} 宏包。
+% \begin{macrocode}
+%<!article>\ctex_at_begin_package:nn { algorithm2e }
+%<!article> { \cs_set_eq:NN \@@_save_chapter:w \@chapter }
+\ctex_at_end_package:nn { algorithm2e }
+ {
+%<!article> \cs_set_eq:NN \@chapter \@@_save_chapter:w
+ \SetAlgorithmName { \SJTU@algorithmname }
+ { \SJTU@algorithmname }
+ { \SJTU@listalgorithmname }
+ \SetAlgoCaptionSeparator { \enskip }
+ \@@_newlistof:nnnnn { algorithm } { alg } { algocf }
+ { \algorithmcfname } { \listalgorithmcfname }
+ \ctex_patch_cmd:Nnn \algocf@latexcaption
+ { \addcontentsline }
+ { \caption@iflist { \addcontentsline } { \@gobblethree } }
+ }
+% \end{macrocode}
+%
+% \subsubsection{\pkg{nomencl} 宏包}
+% \begin{macrocode}
+\ctex_at_end_package:nn { nomencl }
+ { \tl_set:Nn \nomname { \SJTU@nomname } }
+% \end{macrocode}
+%
+% \changes{v2.0.3}{2023/09/25}{添加 \pkg{siunitx} 本地化支持。}
+% \subsubsection{\pkg{translations} 宏包}
+% \begin{macrocode}
+\ctex_at_end_package:nn { translations }
+ {
+ \DeclareLanguage { chinese }
+ \DeclareLanguageAlias { Chinese } { chinese }
+ }
+% \end{macrocode}
+%
+% \subsubsection{\pkg{siunitx} 宏包}
+% \begin{macrocode}
+\ctex_at_end_package:nn { siunitx }
+ {
+ \RequirePackage { translations }
+ \DeclareTranslation { Chinese } { and } { 和 }
+ \DeclareTranslation { Japanese } { and } { と }
+ \DeclareTranslation { Chinese }
+ { to~(numerical~range) } { \textasciitilde }
+ \DeclareTranslation { Japanese }
+ { to~(numerical~range) } { \textasciitilde }
+ \IfPackageAtLeastTF { siunitx } { 2021/05/17 } { }
+ {
+ \DeclareTranslation { English } { to~(numerical~range) } { to }
+ \DeclareTranslation { German } { to~(numerical~range) } { bis }
+ \keys_set:nn { siunitx }
+ {
+ list-final-separator =
+ {
+ \ifmmode \ \else \space \fi
+ \text { \GetTranslation { and } }
+ \ifmmode \ \else \space \fi
+ } ,
+ list-pair-separator =
+ {
+ \ifmmode \ \else \space \fi
+ \text { \GetTranslation { and } }
+ \ifmmode \ \else \space \fi
+ } ,
+ range-phrase =
+ {
+ \ifmmode \ \else \space \fi
+ \text { \GetTranslation { to~(numerical~range) } }
+ \ifmmode \ \else \space \fi
+ }
+ }
+ }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</class>
+% \end{macrocode}
+%
+% \subsection{名称配置}
+% \begin{macrocode}
+%<*name>
+%<*zh|ja>
+\clist_map_inline:nn
+ {
+ { year } { 年 } ,
+ { month } { 月 } ,
+ { day } { 日 }
+ }
+%<zh> { \@@_define_name:nnn { zh } #1 }
+%<ja> { \@@_define_name:nnn { ja } #1 }
+%</zh|ja>
+%<*en>
+\clist_const:Nn \c_@@_name_month_en_clist
+ {
+ January, February, March, April, May, June,
+ July, August, September, October, November, December
+ }
+%</en>
+%<*de>
+\clist_const:Nn \c_@@_name_month_de_clist
+ {
+ Januar, Februar, März, April, Mai, Juni,
+ Juli, August, September, Oktober, November, Dezember
+ }
+%</de>
+%<*thesis>
+%<*zh>
+\@@_define_symbol:nn { white_square } { "25A1 }
+\@@_define_name_from_clist:nnnn { zh }
+ { degree_level } { \g_@@_thesis_type_int }
+ { 学士, 硕士, 博士 }
+%</zh>
+%<*en>
+\@@_define_name_from_clist:nnnn { en }
+ { degree_level } { \g_@@_thesis_type_int }
+ { Bachelor, Master, Doctor }
+%</en>
+%<*de>
+\@@_define_name_from_clist:nnnn { de }
+ { degree_level } { \g_@@_thesis_type_int }
+ { Bachelor, Master, Doktor }
+%</de>
+%<*ja>
+\@@_define_name_from_clist:nnnn { ja }
+ { degree_level } { \g_@@_thesis_type_int }
+ { 学士, 修士, 博士 }
+%</ja>
+%</thesis>
+%<*zh>
+\clist_map_inline:nn
+ {
+%<*thesis>
+ { univ } { 上海交通大学 } ,
+ { author } { 姓名 } ,
+ { id } { 学号 } ,
+ { supervisor } { 导师 } ,
+ { assoc_supervisor } { 副导师 } ,
+ { department } { 院系 } ,
+ { co_supervisor } { 联合导师 } ,
+ { major } { 学科 / 专业 } ,
+ { degree } { 申请学位 } ,
+ { thesis } { 学位论文 } ,
+ { title_page } { 题名页 } ,
+ { declaration } { 原创性声明及使用授权书 } ,
+ { orig_decl } { 原创性声明 } ,
+ { auth_decl } { 使用授权书 } ,
+ { decl_author } { 学位论文作者 } ,
+ { decl_supervisor } { 指导教师 } ,
+ { abstract } { 摘 \protect \quad 要 } ,
+%</thesis>
+ { keywords } { 关键词 } ,
+ { info_sep } { : \null } ,
+ { item_sep } { , }
+ }
+%<thesis> { \@@_define_name:nnn { zh } #1 }
+%<!thesis> { \@@_define_name:nn #1 }
+%</zh>
+%<*en>
+\clist_map_inline:nn
+ {
+%<*thesis>
+ { univ } { Shanghai~ Jiao~ Tong~ University } ,
+ { address } { Shanghai,~ P.R.~ China } ,
+ { author } { Author } ,
+ { supervisor } { Supervisor } ,
+ { assoc_supervisor } { Assoc.~ Supervisor } ,
+ { co_supervisor } { Co-supervisor } ,
+ { title_page } { Title~ Page } ,
+ { declaration } { Statutory~ Declaration } ,
+ { abstract } { Abstract } ,
+%</thesis>
+ { keywords } { Key~words } ,
+ { info_sep } { :~ } ,
+ { item_sep } { ,~ }
+ }
+%<thesis> { \@@_define_name:nnn { en } #1 }
+%<!thesis> { \@@_define_name:nn #1 }
+%</en>
+%<*de>
+\clist_map_inline:nn
+ {
+%<*thesis>
+ { univ } { Shanghai~ Jiao~ Tong~ Universität } ,
+ { address } { Shanghai,~ VR~ China } ,
+ { author } { Autor/in } ,
+ { supervisor } { Betreuer/in } ,
+ { assoc_supervisor } { Zweitbetreuer/in } ,
+ { co_supervisor } { Co-Betreuer/in } ,
+ { title_page } { Titelblatt } ,
+ { declaration } { Eidesstattliche~ Erklärung } ,
+ { abstract } { Abstrakt } ,
+%</thesis>
+ { keywords } { Schlüsselwörter } ,
+ { info_sep } { :~ } ,
+ { item_sep } { ,~ }
+ }
+%<thesis> { \@@_define_name:nnn { de } #1 }
+%<!thesis> { \@@_define_name:nn #1 }
+%</de>
+%<*ja>
+\clist_map_inline:nn
+ {
+%<*thesis>
+ { univ } { 上海交通大学 } ,
+ { address } { 中国・上海 } ,
+ { author } { 氏名 } ,
+ { supervisor } { 指導教員 } ,
+ { assoc_supervisor } { 副指導教員 } ,
+ { co_supervisor } { 共同指導 } ,
+ { thesis } { 学位請求論文 } ,
+ { title_page } { 標題紙 } ,
+ { declaration } { 誓約書・公表許諾書 } ,
+ { abstract } { 要 \protect \quad 旨 } ,
+%</thesis>
+ { keywords } { キーワード } ,
+ { info_sep } { : \null } ,
+ { item_sep } { \quad }
+ }
+%<thesis> { \@@_define_name:nnn { ja } #1 }
+%<!thesis> { \@@_define_name:nn #1 }
+%</ja>
+%<*thesis>
+%<*zh>
+\tl_const:Nn \c_@@_orig_decl_text_zh_tl
+ {
+ 本人郑重声明:所呈交的学位论文,是本人在导师的指导下,独立进行研究工
+ 作所取得的成果。除文中已经注明引用的内容外,本论文不包含任何其他个人
+ 或集体已经发表或撰写过的作品成果。对本文的研究做出重要贡献的个人和集
+ 体,均已在文中以明确方式标明。本人完全知晓本声明的法律后果由本人承
+ 担。
+ }
+\tl_const:Nn \c_@@_auth_decl_text_zh_tl
+ {
+ 本人同意学校保留并向国家有关部门或机构送交论文的复印件和电子版,允许
+ 论文被查阅和借阅。 \par
+ \vskip 6 bp
+ \noindent
+ 本学位论文属于: \par
+ { \c_@@_symbol_white_square_tl } \textbf { 公开论文 } \par
+ { \c_@@_symbol_white_square_tl } \textbf { 内部论文 },
+ 保密 { \c_@@_symbol_white_square_tl }~ 1~ 年 /
+ { \c_@@_symbol_white_square_tl }~ 2~ 年 /
+ { \c_@@_symbol_white_square_tl }~ 3~ 年,
+ 过保密期后适用本授权书。 \par
+ { \c_@@_symbol_white_square_tl } \textbf { 秘密论文 },
+ 保密 \underline { \hspace { 2 em } } 年(不超过~ 10~ 年),
+ 过保密期后适用本授权书。 \par
+ { \c_@@_symbol_white_square_tl } \textbf { 机密论文 },
+ 保密 \underline { \hspace { 2 em } } 年(不超过~ 20~ 年),
+ 过保密期后适用本授权书。 \par
+ \hspace { 6 em }(请在以上方框内选择打“ \ensuremath { \checkmark } ”)
+ }
+\tl_const:Nn \c_@@_signature_text_zh_tl
+ {
+ 签名: \\
+ 日期: \hspace { \stretch { 3 } } 年
+ \hspace { \stretch { 2 } } 月
+ \hspace { \stretch { 2 } } 日
+ }
+%</zh>
+%</thesis>
+%</name>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*scheme>
+\clist_map_inline:nn
+ {
+%<*zh>
+ { assumption } { 假设 } ,
+ { axiom } { 公理 } ,
+ { conjecture } { 猜想 } ,
+ { corollary } { 推论 } ,
+ { definition } { 定义 } ,
+ { example } { 例 } ,
+ { exercise } { 练习 } ,
+ { lemma } { 引理 } ,
+ { problem } { 问题 } ,
+ { proposition } { 命题 } ,
+ { remark } { 注 } ,
+ { solution } { 解 } ,
+ { theorem } { 定理 }
+%</zh>
+%<*en>
+ { assumption } { Assumption } ,
+ { axiom } { Axiom } ,
+ { conjecture } { Conjecture } ,
+ { corollary } { Corollary } ,
+ { definition } { Definition } ,
+ { example } { Example } ,
+ { exercise } { Exercise } ,
+ { lemma } { Lemma } ,
+ { problem } { Problem } ,
+ { proposition } { Proposition } ,
+ { remark } { Remark } ,
+ { solution } { Solution } ,
+ { theorem } { Theorem }
+%</en>
+%<*de>
+ { assumption } { Annahme } ,
+ { axiom } { Axiom } ,
+ { conjecture } { Hypothese } ,
+ { corollary } { Korollar } ,
+ { definition } { Definition } ,
+ { example } { Beispiel } ,
+ { exercise } { Übung } ,
+ { lemma } { Lemma } ,
+ { problem } { Problem } ,
+ { proposition } { Proposition } ,
+ { remark } { Anmerkung } ,
+ { solution } { Lösung } ,
+ { theorem } { Theorem }
+%</de>
+%<*ja>
+ { assumption } { 仮定 } ,
+ { axiom } { 公理 } ,
+ { conjecture } { 予想 } ,
+ { corollary } { 系 } ,
+ { definition } { 定義 } ,
+ { example } { 例 } ,
+ { exercise } { 練習 } ,
+ { lemma } { 補題 } ,
+ { problem } { 問題 } ,
+ { proposition } { 命題 } ,
+ { remark } { 注意 } ,
+ { solution } { 解法 } ,
+ { theorem } { 定理 }
+%</ja>
+ }
+ { \@@_define_name:nn #1 }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</scheme>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \Finale
+%
+\endinput
diff --git a/macros/latex/contrib/sjtutex/sjtutex.pdf b/macros/latex/contrib/sjtutex/sjtutex.pdf
new file mode 100644
index 0000000000..c14c72d1d6
--- /dev/null
+++ b/macros/latex/contrib/sjtutex/sjtutex.pdf
Binary files differ