summaryrefslogtreecommitdiff
path: root/macros
diff options
context:
space:
mode:
Diffstat (limited to 'macros')
-rw-r--r--macros/latex/contrib/bjfuthesis/README.md2
-rw-r--r--macros/latex/contrib/bjfuthesis/bjfuthesis.cls8
-rw-r--r--macros/latex/contrib/bjfuthesis/documentation/bjfuthesis.pdfbin132184 -> 132184 bytes
-rw-r--r--macros/latex/contrib/bjfuthesis/documentation/bjfuthesis.tex99
-rw-r--r--macros/latex/contrib/bjfuthesis/documentation/contents/doc-abstract.tex10
-rw-r--r--macros/latex/contrib/bjfuthesis/documentation/contents/doc-acknowledge.tex2
-rw-r--r--macros/latex/contrib/bjfuthesis/documentation/contents/doc-mainbody.tex83
-rw-r--r--macros/latex/contrib/bjfuthesis/example/contents/abstract.tex14
-rw-r--r--macros/latex/contrib/bjfuthesis/example/contents/acknowledge.tex10
-rw-r--r--macros/latex/contrib/bjfuthesis/example/contents/cover.pdf (renamed from macros/latex/contrib/bjfuthesis/example/cover.pdf)bin208783 -> 208422 bytes
-rw-r--r--macros/latex/contrib/bjfuthesis/example/contents/mainbody.tex575
-rw-r--r--macros/latex/contrib/bjfuthesis/example/contents/mission-statement.pdfbin0 -> 145804 bytes
-rw-r--r--macros/latex/contrib/bjfuthesis/example/contents/statement-of-originality.pdfbin0 -> 260358 bytes
-rw-r--r--macros/latex/contrib/bjfuthesis/example/thesis.pdfbin4831821 -> 5191753 bytes
-rw-r--r--macros/latex/contrib/bjfuthesis/example/thesis.tex607
-rw-r--r--macros/latex/contrib/colorist/colorart.cls2
-rw-r--r--macros/latex/contrib/colorist/colorbook.cls2
-rw-r--r--macros/latex/contrib/colorist/colorist-doc.pdfbin82025 -> 82011 bytes
-rw-r--r--macros/latex/contrib/colorist/colorist-doc.tex2
-rw-r--r--macros/latex/contrib/colorist/colorist.sty33
-rw-r--r--macros/latex/contrib/easybook/easybook.dtx73
-rw-r--r--macros/latex/contrib/easybook/easybook.pdfbin314709 -> 314457 bytes
-rw-r--r--macros/latex/contrib/hvfloat/Changes3
-rw-r--r--macros/latex/contrib/hvfloat/doc/examples/capPos.inc129
-rw-r--r--macros/latex/contrib/hvfloat/doc/examples/capPos.ltx34
-rw-r--r--macros/latex/contrib/hvfloat/doc/examples/capPos.tex147
-rw-r--r--macros/latex/contrib/hvfloat/doc/examples/capVPos.inc133
-rw-r--r--macros/latex/contrib/hvfloat/doc/hvfloat.pdfbin7111003 -> 7113219 bytes
-rw-r--r--macros/latex/contrib/hvfloat/doc/hvfloat.tex5
-rw-r--r--macros/latex/contrib/hvfloat/latex/hvfloat.sty209
-rw-r--r--macros/latex/contrib/hyperref/ChangeLog.txt3
-rw-r--r--macros/latex/contrib/hyperref/README.md2
-rw-r--r--macros/latex/contrib/hyperref/doc/backref.pdfbin198815 -> 198815 bytes
-rw-r--r--macros/latex/contrib/hyperref/doc/hyperref-doc.html2
-rw-r--r--macros/latex/contrib/hyperref/doc/hyperref-doc.pdfbin298609 -> 298448 bytes
-rw-r--r--macros/latex/contrib/hyperref/doc/hyperref-doc.tex2
-rw-r--r--macros/latex/contrib/hyperref/doc/hyperref.pdfbin2427494 -> 2426770 bytes
-rw-r--r--macros/latex/contrib/hyperref/doc/nameref.pdfbin188802 -> 188802 bytes
-rw-r--r--macros/latex/contrib/hyperref/hluatex.dtx4
-rw-r--r--macros/latex/contrib/hyperref/hyperref.dtx6
-rw-r--r--macros/latex/contrib/hyperref/xr-hyper.sty2
-rw-r--r--macros/latex/contrib/mathcommand/README.md35
-rw-r--r--macros/latex/contrib/mathcommand/mathcommand.dtx170
-rw-r--r--macros/latex/contrib/mathcommand/mathcommand.ins60
-rw-r--r--macros/latex/contrib/mathcommand/mathcommand.pdfbin454011 -> 452046 bytes
-rw-r--r--macros/latex/contrib/minimalist/minimalist-doc.pdfbin81352 -> 81350 bytes
-rw-r--r--macros/latex/contrib/minimalist/minimalist-doc.tex2
-rw-r--r--macros/latex/contrib/minimalist/minimalist.sty33
-rw-r--r--macros/latex/contrib/minimalist/minimart.cls2
-rw-r--r--macros/latex/contrib/minimalist/minimbook.cls2
-rw-r--r--macros/latex/contrib/pmdb/README.md8
-rw-r--r--macros/latex/contrib/pmdb/docs/pmdb-man.pdfbin243694 -> 249153 bytes
-rw-r--r--macros/latex/contrib/pmdb/docs/pmdb-man.tex192
-rw-r--r--macros/latex/contrib/pmdb/docs/pmdb.pdfbin262160 -> 279968 bytes
-rw-r--r--macros/latex/contrib/pmdb/docs/sample-item.tex4
-rw-r--r--macros/latex/contrib/pmdb/docs/sample-para.tex7
-rw-r--r--macros/latex/contrib/pmdb/examples/probs/prob2.tex2
-rw-r--r--macros/latex/contrib/pmdb/examples/probs/prob4.tex5
-rw-r--r--macros/latex/contrib/pmdb/examples/tst-eqedb.tex94
-rw-r--r--macros/latex/contrib/pmdb/examples/tst-items.tex9
-rw-r--r--macros/latex/contrib/pmdb/examples/tst-paras.tex12
-rw-r--r--macros/latex/contrib/pmdb/examples/tst-qzdb-paras.pdfbin0 -> 406386 bytes
-rw-r--r--macros/latex/contrib/pmdb/examples/tst-qzdb-paras.tex6
-rw-r--r--macros/latex/contrib/pmdb/examples/tst-qzdb.pdfbin0 -> 450424 bytes
-rw-r--r--macros/latex/contrib/pmdb/examples/tst-qzdb.tex9
-rw-r--r--macros/latex/contrib/pmdb/pmdb.dtx274
-rw-r--r--macros/latex/contrib/pythontex/NEWS.rst20
-rw-r--r--macros/latex/contrib/pythontex/README2
-rw-r--r--macros/latex/contrib/pythontex/depythontex2.py4
-rw-r--r--macros/latex/contrib/pythontex/depythontex3.py4
-rw-r--r--macros/latex/contrib/pythontex/pythontex.dtx23
-rw-r--r--macros/latex/contrib/pythontex/pythontex.ins2
-rw-r--r--macros/latex/contrib/pythontex/pythontex.pdfbin975950 -> 979067 bytes
-rw-r--r--macros/latex/contrib/pythontex/pythontex2.py33
-rw-r--r--macros/latex/contrib/pythontex/pythontex3.py33
-rw-r--r--macros/latex/contrib/pythontex/pythontex_engines.py8
-rw-r--r--macros/latex/contrib/siunitx/CHANGELOG.md17
-rw-r--r--macros/latex/contrib/siunitx/siunitx-code.pdfbin1482618 -> 1485621 bytes
-rw-r--r--macros/latex/contrib/siunitx/siunitx-emulation.dtx23
-rw-r--r--macros/latex/contrib/siunitx/siunitx-symbol.dtx32
-rw-r--r--macros/latex/contrib/siunitx/siunitx-unit.dtx2
-rw-r--r--macros/latex/contrib/siunitx/siunitx.dtx4
-rw-r--r--macros/latex/contrib/siunitx/siunitx.pdfbin634770 -> 634770 bytes
-rw-r--r--macros/latex/contrib/suftesi/suftesi.dtx295
-rw-r--r--macros/latex/contrib/suftesi/suftesi.pdfbin847077 -> 847637 bytes
-rw-r--r--macros/latex/contrib/tiscreen/README1
-rw-r--r--macros/latex/contrib/tiscreen/doc/tiscreen-doc.pdfbin131993 -> 133438 bytes
-rw-r--r--macros/latex/contrib/tiscreen/doc/tiscreen-doc.tex55
-rw-r--r--macros/latex/contrib/tiscreen/tex/tiscreen.sty2
-rw-r--r--macros/luatex/generic/luatexja/README8
-rw-r--r--macros/luatex/generic/luatexja/doc/luatexja-en.pdfbin693535 -> 693756 bytes
-rw-r--r--macros/luatex/generic/luatexja/doc/luatexja-ja.pdfbin1130307 -> 1125155 bytes
-rw-r--r--macros/luatex/generic/luatexja/src/ltj-direction.lua10
-rw-r--r--macros/luatex/generic/luatexja/src/luatexja.sty4
-rw-r--r--macros/luatex/generic/luatexja/src/patches/lltjfont.sty9
95 files changed, 2254 insertions, 1466 deletions
diff --git a/macros/latex/contrib/bjfuthesis/README.md b/macros/latex/contrib/bjfuthesis/README.md
index 9b2d6ad1cd..14f4383696 100644
--- a/macros/latex/contrib/bjfuthesis/README.md
+++ b/macros/latex/contrib/bjfuthesis/README.md
@@ -1,7 +1,7 @@
# 北京林业大学 (BJFU) 毕业论文模板 (LaTeX)
Copyright (C) 2021 Liu Changxin
-Version 1.0.3 (2021-06-06)
+Version 1.0.4 (2021-06-07)
## Abstract
This is a class file for producing dissertations and theses according to the Beijing Forestry University (BJFU) Guidelines for Undergraduate Theses and Dissertations.
diff --git a/macros/latex/contrib/bjfuthesis/bjfuthesis.cls b/macros/latex/contrib/bjfuthesis/bjfuthesis.cls
index 641a6e8d4e..39f11fe847 100644
--- a/macros/latex/contrib/bjfuthesis/bjfuthesis.cls
+++ b/macros/latex/contrib/bjfuthesis/bjfuthesis.cls
@@ -23,18 +23,16 @@
\def\keywords@label@zh{关键词:}
\def\keywords@label@en{Keywords: }
\def\chartnote@label{注:}
-\ProvidesClass{bjfuthesis}[2021/06/06 A thesis class for Beijing Forestry University]
+\ProvidesClass{bjfuthesis}[2021/06/07 A thesis class for Beijing Forestry University]
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{ctexbook}}
\ProcessOptions*
\LoadClass[a4paper,oneside,fontset=none]{ctexbook}
\RequirePackage{pdfpages,graphicx}
-\graphicspath{{figures/}}
\RequirePackage[style=gb7714-2015]{biblatex}
-\addbibresource{bibliography.bib}
\RequirePackage{silence,bicaption}
\DeclareCaptionFormat{bjfucaption}{\textbf{\fontsize{9}{21}\selectfont#1#2#3}}
\captionsetup{format=bjfucaption,skip=0pt,labelsep=space}
-\captionsetup[figure][bi-second]{name=Figure}
+\captionsetup[figure][bi-second]{name=Fig.}
\captionsetup[table][bi-second]{name=Table}
\RequirePackage{amsmath}
\setlength\voffset{-10.4mm}
@@ -165,7 +163,7 @@
\newcommand\keywordscn[1]{\noindent\fontsize{12}{21}\selectfont\textbf{\keywords@label@zh}#1\par}
\newcommand\keywordsen[1]{\noindent\fontsize{12}{21}\selectfont\textbf{\keywords@label@en}#1\par}
\NewCommandCopy\oldfrontmatter\frontmatter
-\renewcommand\frontmatter{\IfFileExists{cover.pdf}{\includepdf[pages={1-2}]{cover.pdf}}{\typeout{!! cover.pdf not found}\ClassWarning{bjfuthesis}{cover.pdf not found}}\oldfrontmatter\renewcommand\thepage{\Roman{page}}\fontsize{12}{21}\selectfont}
+\renewcommand\frontmatter{\oldfrontmatter\renewcommand\thepage{\Roman{page}}\fontsize{12}{21}\selectfont}
\NewCommandCopy\oldmainmatter\mainmatter
\renewcommand\mainmatter{\oldmainmatter\fontsize{12}{21}\selectfont}
\newcommand\chartnote[1]{\fontsize{9}{21}\selectfont\\\begin{flushleft}\chartnote@label#1\end{flushleft}}
diff --git a/macros/latex/contrib/bjfuthesis/documentation/bjfuthesis.pdf b/macros/latex/contrib/bjfuthesis/documentation/bjfuthesis.pdf
index f912884e87..1e52e34850 100644
--- a/macros/latex/contrib/bjfuthesis/documentation/bjfuthesis.pdf
+++ b/macros/latex/contrib/bjfuthesis/documentation/bjfuthesis.pdf
Binary files differ
diff --git a/macros/latex/contrib/bjfuthesis/documentation/bjfuthesis.tex b/macros/latex/contrib/bjfuthesis/documentation/bjfuthesis.tex
index 0f02ad826d..5b0505d74d 100644
--- a/macros/latex/contrib/bjfuthesis/documentation/bjfuthesis.tex
+++ b/macros/latex/contrib/bjfuthesis/documentation/bjfuthesis.tex
@@ -1,11 +1,104 @@
\documentclass{bjfuthesis}
+\usepackage[utf8]{inputenc}
\begin{document}
\frontmatter
- \input{contents/doc-abstract}
+ \chapter*{摘要}
+\begin{abstract}
+ bjfuthesis文档类是为北京林业大学学生书写毕业论文准备的\LaTeX 文档类。该文档类基于ctexbook文档类。它修改了一些布局与样式来提供与北京林业大学毕业论文规范兼容的文档布局。
+\end{abstract}
+\keywordscn{LaTeX,毕业论文,北京林业大学}
+\chapter*{Abstract}
+\begin{abstract}
+ The bjfuthesis class is a \LaTeX\space class intended for students in Beijing Forestry University to write their theses. The class is based on the ctexbook class. It modifies some of the layout and style definitions of these packages in order to provide a document layout that should be compatible with Beijing Forestry University Thesis Standard.
+\end{abstract}
+\keywordsen{LaTeX, thesis, Beijing Forestry University}
\tableofcontents
\mainmatter
- \input{contents/doc-mainbody}
+ \chapter{绪论}
+\section{研究背景}
+国内诸多高校都在GitHub上提供了其高校的论文模板,故本作者秉持开源共享的精神,将本\LaTeX 文档类开源于https://github.com/bjfu-projects/bjfu-thesis。
+\section{文档结构}
+第一章为绪论,简单介绍研究背景以及文档结构。
+
+第二章为英文使用说明,介绍本文档类的使用方法。
+
+第三章为中文使用说明,介绍本文档类的使用方法。
+\chapter{Usage Notes}
+The order of following usage notes is based on the structure of the thesis.
+\begin{enumerate}
+\item To include the cover of your thesis, put `cover.pdf' in the directory.
+\item You MUST add \verb|\frontmatter| before your abstract.
+\item Print title of Chinese abstract or English abstract: \verb|\chapter*{abstract title}|
+\item Print content of abstract: \verb|\begin{abstract}|abstract content\verb|\end{abstract}|
+\item Print Chinese keywords: \verb|\keywordscn{Chinese keywords}|
+\item Print English keywords: \verb|\keywordsen{English keywords}|
+\item Print table of contents: \verb|tableofcontents|
+\item You MUST add \verb|\mainmatter| before the main body of your thesis.
+\item The hierachy of the thesis:
+\begin{verbatim}
+ \chapter{chapter title}
+ \section{section title}
+ \subsection{subsection title}
+\end{verbatim}
+\item Use following structure:
+\begin{verbatim}
+\chapter{chapter 1 title}
+normal text
+\section{section 1.1 title}
+normal text
+\section{section 1.2 title}
+\subsection{subsection 1.2.1 title}
+normal text
+...
+\end{verbatim}
+\item Floats are set to be centered by default, with default allowed positions being current position in code, top, bottom and a separate page.
+\item Put images you want to insert in \verb|\figures|, and you DO NOT need to include 'figures' in your path
+\item Show two captions for a figure or a table:\\ \verb|\bicaption{Chinese caption}{English caption}|
+You MUST place figures in 'figure' environment, and table in 'table' environment, which MUST match,
+or \verb|\bicaption{Chinese caption}{English caption}| will not work as expected.
+\item Show a note for a figure or table: \verb|\chartnote{a note for a figure or a table}|
+\item You MUST add \verb|\backmatter| before your references and your acknowledgement.
+\item Print bibliography: \verb|\printbibliography|
+\end{enumerate}
+\chapter{使用说明}
+以下使用说明的顺序基于论文的结构
+\begin{enumerate}
+\item 要将你的论文封面插入论文,需将``cover.pdf"置于该目录中
+\item 你必须在摘要部分前加入\verb|\frontmatter|
+\item 显示中文或英文摘要标题:\verb|\chapter*{摘要标题}|
+\item 显示摘要内容:\verb|\begin{abstract}|摘要内容\verb|\end{abstract}|
+\item 显示中文关键词:\verb|\keywordscn{中文关键词}|
+\item 显示英文关键词:\verb|\keywordsen{英文关键词}|
+\item 显示目录:\verb|tableofcontents|
+\item 你必须在你的论文的主体部分前加入\verb|\mainmatter|
+\item 论文具有的层次划分:
+\begin{verbatim}
+ \chapter{一级标题}
+ \section{二级标题}
+ \subsection{三级标题}
+\end{verbatim}
+\item 使用以下层次结构:
+\begin{verbatim}
+ \chapter{一级标题 1}
+ 正文文字
+ \section{二级标题 1.1}
+ 正文文字
+ \section{二级标题 1.2}
+ \subsection{三级标题 1.2.1}
+ 正文文字
+ ……
+\end{verbatim}
+\item 浮动体已默认居中,且默认允许的位置已设为“当前代码中的位置、顶部、底部、单独成页”
+\item 将你需要插入的图片置于\verb|\figures|中,无需在路径中包含“figures”
+\item 为一张图或一个表显示两个图(表)题:\verb|\bicaption{中文图题}{英文图题}|
+你必须将图置于“figure”环境中,表置于“table”环境中,必须匹配。
+否则\verb|\bicaption{中文图题}{英文图题}|不会起作用
+\item 显示图表注: \verb|\chartnote{图的注释或表的注释}|
+\item 你必须在你的参考文献前加入\verb|\backmatter|
+\item 显示参考文献:\verb|\printbibliography|
+\end{enumerate}
\backmatter
\chapter{参考文献}
- \input{contents/doc-acknowledge}
+ \chapter{致谢}
+感谢所有为本项目提供过帮助的人的贡献。
\end{document}
diff --git a/macros/latex/contrib/bjfuthesis/documentation/contents/doc-abstract.tex b/macros/latex/contrib/bjfuthesis/documentation/contents/doc-abstract.tex
deleted file mode 100644
index ceba3447e7..0000000000
--- a/macros/latex/contrib/bjfuthesis/documentation/contents/doc-abstract.tex
+++ /dev/null
@@ -1,10 +0,0 @@
-\chapter*{摘要}
-\begin{abstract}
- bjfuthesis文档类是为北京林业大学学生书写毕业论文准备的\LaTeX 文档类。该文档类基于ctexbook文档类。它修改了一些布局与样式来提供与北京林业大学毕业论文规范兼容的文档布局。
-\end{abstract}
-\keywordscn{LaTeX,毕业论文,北京林业大学}
-\chapter*{Abstract}
-\begin{abstract}
- The bjfuthesis class is a \LaTeX\space class intended for students in Beijing Forestry University to write their theses. The class is based on the ctexbook class. It modifies some of the layout and style definitions of these packages in order to provide a document layout that should be compatible with Beijing Forestry University Thesis Standard.
-\end{abstract}
-\keywordsen{LaTeX, thesis, Beijing Forestry University}
diff --git a/macros/latex/contrib/bjfuthesis/documentation/contents/doc-acknowledge.tex b/macros/latex/contrib/bjfuthesis/documentation/contents/doc-acknowledge.tex
deleted file mode 100644
index d34215c371..0000000000
--- a/macros/latex/contrib/bjfuthesis/documentation/contents/doc-acknowledge.tex
+++ /dev/null
@@ -1,2 +0,0 @@
-\chapter{致谢}
-感谢所有为本项目提供过帮助的人的贡献。
diff --git a/macros/latex/contrib/bjfuthesis/documentation/contents/doc-mainbody.tex b/macros/latex/contrib/bjfuthesis/documentation/contents/doc-mainbody.tex
deleted file mode 100644
index a92534d13a..0000000000
--- a/macros/latex/contrib/bjfuthesis/documentation/contents/doc-mainbody.tex
+++ /dev/null
@@ -1,83 +0,0 @@
-\chapter{绪论}
-\section{研究背景}
-国内诸多高校都在GitHub上提供了其高校的论文模板,故本作者秉持开源共享的精神,将本\LaTeX 文档类开源于https://github.com/bjfu-projects/bjfu-thesis。
-\section{文档结构}
-第一章为绪论,简单介绍研究背景以及文档结构。
-
-第二章为英文使用说明,介绍本文档类的使用方法。
-
-第三章为中文使用说明,介绍本文档类的使用方法。
-\chapter{Usage Notes}
-The order of following usage notes is based on the structure of the thesis.
-\begin{enumerate}
-\item To include the cover of your thesis, put `cover.pdf' in the directory.
-\item You MUST add \verb|\frontmatter| before your abstract.
-\item Print title of Chinese abstract or English abstract: \verb|\chapter*{abstract title}|
-\item Print content of abstract: \verb|\begin{abstract}|abstract content\verb|\end{abstract}|
-\item Print Chinese keywords: \verb|\keywordscn{Chinese keywords}|
-\item Print English keywords: \verb|\keywordsen{English keywords}|
-\item Print table of contents: \verb|tableofcontents|
-\item You MUST add \verb|\mainmatter| before the main body of your thesis.
-\item The hierachy of the thesis:
-\begin{verbatim}
- \chapter{chapter title}
- \section{section title}
- \subsection{subsection title}
-\end{verbatim}
-\item Use following structure:
-\begin{verbatim}
-\chapter{chapter 1 title}
-normal text
-\section{section 1.1 title}
-normal text
-\section{section 1.2 title}
-\subsection{subsection 1.2.1 title}
-normal text
-...
-\end{verbatim}
-\item Floats are set to be centered by default, with default allowed positions being current position in code, top, bottom and a separate page.
-\item Put images you want to insert in \verb|\figures|, and you DO NOT need to include 'figures' in your path
-\item Show two captions for a figure or a table:\\ \verb|\bicaption{Chinese caption}{English caption}|
-You MUST place figures in 'figure' environment, and table in 'table' environment, which MUST match,
-or \verb|\bicaption{Chinese caption}{English caption}| will not work as expected.
-\item Show a note for a figure or table: \verb|\chartnote{a note for a figure or a table}|
-\item You MUST add \verb|\backmatter| before your references and your acknowledgement.
-\item Print bibliography: \verb|\printbibliography|
-\end{enumerate}
-\chapter{使用说明}
-以下使用说明的顺序基于论文的结构
-\begin{enumerate}
-\item 要将你的论文封面插入论文,需将``cover.pdf"置于该目录中
-\item 你必须在摘要部分前加入\verb|\frontmatter|
-\item 显示中文或英文摘要标题:\verb|\chapter*{摘要标题}|
-\item 显示摘要内容:\verb|\begin{abstract}|摘要内容\verb|\end{abstract}|
-\item 显示中文关键词:\verb|\keywordscn{中文关键词}|
-\item 显示英文关键词:\verb|\keywordsen{英文关键词}|
-\item 显示目录:\verb|tableofcontents|
-\item 你必须在你的论文的主体部分前加入\verb|\mainmatter|
-\item 论文具有的层次划分:
-\begin{verbatim}
- \chapter{一级标题}
- \section{二级标题}
- \subsection{三级标题}
-\end{verbatim}
-\item 使用以下层次结构:
-\begin{verbatim}
- \chapter{一级标题 1}
- 正文文字
- \section{二级标题 1.1}
- 正文文字
- \section{二级标题 1.2}
- \subsection{三级标题 1.2.1}
- 正文文字
- ……
-\end{verbatim}
-\item 浮动体已默认居中,且默认允许的位置已设为“当前代码中的位置、顶部、底部、单独成页”
-\item 将你需要插入的图片置于\verb|\figures|中,无需在路径中包含“figures”
-\item 为一张图或一个表显示两个图(表)题:\verb|\bicaption{中文图题}{英文图题}|
-你必须将图置于“figure”环境中,表置于“table”环境中,必须匹配。
-否则\verb|\bicaption{中文图题}{英文图题}|不会起作用
-\item 显示图表注: \verb|\chartnote{图的注释或表的注释}|
-\item 你必须在你的参考文献前加入\verb|\backmatter|
-\item 显示参考文献:\verb|\printbibliography|
-\end{enumerate} \ No newline at end of file
diff --git a/macros/latex/contrib/bjfuthesis/example/contents/abstract.tex b/macros/latex/contrib/bjfuthesis/example/contents/abstract.tex
deleted file mode 100644
index 12c5ecc161..0000000000
--- a/macros/latex/contrib/bjfuthesis/example/contents/abstract.tex
+++ /dev/null
@@ -1,14 +0,0 @@
-\chapter*{摘要}
-\begin{abstract}
- 随着在线电影数量不断增加,用户选择电影的时间成本不断上升,准确的推荐算法成为了必然要求。为解决协同过滤推荐算法中的稀缺性问题与冷启动问题,研究人员用商品属性或社交网络等信息来辅助推荐算法。现有的将知识图谱作为辅助信息的推荐算法包括基于嵌入的方法和基于路径的方法,但这两种方法均存在一些缺陷,没有充分有效地利用知识图谱中的相关信息,推荐的准确度较低。
-
- 本文实现了基于知识图谱的“涟漪网络”推荐算法。“涟漪网络”算法的核心是利用现实生活中雨滴产生的涟漪在水面上不断扩散的思路,来模拟用户偏好的扩散。对于每一个用户,涟漪网络将其过往偏好作为知识图谱中的一个种子集,然后沿知识图谱中的关系路径不断地拓展用户偏好,进而发现该用户对某个候选物品以等级划分的潜在兴趣,其中多个“涟漪”重叠形成知识图谱中的用户偏好分布。该算法的实验结果和以往的CKE、DKN、PER等模型结果相比,表现出更优的性能。利用该算法,本文设计并实现了一个基于知识图谱的电影推荐系统,该系统包括管理员用户和普通用户,管理员能新增、编辑和删除电影与用户,普通用户能浏览、收藏与购买电影。该系统可以高效准确地为用户推荐电影,方便用户选择满足自己偏好的电影。
-\end{abstract}
-\keywordscn{知识图谱,推荐系统,涟漪网络,用户偏好,电影商店}
-\chapter*{Abstract}
-\begin{abstract}
- As the number of online movies continues to increase and the time cost for users to choose movies continues to rise, accurate recommendation algorithms have become an necessary requirement. In order to address the scarcity and cold start problem of collaborative filtering, researchers usually make use of side information, such as product attributes or social networks as side information to assist the recommendation. The existing recommendation algorithms that use knowledge graph as side information include embedding-based methods and path-based methods, but both methods have some shortcomings. They do not make full and effective use of the relevant information in the knowledge graph, and the accuracy of recommendation is relatively low.
-
- This paper implements a recommendation algorithm, ``Ripple Network", based on knowledge graph. The core of the Ripple Network algorithm is to use the idea that the ripples produced by raindrops in real life continue to spread on the water surface to stimulate the spread of user preferences. For each user, Ripple Network uses its past preference as a seed set in the knowledge graph, and then continuously expands the user's preferences along the relationship path in the knowledge graph, and then discovers his hierarchical potential interests concerning a certain candidate item. Multiple ``ripples'' overlap to form the user preference distribution in the knowledge graph. Compared with previous model results of CKE, DKN, PER, etc., the experimental results of this algorithm show better performance. Using this algorithm, this paper designs and implements a recommendation system based on the movie knowledge graph. The system includes administrator users and general users. The administrator can add, edit and delete movies and users, and general users can browse, collect and purchase films. The system can provide users with an efficient movie recommendation function, which is convenient for users to choose movies that match their preferences.
-\end{abstract}
-\keywordsen{Knowledge graph, recommender system, Ripple Network, user preferences, movie store}
diff --git a/macros/latex/contrib/bjfuthesis/example/contents/acknowledge.tex b/macros/latex/contrib/bjfuthesis/example/contents/acknowledge.tex
deleted file mode 100644
index 73f28999e0..0000000000
--- a/macros/latex/contrib/bjfuthesis/example/contents/acknowledge.tex
+++ /dev/null
@@ -1,10 +0,0 @@
-\chapter{致谢}
-论文的撰写工作已经接近尾声,在本文的撰写过程中我要特别感谢李冬梅老师的指导。在毕业论文完成期间,李冬梅老师多次对我的毕业论文提出意见与建议。同时,她多次询问论文的撰写进度,更是体现了她对学生无微不至的关怀。每每当我在论文编写中遇到艰深晦涩之处时,她都能不失时机而恰到好处地给予我最有用的提示与建议,使我的毕业论文得以顺利完成。
-
-其次,我要感谢我本科期间曾经为我上课的所有老师。比如,由我的概率论老师为我打下的数学基础才使我得以用最大后验概率估计法完成嵌入表示的学习算法,蓝海洋老师任教的网站设计课程是我完成电影推荐系统的基石。总之,我要感谢大学四年来所有老师孜孜不倦的谆谆教诲与夜以继日的无私奉献。
-
-接着,我还要感谢我的同学,是他们思维的火花激起了论文写作中的灵感。与他们的交流使我受益匪浅。
-
-最后,我还要感谢我的父母,他们一直以来对我生活上与学习上的鼓励与引导是我得益完成论文的关键要素。
-
-感谢所有在论文撰写工作中为我提供过帮助的人。
diff --git a/macros/latex/contrib/bjfuthesis/example/cover.pdf b/macros/latex/contrib/bjfuthesis/example/contents/cover.pdf
index ad03632921..e6486168e8 100644
--- a/macros/latex/contrib/bjfuthesis/example/cover.pdf
+++ b/macros/latex/contrib/bjfuthesis/example/contents/cover.pdf
Binary files differ
diff --git a/macros/latex/contrib/bjfuthesis/example/contents/mainbody.tex b/macros/latex/contrib/bjfuthesis/example/contents/mainbody.tex
deleted file mode 100644
index a05306da0a..0000000000
--- a/macros/latex/contrib/bjfuthesis/example/contents/mainbody.tex
+++ /dev/null
@@ -1,575 +0,0 @@
-\chapter{绪论}
-\section{研究背景与意义}
-一直以来,电影推荐都是在线流媒体播放平台发展中的一个重要问题,做好电影推荐可以使用户能在海量电影中选择满足其偏好的电影,提高用户满意度,从而提高在线流媒体播放平台的流量转化率及购买率,并最终提高在线流媒体播放平台的经济收益。近年来,随着电影行业及互联网行业的不断发展,在线电影数量不断增加,用户在海量电影中选择满足其偏好的电影的难度不断上升,性能优异的推荐算法成为了必然要求。自从在线流媒体播放平台出现以来,人们便开始尝试利用推荐算法来提高平台流量转化率,出现了诸如协同过滤的推荐算法\cite{he2017neural}。但这些算法未能解决数据稀缺性及冷启动问题,并不能为在线流媒体播放平台提供良好的推荐性能。为此,人们尝试将辅助信息融入推荐算法中以解决数据稀缺性及冷启动问题\cite{sun2017collaborative},并提高推荐性能。
-
-知识图谱是一种结构化的语义知识库,被用于迅速提供对物理世界中的概念和相互关系的描述,为解决推荐问题提供了新的方法\cite{zou2020survey},近年来受到国内外研究人员的广泛关注,成为了当前的研究热点。知识图谱通过对复杂的原始数据进行加工、处理及整合,转化成简单可靠、清晰明了的“实体,关系,实体”三元组,汇聚了大量的知识信息,从而能实现基于知识信息的响应和推理。
-
-知识图谱常被用于作为辅助信息添加至推荐算法中以提高推荐的准确性,这已是当前的研究焦点。
-
-近年来,随着在线流媒体播放平台的发展,电影推荐系统应运而生,它作为现代信息技术与传统电影产业相结合的产物,对流媒体播放平台的用户体验起着至关重要的作用,其可大幅度减少用户寻找满足其偏好电影的时间,并提高用户点击率与购买率,从而提高流媒体播放平台的经济收益。电影推荐系统能为用户推荐其感兴趣的电影,而减少对用户不感兴趣内容的显示,从而满足用户需求。但是,目前网络上绝大多数的电影推荐系统都使用传统的基于协同过滤的推荐算法,未能有效利用知识图谱等辅助信息,返回给用户的推荐结果中包含大量用户不感兴趣的电影,此外,还将一些本应推荐给用户的、用户感兴趣的电影丢弃了。造成这一问题的主要原因是推荐算法缺少有关新加入的无用户评分的电影以及新注册的用户的信息。
-
-对于海量的电影数据,为了实现准确地推荐给用户其感兴趣的电影,基于协同过滤的传统推荐算法是满足了不用户需求的,特别是对新注册用户,推荐的准确度无法得到保证。所以,本文旨在以知识图谱作为辅助信息,构建一个合适的电影推荐系统,并利用知识图谱中包含的丰富的辅助信息,最终实现一个电影推荐系统,为用户提供有效的、准确的电影推荐,从而提高用户满意度,提高平台收益。
-\section{国内外研究现状}
-\subsection{推荐系统研究现状}
-推荐系统由Jussi Karlgren于哥伦比亚大学在一份技术报告中以“数字书架”的名称被首次提及,而后自1994年起被在SICS的Jussi Karlgren、由Pattie Maes于MIT领导的研究团队、位于Bellcore的Will Hill以及同样位于MIT的Paul Resnick大规模实现并在技术性报告及出版物大量出现,以上人员与GroupLens的工作被授予了2010年ACM软件系统奖。
-
-自从在90年代中期首批有关协同过滤的论文出现后推荐系统便成为了重要的研究领域。工业界与学术界出现了众多有关建设新的推荐系统的工作。由于该领域包含众多的研究问题及其能帮助用户解决在过多信息中提供个性化推荐的实际应用,因此研究人员对该领域的兴趣依旧很高。
-
-当前,推荐列表在推荐系统将其产生的过程中的方式主要有两种:基于内容推荐与协同过滤推荐\cite{jafarkarimi2012naive}。基于内容推荐的算法使用一些有关物品的离散特征来推荐出拥有相似性的物品。协同过滤方法根据用户的历史行为(诸如其评价过的、点击过的、购买过的商品等)并与其他用户的相似决策结合来建立模形,这种算法可以被用于预测用户对物品的偏好程度。这两种方法常常被同时使用。
-
-此外,近来有越来越多的推荐算法被提出:多准则推荐系统。多准则推荐系统可以被定义为包含多标准偏好信息的推荐系统,而不是构建基于单一凭据的推荐系统。风险感知推荐系统,现存推荐系统的主要方法聚焦于基于上下文信息推荐最相关内容给用户,而没有将不相关内容打扰用户的推荐风险考虑在内。考虑推送推荐内容给用户而造成打扰用户的风险在某些情况下是需要考虑的,比如,在一个工作会议上或是在凌晨或是在晚上。而此类推荐算法为该问题提供了解决方案。
-
-现实中,大量使用的往往是混合推荐系统。其同时结合了协同过滤、基于内容过滤以及其他方法,这种混合式的推荐方法现在被大量使用。混合推荐可以在多种方式下被实现:将基于内容的和基于协同滤的预测模型被分开实现再将他们结合起来,亦或是将两种方法统一到同一模型中并一同实现。
-\subsection{知识图谱的研究现状}
-在知识表示与知识推理中,知识图谱是一个使用图结构的数据模型或拓扑结构的知识库。知识图谱常被用来存储基于内连接的对实体的描述——对象、事件、情形或抽象概念,并包括自由形式的语义。
-
-该词汇最早在1972年于一个有关构建模块化指令系统的课程中被提出。在80年代末,命名为知识图谱的项目主要聚焦于语义网络的设计。在2007年,DBpedia和Freebase作为基于图的常识性知识库被创立。DBpedia致力于从Wikipedia中抽取数据,而Freebase也包含一系列公开的数据集。它们两者都未将自己称为“知识图谱”,但实则构建并描述了有关知识图谱的相关概念。
-
-在2012年,谷歌正式提出了知识图谱的概念\cite{singhal2012introducing},并构建了基于DBpedia和Freebase以及其他数据源的谷歌知识图谱。他们后来将包括CIA World Factbook, Wikidata和Wikipedia的网站的RDFa, Microdata, JSON-LD内容从它们的索引网站上抽取并纳入知识图谱。与知识图谱相关联的实体与关系类型使用来自scheme.org的术语被更广泛地组织了起来。
-
-谷歌知识图谱中非常重要的一项是“自由库”,它是一个大型的协同工作知识库。“自由库”使用图结构作为其数据结构,可以将其视作一个有向图。谷歌知识图谱模型便是谷歌团队利用其在“自由库”之上的技术积累开发出来的\cite{漆桂林2017知识图谱研究进展}。
-
-自此,数个大型跨国公司开始利用它们的知识图谱,很快知识图谱流行起来,有免费的知识图谱,如DBpedia和NELL,以及商业性质的知识图谱,如谷歌知识图谱和Microsoft Satori。这些知识图谱被成功应用于问答系统、词向量嵌入与文字分类等。在2019年,IEEE将其关于“大数据”和“数据挖掘与智能计算”的年度国际会议融入有关知识图谱的国际会议。
-
-以上是知识图谱发展的主要进程。
-
-知识图谱一般表示为三元组的形式,即$G=(h,r,t)$,其中$G$为知识图谱,$h$和$t$是知识库中的实体集合,分别为三元组的头结点与尾节点\cite{徐增林2016知识图谱技术综述}。知识图谱也可以看作是一种结点对应实体、边对应关系的有向异构图。
-
-目前知识图谱的构建过程中主要使用了定义层次学习及事实学习。
-
-定义层次学习是通过使用机器学习等技术,从文字、图片等信息中提取知识表达中的定义,并确定其上下文信息。而知识图谱本质上是属于一种精炼的异构信息网络。利用定义层次学习可以在一定程度上完成对于知识图谱的构建。
-
-事实学习分为有监督的事实学习、半监督的事实学习以及无监督的事实学习。有监督的事实学习通过人为标注的语料信息输入以及深度学习方法来完成知识图谱的构建,而半监督的事实学习方法使用启发式地自动标注文本,但缺陷是训练数据集中可能含有大量的噪声数据。而无监督的学习方法主要使用基于深度学习模型的自然语言处理(NLP)的方法,无须人为干预,由训练模型自动完成信息抽取、信息整合。随着深度学习算法的发展,目前基于无监督的事实学习逐渐成为主流\cite{李涓子2017知识图谱研究综述}。
-
-目前出现了诸多使用以上理论方法设计的知识图谱嵌入算法:基于翻译的TransE\cite{bordes2013translating}、TransH\cite{wang2014knowledge}、TransR\cite{lin2017learning}和基于语义分析的DistMult\cite{yang2014embedding}等。
-
-目前,知识图谱在业界的应用已经取得了巨大成功\cite{曹倩2015知识图谱的技术实现流程及相关应用}:
-
-(1)搜索引擎技术。如前所述,知识图谱最早便是由谷歌提出以改善其搜索引擎的。在将知识图谱应用于搜索引擎之后,搜索引擎能对一些常见的搜索内容基于其使用的知识图谱信息快速给出搜索结果。同时,对于一些名词性的搜索内容,搜索引擎能使用知识图谱以知识卡片的形式给出其相关信息。研究表明,在谷歌将知识图谱技术融入其搜索引擎之后,用户点击进入维基百科的次数明显减少,说明利用知识图谱技术的搜索引擎可以更好的直接给出用户需要的信息而不需要用户再浏览其他网站。
-
-(2)智能问答。信息检索系统中非常常见的一种便是问答系统。问答系统在用户输入问题后能迅速给出用户需要的答案。而在将知识图谱技术应用于问答系统后,其回答的准确率有非常大的提升。目前苹果的智能助理Siri以及谷歌的智能助理谷歌助理(Google Assistant)都使用了知识图谱技术。
-
-此外,知识图谱还广泛应用于金融、医疗等多个领域。
-\subsection{基于知识图谱的推荐系统研究现状}
-由于传统的推荐系统无法解决稀缺性问题和冷启动问题,因此研究人员企图将辅助信息加入到推荐算法中以改善推荐性能。而这类辅助信息有社交网络、用户/物品属性、图像与上下文等。
-
-在数种类型的辅助信息中,知识图谱通常包含有更丰富的信息以及物品间的联系。图\ref{fig:enhanced-recommendation}中说明了知识图谱提供丰富的信息与物品间的连接,有利于提高推荐结果的准确性、多样性和可解释性。知识图谱可以从以下三个方面提高推荐性能:
-\begin{figure}
- \includegraphics[width=\textwidth]{enhanced-recommendation}
- \bicaption{基于知识图谱的电影推荐系统}{Knowledge graph enhanced movie recommendation system}\label{fig:enhanced-recommendation}
-\end{figure}
-
-(1)知识图谱引入了实体语义相关性,这可以帮助找到实体间潜在的联系并提高推荐物品的准确性。
-
-(2)知识图谱由各种类型的关系构成,这对合理地扩展用户兴趣并增加推荐商品的多样性是有益的。
-
-(3)知识图谱连接用户的历史记录及推荐的商品,因此提高了推荐系统的可解释性。
-
-将知识图谱作为辅助信息加入至推荐系统中是当前的热点问题,目前基于知识图谱构建推荐系统的方法主要有以下几类:
-
-(1)基于嵌入的方法。基于嵌入的方法通过知识图谱嵌入计算算法将知识图谱中的实体信息与关系信息映射为低维向量空间中的向量表示(嵌入表示)。而后推荐算法利用该嵌入表示来完成相应的计算,并给出推荐结果。目前将知识图谱中嵌入表示信息作为辅助信息的推荐模型有CKE\cite{zhang2016collaborative}、DKN\cite{wang2018dkn}以及SHINE\cite{wang2018shine}等。CKE是微软在 KDD2016 年发表的,其模型结构在原有系统过滤得到$U$, $V$向量的基础上,将物品的嵌入与其他描述信息相结合,这些信息主要有:
-采用 TransR 算法嵌入得到的知识图谱,图谱内每个实体嵌入表示被提取为物品的结构化向量信息。
-采用SDAE模型得到物品描述性文本的文本嵌入表示。
-采用SCAE模型得到物品相关图像的视觉嵌入表示。DKN是之前同样由微软团队在WWW2018会议上发表的。它是一个主要针对新闻推荐任务提出的框架,知识图谱用于辅助计算新闻标题的嵌入表示。DKN提出对新闻标题内每一个关键实体,在知识图谱内找到其实体嵌入和上下文嵌入。
-SHINE设计深度自编码器来嵌入语义网络,社交网络并进行推荐。其为用户-物品的交互使用自动编码器并计算用户感兴趣的概率。此外,嵌入表示可以包含实体的独热编码\cite{koren2008factorization}、词汇集\cite{wang2018dkn}、上下文信息\cite{sun2017collaborative}或属性\cite{wang2018shine},而选择哪一种嵌入向量的计算方式取决于其应用场合。
-
-(2)基于路径的方法。基于路径的方法将知识图谱作为异构信息网络,主要是通过知识图谱中的路径关系信息来辅助推荐算法完成推荐相关的计算工作。目前基于知识图谱中路径信息的推荐模型有HIN\cite{zhao2017meta}、RKGE\cite{sun2018recurrent}等。HIN是2017年在KDD上提出的,与PER\cite{yu2014personalized}类似,都将知识图谱作为异构信息网络。它针对Yelp和Amazon数据集分别设计了元路径,并得到了L个评估函数。并在建模时使用FM模型,使用FM损失函数组进行梯度下降,并最终得到推荐结果。RKGE模型使用了基于循环神经网络的方法。在人为定义元路径并抽取出所有路径之后,对每种元路径都使用循环神经网络模型来抽取并推理其路径中所包含的信息。
-
-(3)混合式方法。基于嵌入的方法未能充分利用实体间的关系模式信息,而基于路径的方法仅考虑了实体间的语义连通信息,未能有效使用用户/物品本身的语义信息。因此,目前出现了混合式方法,即同时结合了基于嵌入的方法与基于路径的方法的优点。混合式方法是当前的研究热点与焦点,使用该方法的典型模型有AKUPM\cite{tang2019akupm}和RCoLM\cite{cao2019unifying}等。AKUPM是通过注意力机制增强的推荐模型,RCoLM则是基于联合学习并以任务为导向的推荐算法。本文实现的电影推荐系统基于文献\parencite{wang2018ripplenet},其所使用的算法模型是也属于混合式方法。
-\section{本文的主要研究内容}
-本文在推荐算法、知识图谱和基于知识图谱的推荐算法的相关研究基础上,做了以下三方面的研究:
-
-(1)对推荐系统所需的数据进行采集和处理,使用“MovieLens 1M Dataset”作为数据集,此外还从IMDb及豆瓣网爬取了相关电影数据并进行处理,作为本文的研究对象。
-
-(2)根据文献\parencite{wang2018ripplenet}提出的算法,实现了基于知识图谱的涟漪网络推荐算法,此算法能根据用户的历史行为为用户进行电影推荐。不同于文献\parencite{wang2018ripplenet}中仅使用用户评分计算用户偏好,本文在用户偏好的计算过程中还结合了用户收藏,这在一定程度上缓解了冷启动问题并改进了推荐性能。此外,将涟漪网络算法与其他基于知识图谱的推荐算法(DKN\cite{wang2018dkn}、CKE\cite{zhang2016collaborative} 、PER\cite{yu2014personalized}、SHINE\cite{wang2018shine}、LibFM\cite{rendle2012factorization}和Wide\&Deep\cite{cheng2016wide}等)进行了性能比较。
-
-(3)实现了一个基于知识图谱的电影推荐系统,该系统能够根据用户的历史行为(评分、收藏等)来为用户进行电影推荐。该系统分为管理员、未登录用户、普通登录用户。管理员能增加、修改和删除电影和普通用户;未登录用户能根据电影分类查看电影列表以及查看电影详情;普通登录用户除了能进行未登录用户的所有操作外,还能购买、收藏及为电影评分。
-\section{论文结构}
-本论文一共分为五个章节。
-
-第1章是绪论。简明介绍知识图谱作为辅助信息在推荐算法中的作用以及推荐算法对在线流媒体播放平台的作用,同时介绍了推荐系统、知识图谱和基于知识图谱的推荐系统的发展和应用,并说明了本文的主要工作。
-
-第2章是相关理论和技术。介绍了目前知识图谱和推荐系统的研究现状,并对传统的推荐算法与加入辅助信息的推荐算法作了较为细致的分类与阐述。同时还介绍了本文实现的电影推荐系统所使用的技术栈,诸如数据库、前端架构、后端架构等。
-
-第3章是涟漪网络。介绍了涟漪网络算法,以及计算相关实体嵌入的过程中使用的深度学习算法,并对以上算法进行了讨论。最后,还对涟漪网络推荐算法的准确度进行了测试。
-
-第4章是电影推荐系统。介绍了以涟漪网络算法为基础构建的电影推荐系统:介绍了系统架构、系统功能、电影推荐流程以及如何保证该系统的安全性。
-
-第5章是研究结论和展望。总结了涟漪网络算法的设计与实现、电影推荐系统的功能,并指出了其中可以改进的地方。
-\chapter{相关理论和技术}
-\section{知识图谱}
-\subsection{知识图谱的概念及发展进程}
-知识图谱,是一种知识可视化或知识领域映射地图,是显示知识发展进程与结构关系的一系列三元组(实体,关系,实体),用可视化技术描述知识信息及其载体,挖掘、分析、建立、绘制和可视化知识以及实体之间的相互关系。
-
-知识图谱是谷歌于2012年提出的,目的是为了增强其搜索引擎。而后微软于2013年7月发布了Microsoft Satori知识图谱。除传统搜索服务提供商之外,包括Apple,Facebook,IBM等互联网企业也在探索该领域。此外,业界也出现了社区构建的开源知识图谱,如DBpedia,NELL和Wikidata等。以Freebase、WordNet和GeneOntology等为例的知识图谱已成为支持人工智能相关应用的非常重要的资源。
-\subsection{知识图谱的构建方法}
-知识图谱是由多实体结点和不同关系边构成的多关系图,一个边是一个事实三元组(头结点,关系,尾结点),记为$(h,r,t)$。而知识图谱的构建便是寻找这样的三元组。
-
-在过去十年间,出现了诸多构建大型知识图谱的方法,然而,还没有清晰准确的构建知识图谱的范式。主要有两个困难:(1)知识图谱是符号化的逻辑系统而知识图谱的应用常常包含在连续空间中的计算;(2)在一张知识图谱上进行知识聚合是困难的。
-
-目前,知识图谱主要通过以下3个步骤来完成构建:
-
-(1)信息抽取。即从各类型的源数据中抽取出实体(概念)、实体间的关系,并在此基础之上形成确切的知识表达。
-
-(2)知识融合。对新获得的知识进行整合,以完成消歧义。
-
-(3)知识加工。经过质量核查后将融合后的新知识的正确的部分加入至知识图谱中。
-\subsection{知识图谱的应用}
-知识图谱以更接近人类认知的方式为互联网的信息表达提供了一种新的方式,而且提供了一种更益于组织与利用海量数据的方式。当前知识图谱主要用于推荐系统、搜索引擎、个人助理以及问答系统。
-\section{推荐系统}
-推荐系统是内容过滤系统的一个子集,被广泛使用于多个领域,它向用户推荐满足其偏好的物品,并通常具有为视频或音乐服务生成推荐清单的表现形式。
-\subsection{传统的推荐系统}
-传统的推荐系统主要分为基于内容的推荐系统、基于协同过滤的推荐系统和混合推荐系统\cite{黄立威2018基于深度学习的推荐系统研究综述}。基于内容的推荐系统主要用于文本相关的项目,因为内容常常是使用关键字来描述的。该算法通过计算相关物品的离散特征,然后推荐具有与用户历史偏好物品类似特征的有关物品。基于协同过滤的推荐系统主要通过将具有与目标用户相似特征的用户所交互过的物品推荐给目标用户。
-
-基于内容的推荐与基于协同过滤的推荐的有关区别可以通过比较两个流行音乐推荐系统的实现方式看出。(1)潘多拉音乐使用一个基于内容推荐的推荐算法。它根据艺人或歌曲的属性来生成一个包含相似风格歌曲的电台,并且该电台的内容会根据收听用户的反馈进行调整。当用户对一首歌曲“不感兴趣”时该算法将弱化该歌曲的一些属性;而当用户喜欢一首歌曲时,将强化一些属性。并且该算法会根据该属性调整歌曲的顺序,若属性的值越过一个阀值时推荐算法便将某一歌曲从列表中删除。(2)“终级fm”使用协同过滤的推荐算法。它记录用户经常收听的乐队和歌手,然后与其它用户的有关行为进行比较,建立一个电台,并以此推荐歌曲。“终级fm”会给用户推荐其他具有相似特征用户的播放列表(并保证目标用户未收听过)。
-
-基于内容的推荐与基于协同过滤的推荐各有优缺点。潘多拉音乐所使用的基于内容推荐的推荐算法是根据物品本身的性质来进行推荐的,因此不需要用户信息就可以有较好的准确度。但该算法严重依赖物品本身的特性,因此局限性较大,推荐的内容都是与种子集相关的,推荐结果的多样性较低。而“终级fm”使用的协同过滤算法需要根据用户与物品的交互来生成推荐结果,因此需要大量的用户数据,存在数据稀缺性问题与冷启动问题。
-\subsection{基于知识图谱的推荐系统}
-基于内容推荐与协同过滤推荐两者均存在一些局限性,为了提高推荐的准确性,解决传统推荐算法的数据稀缺性与冷启动问题,研究者将一些辅助信息加入至推荐算法中,通常这些辅助信息包括上下文信息、用户或物品的属性、图片和社交网络\cite{常亮2019知识图谱的推荐系统综述}\cite{秦川2020基于知识图谱的推荐系统研究综述}。
-
-而随着知识图谱的发展,将知识图谱作为辅助信息来提高推荐系统的性能已经成为了热门的研究方向。将知识图谱作为辅助信息加入推荐算法的优点有:
-
-(1)提高推荐系统的准确性。知识图谱可以表示不同实体间的关系,可以将物品及其相关属性对应于知识图谱之中,从而推荐算法可以理解物品之间的关系。此外,用户与用户间的关系信息也可以映射至知识图谱之中,从而推荐算法可以更准确地分析物品与物品间的关系、用户与物品之间的关系。
-
-(2)提高推荐系统的可解释性。由于推荐结果依照知识图谱中的关系信息,因此可以由知识图谱中的关系路径得到推荐系统给出推荐结果的原因。
-
-目前主要的基于知识图谱的推荐算法有基于嵌入的方法、基于路径的方法以及混合式方法:
-
-(1)基于嵌入的方法。基于嵌入的方法使用知识图谱的信息来完善实体的嵌入表示。为了将知识图谱中的信息添加至推荐算法中来辅助推荐,需要使用知识图谱嵌入表示算法(Knowledge Graph Embedding, KGE)表计算实体嵌入(实体嵌入指由知识图谱中的信息得到的在低维向量空间中的向量表示)。KGE算法有TransE\cite{bordes2013translating}、TransH\cite{wang2014knowledge}、TransR\cite{lin2017learning}和DistMult\cite{yang2014embedding}等。而推荐算法利用该嵌入表示来进行相关计算,从而对用户进行物品推荐。
-
-(2)基于路径的方法\cite{lin2015modeling}\cite{guu2015traversing}\cite{toutanova2016compositional}。基于路径的方法将知识图谱视为异构信息网络。而推荐系统利用该异构信息网络寻找实体间的关系,从而完成推荐。
-
-(3)混合式方法。基于嵌入的方法未能充分利用实体间的关系模式信息,而基于路径的方法仅考虑了实体间的语义连通信息,未能有效利用用户/物品本身的语义信息。混合式方法结合了基于嵌入的方法与基于路径的方法的优点,该方法是当前的研究热点与焦点,使用该方法的典型模型有AKUPM\cite{tang2019akupm}和RCoLM\cite{cao2019unifying}等。本文实现的算法属于混合方法。
-\section{系统开发技术}
-\label{sec:tech-stack}
-\subsection{数据采集技术}
-电影推荐系统使用的数据来自“MovieLens 1M Dataset”\footnote{https://grouplens.org/datasets/movielens/1m/}数据集,此外还从IMDb\footnote{https://www.imdb.com/}及豆瓣网\footnote{https://www.douban.com/}爬取了相关电影数据并进行处理作为本文的研究对象。
-
-在数据采集的过程中,使用Scrapy框架进行了数据爬取,爬取的数据包括电影名称、电影封面、预告片图片、电景情节介绍、导演、演员以及剧作家。
-
-最终,总计爬取了3684部电影的数据。其中,从IMDb爬取了3494条电影数据,从豆瓣爬取了190条电影数据(由于豆瓣网限制了每IP访问量故爬取的数据较少)。
-\subsection{数据存储技术}
-本系统使用MongoDB与Neo4j存储数据。
-
-\noindent (1)MongoDB
-
-MongoDB是一个新兴的非关系型存储的分布式存储数据的数据库,属于NoSQL,与MySQL等传统的关系型数据库相比,它提供更好的高并发支持,具有高可靠性的优点。与此同时,得益于其基于文档储存的特点,相比较传统的关系型数据库,它的存储结构更灵活。
-
-在本系统中,MongoDB存储普通用户数据、管理员数据、电影数据等。
-
-\noindent(2)Neo4j
-
-Neo4j是一个具有高性能的图数据库,它将结构化的数据信息储存在网络上而不是存储在表中。它具有健壮和成熟的数据库的所有特点。虽然Neo4j是一个新兴的数据库,但它已在具有超过1亿节点、关系和属性的产品中得到了应用,充分体现了其高性能、高可靠性的特点。
-
-在本系统中,最终需存储的图结点有182011个,需存储的边有1241995条。如果将它们存储在传统的关系型数据库中,会因大量的连接查询导致极大的性能开销,表现为查询耗时久。Neo4j对图数据处理做了优化,因此查询等操作可以在较短的时间内完成,故本系统将知识图谱数据存储在Neo4j中而不是关系型数据库中。
-
-\subsection{后端技术}
-本系统使用Flask框架作为网站后端框架。Flask是一个Python编写的轻量级微框架。它具有轻量、便捷、可扩展等特点。系统使用Flask框架充分利用了其便捷、可扩展以及开发便捷的特点,与本系统要求相符。
-
-系统使用表现层状态转换(REST)风格的应用程序接口(API)作为前后端的交互接口。表现层状态转换(Representational State Transfer,REST)是一种基于HTTP协议的软件交互体系结构样式,该协议是由Roy Thomas Fielding博士在2000年的博士论文中引用的\cite{fielding2000architectural},目的是促进不同的软件/程序的开发。在网络上互相传输数据。表示层状态转换基于超文本传输​​协议(HTTP)的一组约束,该协议是一种旨在提供万维网服务的软件构造样式。符合或兼容此体系结构样式(简称为REST或RESTful)的网络服务允许客户端发出使用统一资源标识符访问和操作网络资源的请求,这些资源与一组预定义的操作一致。因此,表示层状态转换提供了Internet上计算机系统之间相互使用资源的互操作性。与其他类型的网络服务(例如SOAP服务)相比,它们使用自己定义的一组操作来访问网络资源。
-
-得益于本系统使用了REST风格的API,本系统能更有效地使用缓存来提升响应速度,同时前后端间的通讯的无状态性可以让不同的服务器处理一连串请求中不同的请求,提高了本系统的可扩展性。与此同时,得益于REST风格语义化的接口,使前后端交互接口更清晰明了,使接口的使用者能更高效便捷地进行相关的开发工作。
-\subsection{前端技术}
-本系统前端使用Angular框架。Angular(通常指“Angular 2+”或“Angular v2及以上”)是一个基于TypeScript的开源网络应用框架,它的开发由Google的Angular团队领导同时也有个人及其他公司维护。Angular完全从相同团队开发的AngularJS重新编写而来。Angular常常作为MEAN技术栈的一部分。MEAN技术栈指MongoDB数据库、Express.js网络服务器框架、Angular/AngularJS以及Node.js服务器运行时。不同于MEAN技术栈,本系统将其中的“E”(指Express.js网络服务器框架)替换为了Flask网络服务器框架。
-
-通过使用Angular框架,本系统具有一个现代化、模块化、响应式的网页架构。同时借助于Angular Material Components官方组件库,本系统前端UI符合材料设计(Material Design)。
-\chapter{基于涟漪网络知识图谱的推荐算法}
-\label{ch:offline-recommendation}
-\section{涟漪网络}
-本算法基于文献\parencite{wang2018ripplenet}实现,并在其基础上进行了一定的改进:文献\parencite{wang2018ripplenet}中计算用户偏好时并未考虑用户收藏,本文在计算用户偏好时,将用户收藏考虑在内,这在一定程度上缓解了数据稀缺性问题和冷启动问题并改进了推荐性能。
-\subsection{架构}
-涟漪网络的总体架构如图\ref{fig:ripplenet-framework}所示,图上方的知识图谱中展示了由用户交互产生的涟漪。涟漪网络以一个用户$u$和一个电影$v$作为输入,并输出用户$u$与电影$v$之间产生交互的概率。对输入用户$u$而言,其历史交互记录$V_u$是知识图谱中的种子集,而后沿着知识图谱中的关系边形成多个涟漪集$S_u^{k}\ (k=1, 2, \dots, H)$。第k个涟漪集是种子集$V_u$经过$k$跳得到的知识三元组。然后迭代地利用这些涟漪集与电影$v$的嵌入表示(黄色的块)计算出用户$u$对电影$v$的的响应(绿色的块),最后结合得到用户的最终嵌入表示(灰色的块)。最终,利用用户$u$与电影$v$的嵌入表示计算出用户$u$对电影$v$感兴趣的预测概率$y_{uv}$。
-\begin{figure}
- \includegraphics[width=\textwidth]{ripplenet-framework}
- \bicaption{涟漪网络的总体架构}{The overall framework of the Ripple Network}\label{fig:ripplenet-framework}
-\end{figure}
-\subsection{涟漪集}
-\begin{figure}
- \includegraphics[width=\textwidth]{illustration-of-ripple-sets}
- \bicaption{电影知识图谱中由“阿甘正传”激发的涟漪集}{Sets of ripples of “Forest Gump” in Knowledge Graph of movies}\label{fig:illustration-of-ripple-sets}
-\end{figure}
-知识图谱常常含有丰富的事实信息与实体间的联系。比如,图\ref{fig:illustration-of-ripple-sets}(图中不同颜色的圆圈表示不同跳数的涟漪集,越浅的蓝色代表种子集与该区域内实体的关联程度越低)中电影“阿甘正传”与“罗伯特·泽米吉斯”相连,它们之间的联系为“罗伯特·泽米吉斯”是电影“阿甘正传”的导演。而“回到未来”也与“罗伯特·泽米吉斯”相连。因此,如果一个用户与电影“阿甘正传”交互过,则他很有可能也对“回到未来”感兴趣。为了描述用户在知识图谱中分层次的潜在偏好集,递归定义用户$u$的$k$跳相关实体如下:
-
-\textbf{定义1(相关实体集)} 给定交互矩阵$\Upsilon$与知识图谱$G$,则用户$u$的$k$跳相关实体集的定义为式\eqref{relevant-entities}。
-
-\begin{equation}
- E_u^k=\{t|(h, r, t)\in G \text{且} h\in E^{k-1}_u\}, k = 1, 2, \dots, H\label{relevant-entities}
-\end{equation}
-
-式\eqref{relevant-entities}中,$E_u^0=V_u=\{v | y_{uv}=1\}$是用户的历史偏好集(历史偏好集是指用户在最高为5的评分中给出的评分$\geqslant$4的物品以及用户已加入收藏的物品),可以看作是用户$u$在知识图谱中的种子集。
-
-相关实体集可以看作是用户的历史偏好集在知识图谱中的自然扩展。给定相关实体集的定义,以下定义用户$u$的$k$跳涟漪集:
-
-\textbf{定义2(涟漪集)}用户$u$的$k$跳涟漪集可以看作是知识图谱中以$E^{k-1}_u$为起点的知识三元组,定义如式\eqref{ripple-set}所示。
-
-\begin{equation}
- S_u^k = \{(h, r, t)|(h, r, t)\in G \text{且} h\in E^{k-1}_u\}, k = 1, 2, \dots, H\label{ripple-set}
-\end{equation}
-
-“涟漪”这个词有两重意思:(1)对由多个雨点产生的真实涟漪的模拟,用户对电影的潜在兴趣集在知识图谱中由近及远地传递。这一过程如图\ref{fig:illustration-of-ripple-sets}所示。(2)用户的潜在兴趣随着知识图谱中传递的跳数$k$的增大逐渐递减。图\ref{fig:illustration-of-ripple-sets}中蓝色的变浅显示了潜在兴趣递减的过程。
-
-一个可能出现的问题是在跳数$k$增加的过程中涟漪集的大小可能过大。为了解决这个问题,注意到:
-
-(1)在真实使用的知识图谱中大量的实体是沉没实体,意思是它们只有传入链路而没有传出链路。
-
-(2)在电影推荐的具体情境下,关系可以限制在情境相关的分类中以减少涟漪集的数量并提高实体间的相关度。
-
-(3)最大跳数$H$通常在实际应用中不会过大,因为离用户历史偏好集较远的实体会带来更多的错误推荐而不是更丰富的推荐结果。
-
-(4)在涟漪网络中,我们可以对一个固定大小的邻集而不是对完整的涟漪集采样从而更进一步地减小计算工作量。设计这样的采样器是一个重要的工作,尤其是非统一的采样器能更好地捕获用户的分等级的潜在兴趣。
-\subsection{偏好扩散}
-\label{sec:osum}
-传统的协同过滤算法是通过学习用户与物品间的潜在联系来完成推荐,而在涟漪网络算法中,这一过程是通过偏好扩散完成的:对每个用户,涟漪网络将他的过往兴趣视为知识图谱中的种子集,然后沿知识图谱中的路径不断地拓展用户的潜在兴趣集,进而得到按等级划分的关于候选物品的潜在兴趣集。我们利用现实生活中的由雨滴产生的涟漪在水面上扩散来模拟偏好扩散的过程,其中多个“涟漪”重叠形成基于知识图谱的用户偏好分布。
-
-如图\ref{fig:ripplenet-framework},每部电影都有一个嵌入表示$v$,$v\in \mathbb{R}^{d}$,其中$\mathbb{R}$是实数集,$d$是嵌入表示向量的维数。给定电影的嵌入表示$v$以及用户$1$跳涟漪集$S_u^{1}$,可以利用电影$v$、$S_u^{1}$中的三元组中头节点$head_i$以及该三元组中的关系$r_i$来计算出电影$v$和实体$head_i$之间的相关度,如式\eqref{eq:item-entity-relevance}所示。
-
-\begin{equation}
- p_i=softmax(v^TR_ih_i)=\frac{exp(v^TR_ih_i)}{\sum_{(h, r, t)\in S_u^1} exp(v^TRh)}\label{eq:item-entity-relevance}
-\end{equation}
-
-式\eqref{eq:item-entity-relevance}中,$R_i\in \mathbb{R}^{d\times d}$与$h_i\in \mathbb{R}^d$分别是关系$r_i$和头节点$h_i$的嵌入表示。相关度$p_i$为向量空间$R_i$中的电影$v$与实体$h_i$之间的相似度。同时还考虑了关系信息的嵌入表示矩阵在计算电影$v$与实体$h_i$之间的相似度,因为不同电影-实体对之间的相似度在不同关系的场景下可能有所不同。比如,“阿甘正传”与“回到未来”在导演方面有很高的相似度,但它们在体裁或剧作家方面可能没有联系。
-
-在完成相似度计算之后,将$S_u^{1}$中三元组的尾节点根据计算得到的相似度进行加权求和,得到向量$o^{1}_u$,如式\eqref{eq:o1}所示。
-
-\begin{equation}
- o^1_u=\sum_{(h_i,r_i,t_i)\in S_u^1}p_it_i\label{eq:o1}
-\end{equation}
-
-式\eqref{eq:o1}中,$t_i\in \mathbb{R}^{d}$,$t_i$是事实三元组中的尾节点。向量$o^{1}_u$可以视为用户偏好集$V_u$关于电影$v$的$1$次响应。与协同过滤算法类似的是,它根据用户交互过的物品来表示用户嵌入而不是使用单独的参数来表示用户,从而减少了参数数量。通过式\eqref{eq:item-entity-relevance}与式\eqref{eq:o1},用户的偏好从其交互过的电影(即种子集)成功在知识图谱中进行了一次扩散,这称为涟漪网络中的偏好扩散。
-
-可以将式\eqref{eq:item-entity-relevance}中的$v$替换为$o_u^1$,我们可以再次进行偏好扩散以得到用户的2次响应$o_u^2$。以此类推,最终我们可以将该用户的偏好集扩散至$H$跳,得到用户的涟漪集$S_u^{i}, i=1,\dots,H$。从中可以得到用户的多次响应$o^{1}_u, o^{2}_u, o^{H}_u$。用户$u$关于电影$v$的嵌入表示是通过结合所有的不同响应并计算得到的,如式\eqref{eq:osum}所示。
-\begin{equation}
- u=o_u^1+o_u^2+\dots+o_u^H\label{eq:osum}
-\end{equation}
-
-尽管最后一跳的用户响应中理论上包含了所有之前得到的信息,但是对$o^k_u$进行求和仍然是有必要的,因为之前得到的用户响应可能在偏好传递的过程中稀释了,因此仅使用最后一跳的响应不能很好地表示用户嵌入。最终,利用用户嵌入与电影嵌入,计算出用户对电影感兴趣的概率,如式\eqref{eq:predicted-possibility}所示。
-\begin{equation}
- y_{uv}=\zeta(u^Tv)\label{eq:predicted-possibility}
-\end{equation}
-
-其中,$\zeta(x)=\frac{1}{1+exp(-x)}$是sigmoid函数。
-\section{学习算法}
-在涟漪网络算法中,我们的目标是通过式\eqref{eq:predicted-possibility}求出用户对电影感兴趣的概率。但是,为了将其计算出来我们需要先求出所有物品、用户以及关系的嵌入表示,如第\ref{sec:osum}节中所述,用户的嵌入表示可以通过其涟漪集来代替,以此消元。但物品及关系的嵌入表示却是需要求出来的。
-
-为了求出物品及关系的嵌入表示,这里使用最大后验概率估计的方法。
-
-我们的目标是在已经得到知识图谱$G$以及用户与电影的交互矩阵$\Upsilon$的情况下最大化模型参数$\Gamma$,如式\eqref{eq:max}所示。
-\begin{equation}
- max\ p(\Gamma |G,\Upsilon)\label{eq:max}
-\end{equation}
-
-式\eqref{eq:max}中,参数$\Gamma$包含了全部的实体、关系和电影的嵌入表示。可以将式\eqref{eq:max}等价于最大化式\eqref{eq:equal-max}。
-
-\begin{equation}
- p(\Gamma |G,\Upsilon)=\frac{p(\Gamma,G,\Upsilon)}{p(G,\Upsilon)}\varpropto p(\Gamma)\centerdot p(G|\Gamma)\centerdot p(\Upsilon|\Gamma,G)\label{eq:equal-max}
-\end{equation}
-
-根据贝叶斯公式,在式\eqref{eq:equal-max}中,第一项$p(\Gamma)$代表模型参数的先验概率。设$p(\Gamma)$为均值为0,方差为对角协方差矩阵的正态分布,如式\eqref{eq:normal-distribution}所示。
-
-\begin{equation}
- p(\Gamma)=N(0,\lambda_1^{-1}I)\label{eq:normal-distribution}
-\end{equation}
-
-式\eqref{eq:equal-max}中,$p(G|\Gamma)$是给定$\Gamma$的知识图谱的最大似然函数。最近,有研究者提出了多种计算知识图谱嵌入的方法,包括基于距离的方法和基于语义匹配的方法。在本算法中,使用三路张量分解的方法来建立知识图谱嵌入的最大似然函数,如式\eqref{eq:term2}。
-
-\begin{equation}
- p(G|\Gamma)=\prod_{(h,r,t)\in E\times R\times E}p((h,r,t)|\Gamma)=\prod_{(h,r,t)\in E\times R\times E}N(I_{h,r,t}-h^TRt,\lambda_2^{-1})\label{eq:term2}
-\end{equation}
-
-式\eqref{eq:term2}中,若$I_{h,r,t}\in G$则标志$I_{h,r,t}$等于1,否则为0。式\eqref{eq:equal-max}中的第三项是给定$\Gamma$与知识图谱的似然函数,可以看作伯努利分布的累乘,如式\eqref{eq:bernoulli}。
-
-\begin{equation}
- p(\Upsilon|\Gamma,G)=\prod_{(u,v)\in \Upsilon}\zeta(u^Tv)^{y_{uv}}\centerdot (1-\zeta (u^Tv))^{1-y_{uv}}\label{eq:bernoulli}
-\end{equation}
-
-对式\eqref{eq:equal-max}取负对数,有如式\eqref{eq:term3}所示的损失函数:
-\begin{multline}
- min\ L=-log(p(\Upsilon|\Gamma,G)\centerdot p(G|\Gamma)\centerdot p(\Gamma))\\
-=\sum_{(u,v)\in \Upsilon}-(y_{uv}log\ \zeta(u^Tv)+(1-y_{uv}log(1-\zeta(u^Tv))))\\
-+\frac{\lambda_2}{2}\sum_{r\in R}\|I_r-E^TRE\|_2^2+\frac{\lambda_1}{2}(\|V\|^2_2+\|E\|^2_2+\sum_{r\in R}\|R\|^2_2)\label{eq:term3}
-\end{multline}
-
-式\eqref{eq:term3}中,$V$和$E$是所有电影与实体的嵌入表示,$I_r$是在知识图谱中对关系$r$的标志向量$I$的分向量。在式\eqref{eq:term3}中,第一项是交互矩阵$\Upsilon$与涟漪网络的估测值之间的交叉熵,第二项是真实的知识图谱分向量$I_r$以及人为构建的指示矩阵$E^{T}RE$之间的均方误差,最后一项是为防止过拟合加入的正则项。
-
-直接求解上式来得到参数$\Gamma$是不可能的,因此可以使用随机梯度下降算法递归地优化损失函数来求解模型参数,而后再计算参数$\Gamma$的损失函数的梯度,并根据采样得到的一小批数据反向传递,然后更新参数并最终得到参数$\Gamma$。
-\section{分析}
-\subsection{可解释性}
-可解释的推荐系统旨在阐释为什么用户会对一件物品感兴趣,这帮助提升用户对推荐结果的满意度以及对推荐系统的信任。对推荐结果的解释通常基于标签、语义分析等。因为涟漪网络探索用户基于知识图谱的兴趣,因此它提供了一种基于知识图谱中的关系路径来阐述推荐结果的全新方式。比如,在图\ref{fig:illustration-of-ripple-sets}中,当用户对“幸福终点站”感兴趣,则该用户也可能对“荒岛余生”感兴趣。因为在知识图谱中,“汤姆·汉克斯”与“幸福终点站”相连,关系是演员,而“汤姆·汉克斯”与“荒岛余生”也相连,关系也是演员,换句话说,“荒岛余生”与“幸福终点站”有相同的演员。这便解释了用户对“幸福终点站”和“荒岛余生”同时感兴趣的原因。涟漪网络算法通过在知识图谱中寻找与用户交互过的电影(种子集)相连的物品,并不断扩散,最终确保推荐结果具有较高的准确性。
-\subsection{涟漪重叠}
-在涟漪网络中,一个可能的问题是涟漪集中的电影非常多,从而在偏好传递的过程中不可避免地导致用户的真实潜在偏好信息被稀释。然而,用户点击记录中不同的电影常常高度重叠(从种子集出发到达一部电影常常有不止一条路径),这在很大程度上避免了真实潜在偏好信息被稀释的问题。比如,在图\ref{fig:illustration-of-ripple-sets}中,如果一个用户喜欢“阿甘正传”,则他也可能喜欢“荒岛余生”。在该知识图谱中,从“阿甘正传”到“荒岛余生”有两条路径:“阿甘正传-U.S.-荒岛余生”与“阿甘正传-汤姆·汉克斯-荒岛余生”,这正是涟漪重叠的表现。
-\section{测试}
-\subsection{数据集}
-本测试使用“MovieLens 1M Dataset”数据集。该数据集由电影信息、用户信息以及用户对电影的评价三部分组成。其中,含有电影数据3883条、用户数据6040条以及1000209条用户对电影的评价数据。因该数据集数据量适中,数据准确可靠,因此在推荐系统的性能测试中被广泛使用。
-
-本测试使用的知识图谱来自Microsoft Satori,是依据“MovieLens 1M Dataset”中的电影名称从Microsoft Satori中提取相关的节点的与关系数据得到的。
-\subsection{基线}
-本测试中,会将本算法的测试结果与以下算法的相比较:
-
-DKN\cite{wang2018dkn}是由微软团队在WWW2018会议上发表的。它是一个主要针对新闻任务提出的框架,知识图谱用于辅助计算新闻标题的嵌入表示。DKN提出对新闻标题内每一个关键实体,在知识图谱内找到其实体嵌入和上下文嵌入。
-
-CKE\cite{zhang2016collaborative}是微软在KDD2016年发表的,其模型结构在原有系统过滤得到$U$,$V$向量的基础上,将物品的嵌入与其他描述信息相结合,这些信息主要有:
-采用TransR算法计算知识图谱嵌入表示,知识图谱内每个实体嵌入表示被提取为物品的结构化向量信息。
-采用SDAE模型得到物品描述性文本的文本性嵌入表示。
-采用SCAE模型得到物品相关图像的视觉嵌入表示。
-
-SHINE\cite{wang2018shine}设计深度自编码器并嵌入语义网络以及社交网络来进行推荐。其为用户-物品的交互使用自动编码器并刻画用户感兴趣的概率。
-
-PER\cite{yu2014personalized}是以基于路径的方法来将知识图谱作为辅助信息中的比较经典的算法。其提出的元路径可以为推荐系统提供可靠的方向,但是需要使用者了解领域内知识,进行人为路径设计。
-
-LibFM\cite{rendle2012factorization}是一个广泛使用的在CTR场景中的分解推荐模型。
-
-Wide\&Deep\cite{cheng2016wide}是一个结合线性路径的推荐模型。类似于LibFM,我们将用户、物品及实体的嵌入表示作为其输入。
-\subsection{测试步骤}
-在涟漪网络中,设置跳数$H=2$。根据实验结果,较大的跳数几乎无法提高性能却会造成较大的计算开销。我们将数据划分为训练集、评估集与测试集,按照6:2:2的比例进行分配。实验进行5次,计算准确度以及AUC然后取平均值。
-\subsection{结果}
-测试结果如表\ref{tab:acc-auc}中所示,总体上涟漪网络算法的性能最佳,其次是Wide\&Deep算法,说明他们可以充分利用知识图谱中的有效信息来辅助推荐算法。而表现最差的是PER算法,这可能是因为手工定义的元路径在电影推荐方面效果较差。
-\begin{table}
- \bicaption{在兴趣预测计算中的AUC和准确度}{AUC and ACC in interest prediction}\label{tab:acc-auc}
- \begin{tabular}{lcl}
- \toprule
- 算法 & AUC & 准确度 \\
- \midrule
- 涟漪网络 & 0.899 & 0.835 \\
- DKN & 0.655 & 0.589 \\
- CKE & 0.796 & 0.739 \\
- SHINE & 0.778 & 0.732\\
- LibFM & 0.892 & 0.812\\
- Wide\&Deep & 0.903 & 0.822\\
- \bottomrule
- \end{tabular}
-\end{table}
-\chapter{基于知识图谱的电影推荐系统}
-\section{系统整体设计}
-如第\ref{sec:tech-stack}节中所述,本系统使用的数据来自“MovieLens 1M Dataset”、IMDb和豆瓣网。其中IMDb和豆瓣网的数据是使用爬虫爬取得到的。最后再使用Python脚本对这些数据进行处理加工,并导入MongoDB数据库和Neo4j数据库。
-
-本系统使用MongoDB和Neo4j存储数据。其中,MongoDB作为非关系型的新兴NoSQL数据库,以灵活的非结构化的方式存储普通用户数据、管理员数据、电影数据等,并提供高并发的性能支持与可分布式存储的扩展性。而在以高性能著称的图数据库Neo4j中,存储用于推荐算法使用的电影知识图谱。
-
-本系统后端使用Python编写的Flask框架,Flask框架是轻量级的微框架,以高可扩展性著称,为本系统的后端网页应用服务器提供支持。在Flask中,基于REST风格构建API以供前端使用,REST风格的语义化API使后端API的构建与前端API的使用简单方便。
-
-本系统前端使用Angular作为前端网页框架。Angular是基于TypeScript的网页框架,以模块化及可重用的组件设计著称。Angular为本系统提供了模块化的网页设计,使本系统前端逻辑清晰,易于维护。此外,本系统使用了Angular材料组件库(Angular Material Components),得益于此,本系统遵循材料设计(Material Design)语言,使视觉传达风格简洁美观,具有响应式动化与过渡效过、光线与阴影等。
-\section{数据库设计}
-如前所述,本系统的MongoDB数据库用于存储普通用户数据、管理员数据、电影数据等,而Neo4j作为高性能的图数据库,用于存储知识图谱。以下逐一说明MongoDB数据库与Neo4j数据库的存储结构。
-
-不同于MySQL等关系型数据库,MongoDB数据库作为非结构化存储的NoSQL数据库,没有表、列与行的概念,而只有集合与文档的概念,即在数据库中存储集合(一定程度上对应于关系型数据库的表),在集合中存储文档(一定程度上对应于关系型数据库的行),而关系型数据库中的列则对应于MongoDB数据库中文档的属性。
-
-本系统在MongoDB数据库中建立4个集合,分别用于存储用户、管理员、体裁与电影数据。因其中的数据为非结构化数据,因此无法用表格的形式给出,目前习惯上以JSON形式给出数据的逻辑结构,以下以JSON形式来表示存储结构:
-
-以下为普通用户集合的数据结构,用户集合中的文档存储用户ID、哈希处理后的密码、其进行过评分的电影(包括电影ID、评分及时间)以及由推荐算法服务器写入的推荐列表、已购买电影及心愿单:
-\begin{verbatim}
- {
- _id: Integer,
- password: String,
- rating: Array([
- {
- movieId: Integer,
- rating: Integer,
- timestamp: Integer
- },
- ...
- ]),
- recommendation: Array([Interger, ...]),
- bought: Array([Interger, ...]),
- wishlist: Array([Interger, ...])
- }
-\end{verbatim}
-
-以下为管理员集合的数据结构,其存储结构较简单,管理员集合中的文档存储管理员ID、哈希处理后的密码:
-\begin{verbatim}
- {
- _id: String,
- password: String
- }
-\end{verbatim}
-
-以下为体裁集合的数据结构,其存储结构较简单,体裁集合中的文档存储体裁名称:
-\begin{verbatim}
- {
- _id: String
- }
-\end{verbatim}
-
-以下为电影集合的数据结构,电影集合中的文档存储电影ID、电影封面、体裁、价格、评分累加和、评分总数量、预告片图片、剧情介绍、导演、剧本作家及演员。需要说明的是评分累加和以及评分总数量对应于用户集合中的评分,但只起缓存作用,定期计算。(经测试表明,每次用户访问时计算的开销较大,用户得到响应的时间过长):
-\begin{verbatim}
- {
- _id: Integer,
- title: String,
- cover: String,
- genres: Array([String, ...]),
- price: Float,
- ratingSum: Integer,
- ratingCount: Integer,
- trailer_image_url: String,
- storyline: Array([String, ...]),
- directors: Array([String, ...]),
- writers: Array([String, ...]),
- actors: Array([String, ...]),
- }
-\end{verbatim}
-
-Neo4j数据库用于存储推荐算法使用的知识图谱,含有182011个结点、1241995条边,其数据结构可表示为:
-\begin{verbatim}
- node: actor | country | director | film | genre | language
- | person_or_entity_appearing_in_film | rating | star
- | writer
- relationship: actor.film | director.film | film.country
- | film.director | film.genre | film.language | film.rating
- | film.star | film.writer | genre.film
- | person_or_entity_appearing_in_film.film | writer.film
- edge = (node) - [relationship] -> (node)
-\end{verbatim}
-\section{系统功能说明}
-\begin{figure}
- \includegraphics{use-case}
- \bicaption{系统功能用例图}{Use case diagram for the system }\label{fig:use-case}
-\end{figure}
-本系统用户角色分为未登录用户、普通用户与管理员用户,其用例说明如图\ref{fig:use-case}。
-\subsection{系统导航}
-本系统使用浮动侧边栏作为导航方式,如图\ref{fig:admin-navigation}。点击侧导航栏右下角的固定的按钮可以将浮动侧边栏设为固定,再次点击后将取消固定。
-\begin{figure}
- \fbox{\includegraphics[width=.94\textwidth]{admin-navigation}}
- \bicaption{系统侧导航栏(管理员)}{Side navigation panel of the system (for administrators)}\label{fig:admin-navigation}
-\end{figure}
-
-\subsection{未登录用户}
-未登录用户能进行以下操作:
-
-\noindent (1)接收随机的电影推荐
-
-未登录用户首页随机显示50部电影,如图\ref{fig:anonymous-index}。
-\begin{figure}
- \fbox{\includegraphics[width=.94\textwidth]{anonymous-index}}
- \bicaption{未登录用户首页}{Index page for anonymous user }\label{fig:anonymous-index}
-\end{figure}
-
-\noindent (2)按分类查看电影
-
-未登录用户可以根据电影的分类来查看电影,如图\ref{fig:anonymous-category}。
-\begin{figure}
- \fbox{\includegraphics[width=.94\textwidth]{anonymous-category}}
- \bicaption{未登录用户分类页面}{Category page for anonymous user }\label{fig:anonymous-category}
-\end{figure}
-
-\noindent (3)查看电影详情
-
-未登录用户可以查看电影详情,如图\ref{fig:anonymous-details}。点击页面上的“添加至心愿单”和“购买”会跳转至登录界面。
-\begin{figure}
- \fbox{\includegraphics[height=.7\textheight]{anonymous-details}}
- \bicaption{未登录用户电影详情页面}{Movie details page for anonymous user }\label{fig:anonymous-details}
-\end{figure}
-
-\noindent (4)搜索电影
-
-未登录用户可以在应用栏右部的搜索框搜索电影,如图\ref{fig:anonymous-search}。本系统支持模糊搜索,与此同时,随着用户搜索内容的不断输入,系统会在搜索框下方显示候选的匹配词条,方便用户直接点击查看,此外,用户也能通过回车跳转至完整的搜索结果页面。
-\begin{figure}
- \fbox{\includegraphics[width=.94\textwidth]{anonymous-search}}
- \bicaption{未登录用户电影搜索界面(侧导航栏已固定)}{Movie search page for anonymous user (side navigation panel pinned)}\label{fig:anonymous-search}
-\end{figure}
-\subsection{注册与登录}
-\noindent(1)注册
-
-本系统对普通用户开放注册功能,并能提供用户名是否含不合法字符、是否与已注册用户名冲突、密码是否符合复杂度要求等的检测。
-
-\noindent (2)登录
-
-本系统提供登录功能,并能根据不同的登录错误类型相应地作出响应。
-\subsection{普通用户}
-普通用户具备未登录用户的所有功能。此外,还具备以下功能:
-
-\noindent (1)添加心愿单
-
-已登录用户能在电影详情页面添加电影至心愿单。
-
-\noindent (2)购买
-
-已登录用户能在电影详情页面购买电影。
-
-\noindent (3)评分
-
-已登录用户能在电影详情页面给电影评分。电影评分功能位于电影详情页面,如图\ref{fig:general-details}所示。
-
-\begin{figure}
- \fbox{\includegraphics[width=.94\textwidth]{general-details}}
- \bicaption{电影评分页面}{Rating page for movies}\label{fig:general-details}
-\end{figure}
-
-\noindent (4)查看已购买的电影
-
-已登录用户能通过侧导航栏跳转至查看已购买的电影的页面。
-
-\noindent (5)查看已添加心愿单的电影
-
-已登录用户能通过侧导航栏跳转至查看已添加心愿单的电影的页面。
-\subsection{管理员用户}
-\noindent (1)管理电影信息
-
-管理员能增加电影、删除电影与修改电影信息,如图\ref{fig:admin-movie}所示。
-\begin{figure}
- \fbox{\includegraphics[width=.94\textwidth]{admin-movie}}
- \bicaption{管理电影页面}{Movie administration page}\label{fig:admin-movie}
-\end{figure}
-
-\noindent (2)管理用户信息
-
-管理员能增加用户、删除用户与修改用户密码。
-
-\noindent (3)管理知识图谱
-
-管理员能增加、删除、修改以及查找知识图谱中的结点与关系,如图\ref{fig:admin-knowledge-graph}所示。该界面中的结点及关系可以以动态的方式呈现,同时支持以填写选项的方式以及使用Cypher语句的方式来增加、删除、修改以及查找知识图谱中的结点与关系。当鼠标悬浮于某一节点或关系之上时,将显示有关这一节点或关系的有关信息。
-\begin{figure}
- \fbox{\includegraphics[width=.94\textwidth]{admin-knowledge-graph}}
- \bicaption{管理知识图谱页面}{Knowledge graph administration page}\label{fig:admin-knowledge-graph}
-\end{figure}
-\section{电影推荐流程}
-本系统的推荐流程分为离线推荐与实时推荐,如图\ref{fig:recommendation-procedure}所示。
-
-\begin{figure}
- \includegraphics{recommendation-procedure}
- \bicaption{电影推荐流程}{Movie recommendation procedure }\label{fig:recommendation-procedure}
-\end{figure}
-
-其中,离线推荐使用第\ref{ch:offline-recommendation}章所述的涟漪网络算法,此算法是基于文献\parencite{wang2018ripplenet}实现的。不同于文献\parencite{wang2018ripplenet}中仅使用用户评分计算用户偏好,本推荐系统在用户偏好的计算过程中还结合了用户收藏,这在一定程度上缓解了冷启动问题并改进了推荐性能。
-此外,本推荐系统还结合了实时推荐机制作为补充,描述如下:
-
-(1)离线推荐服务器定期运行涟漪网络算法。离线推荐服务器从MongoDB数据库服务器获取用户信息与电影评分、电影是否加入心愿单等数据以及从Neo4j数据库服务器获取知识图谱数据信息。然后执行涟漪网络算法。最后离线推荐服务器将计算得到的各用户推荐列表存入MongoDB数据库中,等待用户访问时将该结果推荐给用户。
-
-(2)当用户访问时,网页后端服务器查询推荐列表中的电影数据是否达到阀值,如果推荐列表中的数量过少,则根据用户交互随机将同体裁电影加入推荐列表的末端作为补充并最终显示给用户。
-
-上述步骤中,(1)中的离线推荐准确度高,但算法运算时间长,无法做到即时响应用户请求。(2)中的实时推荐方法准确度低,但算法运算快,可以做到实时响应请求并即时发出响应。两者相互补充组成了本系统的电影推荐算法。
-\section{系统安全性}
-本系统对已登录普通用户与管理员在前后端交互过程中使用JSON网络令牌(JSON Web Token, JWT)实现授权与认证(Authorization and Authentication),以此保证系统的安全性,本系统的总体安全性设计如图\ref{fig:jwt}所示。
-
-\begin{figure}
- \includegraphics{jwt}
- \bicaption{系统总体安全性设计}{Overall security design for the system}\label{fig:jwt}
-\end{figure}
-
-在用户登录时,Flask后端网页服务器会生成一个长期JSON网络令牌和一个临时JSON网络令牌,令牌中存储有用户id以及过期时间,并且该令牌使用非对称加密算法加密,其中含有由Flask后端网页服务器颁发的签名信息,这确保了JSON网络令牌不会被伪造。
-
-前端网页服务器在接收到令牌后会将令牌存储在浏览器的localStorage中,并在每一个接下来的请求头中附上该令牌,而后端服务器只有在该令牌有效(指确实为后端网页服务器颁发且该另令牌尚未过期)的情况下才会继续执行有关请求。与此同时,若该请求是用户内容相关的,则后端服务器还会检测令牌中的id是否与请求中使用的id相同。若不满足以上任意一项,则后端网页服务器返回未授权错误。
-
-其中,若后端网页服务器发现令牌过期,则会将该信息发送给前端网页服务器,前端网页服务器将会将长期令牌发送给后端服务器以刷新(renew)临时令牌。
-
-此外,本系统还使用了哈希算法对密码进行哈希处理,数据库中的密码全部为哈希处理后的密码。同时,用户登录过程是后端网页服务器使用原密码与哈希处理后的密码进行比较,而没有开放哈希处理后的密码与哈希处理后的密码进行比较的接口,这保障了本系统的安全性。这在同时令网站仅允许HTTPS(HTTPS-only)网络连接的情况下可以充分保证本系统的安全性。
-
-需要指出的是,虽然本系统在用户登录与注册时密码在前端没有进行哈希处理,但是本系统在部署时使用HTTPS-only的连接,在这种情况下,所有的数据传输都处于加密状态,避免了中间人攻击的可能,因此明文传输密码而不使用哈希处理是安全的,在实际使用的过程中可行。而本系统的后端网页服务器对前端网页服务器传入的明文密码进行哈希处理的目的是避免数据库中存入明文的密码。如果数据库中存入明文的密码,则当数据库中用户密码泄露时攻击者可以轻易使用泄露的密码登录本系统。而如上所述,本系统后端只开放了接收明文密码的接口,即只将数据库中哈希处理后的密码与用户请求中的明文密码进行对比,即使攻击者获取了用户哈希后的密码,要计算其对应的明文密码也是困难的,甚至在明文密码足够复杂的情况下是不可能的。因此,以上措施保证了本系统的安全性。
-\chapter{研究结论和展望}
-\section{工作总结}
-随着互联网的发展,用户可选择的电影数量不断增加,为了让用户快速找到感兴趣的电影,各种推荐算法应运而生。这些算法存在推荐准确性较低、数据稀缺性以及冷启动问题。本文针对此现状,以电影推荐为研究对象,使用知识图谱作为辅助信息,利用涟漪网络算法实现了电影推荐系统。具体地说,主要的研究工作如下:
-
-(1)使用基于Scrapy框架的爬虫从IMDb和豆瓣网上爬取了3684条电影数据。其中,从IMDb爬取了3494条电影数据,从豆瓣网爬取了190条电影数据(由于豆瓣网限制了每IP访问量故爬取的数据较少)。这些电影数据包括电影封面图片、电影情节介绍、电影预告片图片、电影演员列表、导演以及剧本作家等信息。
-
-(2)根据文献\parencite{wang2018ripplenet}实现了基于知识图谱的涟漪网络推荐算法,通过使用“MovieLens 1M Dataset”数据集以及从IMDb和豆瓣网上爬取的电影数据,实现了基于用户心愿单和用户评分并以知识图谱为辅助信息的推荐算法。不同于文献\parencite{wang2018ripplenet}中仅使用用户评分计算用户偏好,本文在用户偏好的计算过程中还结合了用户收藏,这在一定程度上缓解了冷启动问题并改进了推荐性能。并对实现的推荐算法进行了实验,计算了其AUC和准确度两个关键的性能指标,将该指标与DKN\cite{wang2018dkn}、CKE\cite{zhang2016collaborative}、PER\cite{yu2014personalized}、SHINE\cite{wang2018shine}、LibFM\cite{rendle2012factorization}以及Wide\&Deep\cite{cheng2016wide}算法的进行了对比。并以此发现,涟漪网络算法的性能最优。
-
-(3)基于涟漪网络算法实现了基于知识图谱的电影推荐系统。该系统为未登录用户提供按分类查看电影、查看电影详情的功能;为普通用户提供电影推荐、按分类查看电影、查看电影详情、电影评分、将电影加入心愿单以及购买电影功能;为管理员提供增加、删除、修改、查找电影及用户的功能。同时使用JSON网络令牌、HTTPS以及哈希化密码等手段保障系统的安全性。
-\section{工作展望}
-为了给用户提供准确的推荐电影,需要不断优化并改进推荐过程。推荐系统的基础是用户历史偏好集、知识图谱信息以及推荐算法本身。因此有效地记录用户历史偏好集,完善知识图谱信息并改进推荐算法本身是提高推荐结果的重要因素。本文虽然对基于知识图谱的推荐算法有了一定的研究,并且将其应用于电影推荐系统中,但是由于时间和能力所限,该系统仍存在着不足的地方,主要体现在以下两个方面:
-
-\noindent (1)需要完善知识图谱的信息
-
-知识图谱是本文使用的涟漪网络算法的基础,但本文所使用的知识图谱的信息还不够完善,因此在一定程度上影响了涟漪网络算法的性能。
-
-\noindent (2)涟漪网络算法有待进一步改进
-
-尽管涟漪网络算法相比于传统的推荐算法在准确度上有所提升,但涟漪网络算法目前仅适用于离线推荐,而无法用于实时推荐,这使它的适用场景受到了限制。未来可考虑改造该算法,使其能满足实时推荐的需求。
-
-对于以上提及的问题,未来还需要更深入地学习有关知识图谱、推荐算法、深度学习的有关知识,对系统进行改进,从而使其更完善。
diff --git a/macros/latex/contrib/bjfuthesis/example/contents/mission-statement.pdf b/macros/latex/contrib/bjfuthesis/example/contents/mission-statement.pdf
new file mode 100644
index 0000000000..57d34537fd
--- /dev/null
+++ b/macros/latex/contrib/bjfuthesis/example/contents/mission-statement.pdf
Binary files differ
diff --git a/macros/latex/contrib/bjfuthesis/example/contents/statement-of-originality.pdf b/macros/latex/contrib/bjfuthesis/example/contents/statement-of-originality.pdf
new file mode 100644
index 0000000000..2ef5980867
--- /dev/null
+++ b/macros/latex/contrib/bjfuthesis/example/contents/statement-of-originality.pdf
Binary files differ
diff --git a/macros/latex/contrib/bjfuthesis/example/thesis.pdf b/macros/latex/contrib/bjfuthesis/example/thesis.pdf
index 4bbb60245a..7c4998cbb9 100644
--- a/macros/latex/contrib/bjfuthesis/example/thesis.pdf
+++ b/macros/latex/contrib/bjfuthesis/example/thesis.pdf
Binary files differ
diff --git a/macros/latex/contrib/bjfuthesis/example/thesis.tex b/macros/latex/contrib/bjfuthesis/example/thesis.tex
index b8f5b59421..c97d0d6aa8 100644
--- a/macros/latex/contrib/bjfuthesis/example/thesis.tex
+++ b/macros/latex/contrib/bjfuthesis/example/thesis.tex
@@ -1,11 +1,612 @@
\documentclass{bjfuthesis}
+\addbibresource{bibliography.bib}
+\usepackage[utf8]{inputenc}
\begin{document}
+\includepdf[pages={1}]{contents/cover.pdf}
+\includepdf{contents/statement-of-originality.pdf}
+\includepdf{contents/mission-statement.pdf}
\frontmatter
- \input{contents/abstract}
+ \chapter*{摘要}
+\begin{abstract}
+ 随着在线电影数量不断增加,用户选择电影的时间成本不断上升,准确的推荐算法成为了必然要求。为解决协同过滤推荐算法中的稀缺性问题与冷启动问题,研究人员用商品属性或社交网络等信息来辅助推荐算法。现有的将知识图谱作为辅助信息的推荐算法包括基于嵌入的方法和基于路径的方法,但这两种方法均存在一些缺陷,没有充分有效地利用知识图谱中的相关信息,推荐的准确度较低。
+
+ 本文实现了基于知识图谱的“涟漪网络”推荐算法。“涟漪网络”算法的核心是利用现实生活中雨滴产生的涟漪在水面上不断扩散的思路,来模拟用户偏好的扩散。对于每一个用户,涟漪网络将其过往偏好作为知识图谱中的一个种子集,然后沿知识图谱中的关系路径不断地拓展用户偏好,进而发现该用户对某个候选物品以等级划分的潜在兴趣,其中多个“涟漪”重叠形成知识图谱中的用户偏好分布。该算法的实验结果和以往的CKE、DKN、PER等模型结果相比,表现出更优的性能。利用该算法,本文设计并实现了一个基于知识图谱的电影推荐系统,该系统包括管理员用户和普通用户,管理员能新增、编辑和删除电影与用户,普通用户能浏览、收藏与购买电影。该系统可以高效准确地为用户推荐电影,方便用户选择满足自己偏好的电影。
+\end{abstract}
+\keywordscn{知识图谱,推荐系统,涟漪网络,用户偏好,电影商店}
+\chapter*{Abstract}
+\begin{abstract}
+ As the number of online movies continues to increase and the time cost for users to choose movies continues to rise, accurate recommendation algorithms have become an necessary requirement. In order to address the scarcity and cold start problem of collaborative filtering, researchers usually make use of side information, such as product attributes or social networks as side information to assist the recommendation. The existing recommendation algorithms that use knowledge graph as side information include embedding-based methods and path-based methods, but both methods have some shortcomings. They do not make full and effective use of the relevant information in the knowledge graph, and the accuracy of recommendation is relatively low.
+
+ This paper implements a recommendation algorithm, ``Ripple Network", based on knowledge graph. The core of the Ripple Network algorithm is to use the idea that the ripples produced by raindrops in real life continue to spread on the water surface to stimulate the spread of user preferences. For each user, Ripple Network uses its past preference as a seed set in the knowledge graph, and then continuously expands the user's preferences along the relationship path in the knowledge graph, and then discovers his hierarchical potential interests concerning a certain candidate item. Multiple ``ripples'' overlap to form the user preference distribution in the knowledge graph. Compared with previous model results of CKE, DKN, PER, etc., the experimental results of this algorithm show better performance. Using this algorithm, this paper designs and implements a recommendation system based on the movie knowledge graph. The system includes administrator users and general users. The administrator can add, edit and delete movies and users, and general users can browse, collect and purchase films. The system can provide users with an efficient movie recommendation function, which is convenient for users to choose movies that match their preferences.
+\end{abstract}
+\keywordsen{Knowledge graph, recommender system, Ripple Network, user preferences, movie store}
\tableofcontents
\mainmatter
- \input{contents/mainbody}
+ \chapter{绪论}
+\section{研究背景与意义}
+一直以来,电影推荐都是在线流媒体播放平台发展中的一个重要问题,做好电影推荐可以使用户能在海量电影中选择满足其偏好的电影,提高用户满意度,从而提高在线流媒体播放平台的流量转化率及购买率,并最终提高在线流媒体播放平台的经济收益。近年来,随着电影行业及互联网行业的不断发展,在线电影数量不断增加,用户在海量电影中选择满足其偏好的电影的难度不断上升,性能优异的推荐算法成为了必然要求。自从在线流媒体播放平台出现以来,人们便开始尝试利用推荐算法来提高平台流量转化率,出现了诸如协同过滤的推荐算法\cite{he2017neural}。但这些算法未能解决数据稀缺性及冷启动问题,并不能为在线流媒体播放平台提供良好的推荐性能。为此,人们尝试将辅助信息融入推荐算法中以解决数据稀缺性及冷启动问题\cite{sun2017collaborative},并提高推荐性能。
+
+知识图谱是一种结构化的语义知识库,被用于迅速提供对物理世界中的概念和相互关系的描述,为解决推荐问题提供了新的方法\cite{zou2020survey},近年来受到国内外研究人员的广泛关注,成为了当前的研究热点。知识图谱通过对复杂的原始数据进行加工、处理及整合,转化成简单可靠、清晰明了的“实体,关系,实体”三元组,汇聚了大量的知识信息,从而能实现基于知识信息的响应和推理。
+
+知识图谱常被用于作为辅助信息添加至推荐算法中以提高推荐的准确性,这已是当前的研究焦点。
+
+近年来,随着在线流媒体播放平台的发展,电影推荐系统应运而生,它作为现代信息技术与传统电影产业相结合的产物,对流媒体播放平台的用户体验起着至关重要的作用,其可大幅度减少用户寻找满足其偏好电影的时间,并提高用户点击率与购买率,从而提高流媒体播放平台的经济收益。电影推荐系统能为用户推荐其感兴趣的电影,而减少对用户不感兴趣内容的显示,从而满足用户需求。但是,目前网络上绝大多数的电影推荐系统都使用传统的基于协同过滤的推荐算法,未能有效利用知识图谱等辅助信息,返回给用户的推荐结果中包含大量用户不感兴趣的电影,此外,还将一些本应推荐给用户的、用户感兴趣的电影丢弃了。造成这一问题的主要原因是推荐算法缺少有关新加入的无用户评分的电影以及新注册的用户的信息。
+
+对于海量的电影数据,为了实现准确地推荐给用户其感兴趣的电影,基于协同过滤的传统推荐算法是满足了不用户需求的,特别是对新注册用户,推荐的准确度无法得到保证。所以,本文旨在以知识图谱作为辅助信息,构建一个合适的电影推荐系统,并利用知识图谱中包含的丰富的辅助信息,最终实现一个电影推荐系统,为用户提供有效的、准确的电影推荐,从而提高用户满意度,提高平台收益。
+\section{国内外研究现状}
+\subsection{推荐系统研究现状}
+推荐系统由Jussi Karlgren于哥伦比亚大学在一份技术报告中以“数字书架”的名称被首次提及,而后自1994年起被在SICS的Jussi Karlgren、由Pattie Maes于MIT领导的研究团队、位于Bellcore的Will Hill以及同样位于MIT的Paul Resnick大规模实现并在技术性报告及出版物大量出现,以上人员与GroupLens的工作被授予了2010年ACM软件系统奖。
+
+自从在90年代中期首批有关协同过滤的论文出现后推荐系统便成为了重要的研究领域。工业界与学术界出现了众多有关建设新的推荐系统的工作。由于该领域包含众多的研究问题及其能帮助用户解决在过多信息中提供个性化推荐的实际应用,因此研究人员对该领域的兴趣依旧很高。
+
+当前,推荐列表在推荐系统将其产生的过程中的方式主要有两种:基于内容推荐与协同过滤推荐\cite{jafarkarimi2012naive}。基于内容推荐的算法使用一些有关物品的离散特征来推荐出拥有相似性的物品。协同过滤方法根据用户的历史行为(诸如其评价过的、点击过的、购买过的商品等)并与其他用户的相似决策结合来建立模形,这种算法可以被用于预测用户对物品的偏好程度。这两种方法常常被同时使用。
+
+此外,近来有越来越多的推荐算法被提出:多准则推荐系统。多准则推荐系统可以被定义为包含多标准偏好信息的推荐系统,而不是构建基于单一凭据的推荐系统。风险感知推荐系统,现存推荐系统的主要方法聚焦于基于上下文信息推荐最相关内容给用户,而没有将不相关内容打扰用户的推荐风险考虑在内。考虑推送推荐内容给用户而造成打扰用户的风险在某些情况下是需要考虑的,比如,在一个工作会议上或是在凌晨或是在晚上。而此类推荐算法为该问题提供了解决方案。
+
+现实中,大量使用的往往是混合推荐系统。其同时结合了协同过滤、基于内容过滤以及其他方法,这种混合式的推荐方法现在被大量使用。混合推荐可以在多种方式下被实现:将基于内容的和基于协同滤的预测模型被分开实现再将他们结合起来,亦或是将两种方法统一到同一模型中并一同实现。
+\subsection{知识图谱的研究现状}
+在知识表示与知识推理中,知识图谱是一个使用图结构的数据模型或拓扑结构的知识库。知识图谱常被用来存储基于内连接的对实体的描述——对象、事件、情形或抽象概念,并包括自由形式的语义。
+
+该词汇最早在1972年于一个有关构建模块化指令系统的课程中被提出。在80年代末,命名为知识图谱的项目主要聚焦于语义网络的设计。在2007年,DBpedia和Freebase作为基于图的常识性知识库被创立。DBpedia致力于从Wikipedia中抽取数据,而Freebase也包含一系列公开的数据集。它们两者都未将自己称为“知识图谱”,但实则构建并描述了有关知识图谱的相关概念。
+
+在2012年,谷歌正式提出了知识图谱的概念\cite{singhal2012introducing},并构建了基于DBpedia和Freebase以及其他数据源的谷歌知识图谱。他们后来将包括CIA World Factbook, Wikidata和Wikipedia的网站的RDFa, Microdata, JSON-LD内容从它们的索引网站上抽取并纳入知识图谱。与知识图谱相关联的实体与关系类型使用来自scheme.org的术语被更广泛地组织了起来。
+
+谷歌知识图谱中非常重要的一项是“自由库”,它是一个大型的协同工作知识库。“自由库”使用图结构作为其数据结构,可以将其视作一个有向图。谷歌知识图谱模型便是谷歌团队利用其在“自由库”之上的技术积累开发出来的\cite{漆桂林2017知识图谱研究进展}。
+
+自此,数个大型跨国公司开始利用它们的知识图谱,很快知识图谱流行起来,有免费的知识图谱,如DBpedia和NELL,以及商业性质的知识图谱,如谷歌知识图谱和Microsoft Satori。这些知识图谱被成功应用于问答系统、词向量嵌入与文字分类等。在2019年,IEEE将其关于“大数据”和“数据挖掘与智能计算”的年度国际会议融入有关知识图谱的国际会议。
+
+以上是知识图谱发展的主要进程。
+
+知识图谱一般表示为三元组的形式,即$G=(h,r,t)$,其中$G$为知识图谱,$h$和$t$是知识库中的实体集合,分别为三元组的头结点与尾节点\cite{徐增林2016知识图谱技术综述}。知识图谱也可以看作是一种结点对应实体、边对应关系的有向异构图。
+
+目前知识图谱的构建过程中主要使用了定义层次学习及事实学习。
+
+定义层次学习是通过使用机器学习等技术,从文字、图片等信息中提取知识表达中的定义,并确定其上下文信息。而知识图谱本质上是属于一种精炼的异构信息网络。利用定义层次学习可以在一定程度上完成对于知识图谱的构建。
+
+事实学习分为有监督的事实学习、半监督的事实学习以及无监督的事实学习。有监督的事实学习通过人为标注的语料信息输入以及深度学习方法来完成知识图谱的构建,而半监督的事实学习方法使用启发式地自动标注文本,但缺陷是训练数据集中可能含有大量的噪声数据。而无监督的学习方法主要使用基于深度学习模型的自然语言处理(NLP)的方法,无须人为干预,由训练模型自动完成信息抽取、信息整合。随着深度学习算法的发展,目前基于无监督的事实学习逐渐成为主流\cite{李涓子2017知识图谱研究综述}。
+
+目前出现了诸多使用以上理论方法设计的知识图谱嵌入算法:基于翻译的TransE\cite{bordes2013translating}、TransH\cite{wang2014knowledge}、TransR\cite{lin2017learning}和基于语义分析的DistMult\cite{yang2014embedding}等。
+
+目前,知识图谱在业界的应用已经取得了巨大成功\cite{曹倩2015知识图谱的技术实现流程及相关应用}:
+
+(1)搜索引擎技术。如前所述,知识图谱最早便是由谷歌提出以改善其搜索引擎的。在将知识图谱应用于搜索引擎之后,搜索引擎能对一些常见的搜索内容基于其使用的知识图谱信息快速给出搜索结果。同时,对于一些名词性的搜索内容,搜索引擎能使用知识图谱以知识卡片的形式给出其相关信息。研究表明,在谷歌将知识图谱技术融入其搜索引擎之后,用户点击进入维基百科的次数明显减少,说明利用知识图谱技术的搜索引擎可以更好的直接给出用户需要的信息而不需要用户再浏览其他网站。
+
+(2)智能问答。信息检索系统中非常常见的一种便是问答系统。问答系统在用户输入问题后能迅速给出用户需要的答案。而在将知识图谱技术应用于问答系统后,其回答的准确率有非常大的提升。目前苹果的智能助理Siri以及谷歌的智能助理谷歌助理(Google Assistant)都使用了知识图谱技术。
+
+此外,知识图谱还广泛应用于金融、医疗等多个领域。
+\subsection{基于知识图谱的推荐系统研究现状}
+由于传统的推荐系统无法解决稀缺性问题和冷启动问题,因此研究人员企图将辅助信息加入到推荐算法中以改善推荐性能。而这类辅助信息有社交网络、用户/物品属性、图像与上下文等。
+
+在数种类型的辅助信息中,知识图谱通常包含有更丰富的信息以及物品间的联系。图\ref{fig:enhanced-recommendation}中说明了知识图谱提供丰富的信息与物品间的连接,有利于提高推荐结果的准确性、多样性和可解释性。知识图谱可以从以下三个方面提高推荐性能:
+\begin{figure}
+ \includegraphics[width=\textwidth]{figures/enhanced-recommendation.png}
+ \bicaption{基于知识图谱的电影推荐系统}{Knowledge graph enhanced movie recommendation system}\label{fig:enhanced-recommendation}
+\end{figure}
+
+(1)知识图谱引入了实体语义相关性,这可以帮助找到实体间潜在的联系并提高推荐物品的准确性。
+
+(2)知识图谱由各种类型的关系构成,这对合理地扩展用户兴趣并增加推荐商品的多样性是有益的。
+
+(3)知识图谱连接用户的历史记录及推荐的商品,因此提高了推荐系统的可解释性。
+
+将知识图谱作为辅助信息加入至推荐系统中是当前的热点问题,目前基于知识图谱构建推荐系统的方法主要有以下几类:
+
+(1)基于嵌入的方法。基于嵌入的方法通过知识图谱嵌入计算算法将知识图谱中的实体信息与关系信息映射为低维向量空间中的向量表示(嵌入表示)。而后推荐算法利用该嵌入表示来完成相应的计算,并给出推荐结果。目前将知识图谱中嵌入表示信息作为辅助信息的推荐模型有CKE\cite{zhang2016collaborative}、DKN\cite{wang2018dkn}以及SHINE\cite{wang2018shine}等。CKE是微软在 KDD2016 年发表的,其模型结构在原有系统过滤得到$U$, $V$向量的基础上,将物品的嵌入与其他描述信息相结合,这些信息主要有:
+采用 TransR 算法嵌入得到的知识图谱,图谱内每个实体嵌入表示被提取为物品的结构化向量信息。
+采用SDAE模型得到物品描述性文本的文本嵌入表示。
+采用SCAE模型得到物品相关图像的视觉嵌入表示。DKN是之前同样由微软团队在WWW2018会议上发表的。它是一个主要针对新闻推荐任务提出的框架,知识图谱用于辅助计算新闻标题的嵌入表示。DKN提出对新闻标题内每一个关键实体,在知识图谱内找到其实体嵌入和上下文嵌入。
+SHINE设计深度自编码器来嵌入语义网络,社交网络并进行推荐。其为用户-物品的交互使用自动编码器并计算用户感兴趣的概率。此外,嵌入表示可以包含实体的独热编码\cite{koren2008factorization}、词汇集\cite{wang2018dkn}、上下文信息\cite{sun2017collaborative}或属性\cite{wang2018shine},而选择哪一种嵌入向量的计算方式取决于其应用场合。
+
+(2)基于路径的方法。基于路径的方法将知识图谱作为异构信息网络,主要是通过知识图谱中的路径关系信息来辅助推荐算法完成推荐相关的计算工作。目前基于知识图谱中路径信息的推荐模型有HIN\cite{zhao2017meta}、RKGE\cite{sun2018recurrent}等。HIN是2017年在KDD上提出的,与PER\cite{yu2014personalized}类似,都将知识图谱作为异构信息网络。它针对Yelp和Amazon数据集分别设计了元路径,并得到了L个评估函数。并在建模时使用FM模型,使用FM损失函数组进行梯度下降,并最终得到推荐结果。RKGE模型使用了基于循环神经网络的方法。在人为定义元路径并抽取出所有路径之后,对每种元路径都使用循环神经网络模型来抽取并推理其路径中所包含的信息。
+
+(3)混合式方法。基于嵌入的方法未能充分利用实体间的关系模式信息,而基于路径的方法仅考虑了实体间的语义连通信息,未能有效使用用户/物品本身的语义信息。因此,目前出现了混合式方法,即同时结合了基于嵌入的方法与基于路径的方法的优点。混合式方法是当前的研究热点与焦点,使用该方法的典型模型有AKUPM\cite{tang2019akupm}和RCoLM\cite{cao2019unifying}等。AKUPM是通过注意力机制增强的推荐模型,RCoLM则是基于联合学习并以任务为导向的推荐算法。本文实现的电影推荐系统基于文献\parencite{wang2018ripplenet},其所使用的算法模型是也属于混合式方法。
+\section{本文的主要研究内容}
+本文在推荐算法、知识图谱和基于知识图谱的推荐算法的相关研究基础上,做了以下三方面的研究:
+
+(1)对推荐系统所需的数据进行采集和处理,使用“MovieLens 1M Dataset”作为数据集,此外还从IMDb及豆瓣网爬取了相关电影数据并进行处理,作为本文的研究对象。
+
+(2)根据文献\parencite{wang2018ripplenet}提出的算法,实现了基于知识图谱的涟漪网络推荐算法,此算法能根据用户的历史行为为用户进行电影推荐。不同于文献\parencite{wang2018ripplenet}中仅使用用户评分计算用户偏好,本文在用户偏好的计算过程中还结合了用户收藏,这在一定程度上缓解了冷启动问题并改进了推荐性能。此外,将涟漪网络算法与其他基于知识图谱的推荐算法(DKN\cite{wang2018dkn}、CKE\cite{zhang2016collaborative} 、PER\cite{yu2014personalized}、SHINE\cite{wang2018shine}、LibFM\cite{rendle2012factorization}和Wide\&Deep\cite{cheng2016wide}等)进行了性能比较。
+
+(3)实现了一个基于知识图谱的电影推荐系统,该系统能够根据用户的历史行为(评分、收藏等)来为用户进行电影推荐。该系统分为管理员、未登录用户、普通登录用户。管理员能增加、修改和删除电影和普通用户;未登录用户能根据电影分类查看电影列表以及查看电影详情;普通登录用户除了能进行未登录用户的所有操作外,还能购买、收藏及为电影评分。
+\section{论文结构}
+本论文一共分为五个章节。
+
+第1章是绪论。简明介绍知识图谱作为辅助信息在推荐算法中的作用以及推荐算法对在线流媒体播放平台的作用,同时介绍了推荐系统、知识图谱和基于知识图谱的推荐系统的发展和应用,并说明了本文的主要工作。
+
+第2章是相关理论和技术。介绍了目前知识图谱和推荐系统的研究现状,并对传统的推荐算法与加入辅助信息的推荐算法作了较为细致的分类与阐述。同时还介绍了本文实现的电影推荐系统所使用的技术栈,诸如数据库、前端架构、后端架构等。
+
+第3章是涟漪网络。介绍了涟漪网络算法,以及计算相关实体嵌入的过程中使用的深度学习算法,并对以上算法进行了讨论。最后,还对涟漪网络推荐算法的准确度进行了测试。
+
+第4章是电影推荐系统。介绍了以涟漪网络算法为基础构建的电影推荐系统:介绍了系统架构、系统功能、电影推荐流程以及如何保证该系统的安全性。
+
+第5章是研究结论和展望。总结了涟漪网络算法的设计与实现、电影推荐系统的功能,并指出了其中可以改进的地方。
+\chapter{相关理论和技术}
+\section{知识图谱}
+\subsection{知识图谱的概念及发展进程}
+知识图谱,是一种知识可视化或知识领域映射地图,是显示知识发展进程与结构关系的一系列三元组(实体,关系,实体),用可视化技术描述知识信息及其载体,挖掘、分析、建立、绘制和可视化知识以及实体之间的相互关系。
+
+知识图谱是谷歌于2012年提出的,目的是为了增强其搜索引擎。而后微软于2013年7月发布了Microsoft Satori知识图谱。除传统搜索服务提供商之外,包括Apple,Facebook,IBM等互联网企业也在探索该领域。此外,业界也出现了社区构建的开源知识图谱,如DBpedia,NELL和Wikidata等。以Freebase、WordNet和GeneOntology等为例的知识图谱已成为支持人工智能相关应用的非常重要的资源。
+\subsection{知识图谱的构建方法}
+知识图谱是由多实体结点和不同关系边构成的多关系图,一个边是一个事实三元组(头结点,关系,尾结点),记为$(h,r,t)$。而知识图谱的构建便是寻找这样的三元组。
+
+在过去十年间,出现了诸多构建大型知识图谱的方法,然而,还没有清晰准确的构建知识图谱的范式。主要有两个困难:(1)知识图谱是符号化的逻辑系统而知识图谱的应用常常包含在连续空间中的计算;(2)在一张知识图谱上进行知识聚合是困难的。
+
+目前,知识图谱主要通过以下3个步骤来完成构建:
+
+(1)信息抽取。即从各类型的源数据中抽取出实体(概念)、实体间的关系,并在此基础之上形成确切的知识表达。
+
+(2)知识融合。对新获得的知识进行整合,以完成消歧义。
+
+(3)知识加工。经过质量核查后将融合后的新知识的正确的部分加入至知识图谱中。
+\subsection{知识图谱的应用}
+知识图谱以更接近人类认知的方式为互联网的信息表达提供了一种新的方式,而且提供了一种更益于组织与利用海量数据的方式。当前知识图谱主要用于推荐系统、搜索引擎、个人助理以及问答系统。
+\section{推荐系统}
+推荐系统是内容过滤系统的一个子集,被广泛使用于多个领域,它向用户推荐满足其偏好的物品,并通常具有为视频或音乐服务生成推荐清单的表现形式。
+\subsection{传统的推荐系统}
+传统的推荐系统主要分为基于内容的推荐系统、基于协同过滤的推荐系统和混合推荐系统\cite{黄立威2018基于深度学习的推荐系统研究综述}。基于内容的推荐系统主要用于文本相关的项目,因为内容常常是使用关键字来描述的。该算法通过计算相关物品的离散特征,然后推荐具有与用户历史偏好物品类似特征的有关物品。基于协同过滤的推荐系统主要通过将具有与目标用户相似特征的用户所交互过的物品推荐给目标用户。
+
+基于内容的推荐与基于协同过滤的推荐的有关区别可以通过比较两个流行音乐推荐系统的实现方式看出。(1)潘多拉音乐使用一个基于内容推荐的推荐算法。它根据艺人或歌曲的属性来生成一个包含相似风格歌曲的电台,并且该电台的内容会根据收听用户的反馈进行调整。当用户对一首歌曲“不感兴趣”时该算法将弱化该歌曲的一些属性;而当用户喜欢一首歌曲时,将强化一些属性。并且该算法会根据该属性调整歌曲的顺序,若属性的值越过一个阀值时推荐算法便将某一歌曲从列表中删除。(2)“终级fm”使用协同过滤的推荐算法。它记录用户经常收听的乐队和歌手,然后与其它用户的有关行为进行比较,建立一个电台,并以此推荐歌曲。“终级fm”会给用户推荐其他具有相似特征用户的播放列表(并保证目标用户未收听过)。
+
+基于内容的推荐与基于协同过滤的推荐各有优缺点。潘多拉音乐所使用的基于内容推荐的推荐算法是根据物品本身的性质来进行推荐的,因此不需要用户信息就可以有较好的准确度。但该算法严重依赖物品本身的特性,因此局限性较大,推荐的内容都是与种子集相关的,推荐结果的多样性较低。而“终级fm”使用的协同过滤算法需要根据用户与物品的交互来生成推荐结果,因此需要大量的用户数据,存在数据稀缺性问题与冷启动问题。
+\subsection{基于知识图谱的推荐系统}
+基于内容推荐与协同过滤推荐两者均存在一些局限性,为了提高推荐的准确性,解决传统推荐算法的数据稀缺性与冷启动问题,研究者将一些辅助信息加入至推荐算法中,通常这些辅助信息包括上下文信息、用户或物品的属性、图片和社交网络\cite{常亮2019知识图谱的推荐系统综述, 秦川2020基于知识图谱的推荐系统研究综述}。
+
+而随着知识图谱的发展,将知识图谱作为辅助信息来提高推荐系统的性能已经成为了热门的研究方向。将知识图谱作为辅助信息加入推荐算法的优点有:
+
+(1)提高推荐系统的准确性。知识图谱可以表示不同实体间的关系,可以将物品及其相关属性对应于知识图谱之中,从而推荐算法可以理解物品之间的关系。此外,用户与用户间的关系信息也可以映射至知识图谱之中,从而推荐算法可以更准确地分析物品与物品间的关系、用户与物品之间的关系。
+
+(2)提高推荐系统的可解释性。由于推荐结果依照知识图谱中的关系信息,因此可以由知识图谱中的关系路径得到推荐系统给出推荐结果的原因。
+
+目前主要的基于知识图谱的推荐算法有基于嵌入的方法、基于路径的方法以及混合式方法:
+
+(1)基于嵌入的方法。基于嵌入的方法使用知识图谱的信息来完善实体的嵌入表示。为了将知识图谱中的信息添加至推荐算法中来辅助推荐,需要使用知识图谱嵌入表示算法(Knowledge Graph Embedding, KGE)表计算实体嵌入(实体嵌入指由知识图谱中的信息得到的在低维向量空间中的向量表示)。KGE算法有TransE\cite{bordes2013translating}、TransH\cite{wang2014knowledge}、TransR\cite{lin2017learning}和DistMult\cite{yang2014embedding}等。而推荐算法利用该嵌入表示来进行相关计算,从而对用户进行物品推荐。
+
+(2)基于路径的方法\cite{lin2015modeling, guu2015traversing, toutanova2016compositional}。基于路径的方法将知识图谱视为异构信息网络。而推荐系统利用该异构信息网络寻找实体间的关系,从而完成推荐。
+
+(3)混合式方法。基于嵌入的方法未能充分利用实体间的关系模式信息,而基于路径的方法仅考虑了实体间的语义连通信息,未能有效利用用户/物品本身的语义信息。混合式方法结合了基于嵌入的方法与基于路径的方法的优点,该方法是当前的研究热点与焦点,使用该方法的典型模型有AKUPM\cite{tang2019akupm}和RCoLM\cite{cao2019unifying}等。本文实现的算法属于混合方法。
+\section{系统开发技术}
+\label{sec:tech-stack}
+\subsection{数据采集技术}
+电影推荐系统使用的数据来自“MovieLens 1M Dataset”\footnote{https://grouplens.org/datasets/movielens/1m/}数据集,此外还从IMDb\footnote{https://www.imdb.com/}及豆瓣网\footnote{https://www.douban.com/}爬取了相关电影数据并进行处理作为本文的研究对象。
+
+在数据采集的过程中,使用Scrapy框架进行了数据爬取,爬取的数据包括电影名称、电影封面、预告片图片、电景情节介绍、导演、演员以及剧作家。
+
+最终,总计爬取了3684部电影的数据。其中,从IMDb爬取了3494条电影数据,从豆瓣爬取了190条电影数据(由于豆瓣网限制了每IP访问量故爬取的数据较少)。
+\subsection{数据存储技术}
+本系统使用MongoDB与Neo4j存储数据。
+
+\noindent (1)MongoDB
+
+MongoDB是一个新兴的非关系型存储的分布式存储数据的数据库,属于NoSQL,与MySQL等传统的关系型数据库相比,它提供更好的高并发支持,具有高可靠性的优点。与此同时,得益于其基于文档储存的特点,相比较传统的关系型数据库,它的存储结构更灵活。
+
+在本系统中,MongoDB存储普通用户数据、管理员数据、电影数据等。
+
+\noindent(2)Neo4j
+
+Neo4j是一个具有高性能的图数据库,它将结构化的数据信息储存在网络上而不是存储在表中。它具有健壮和成熟的数据库的所有特点。虽然Neo4j是一个新兴的数据库,但它已在具有超过1亿节点、关系和属性的产品中得到了应用,充分体现了其高性能、高可靠性的特点。
+
+在本系统中,最终需存储的图结点有182011个,需存储的边有1241995条。如果将它们存储在传统的关系型数据库中,会因大量的连接查询导致极大的性能开销,表现为查询耗时久。Neo4j对图数据处理做了优化,因此查询等操作可以在较短的时间内完成,故本系统将知识图谱数据存储在Neo4j中而不是关系型数据库中。
+
+\subsection{后端技术}
+本系统使用Flask框架作为网站后端框架。Flask是一个Python编写的轻量级微框架。它具有轻量、便捷、可扩展等特点。系统使用Flask框架充分利用了其便捷、可扩展以及开发便捷的特点,与本系统要求相符。
+
+系统使用表现层状态转换(REST)风格的应用程序接口(API)作为前后端的交互接口。表现层状态转换(Representational State Transfer,REST)是一种基于HTTP协议的软件交互体系结构样式,该协议是由Roy Thomas Fielding博士在2000年的博士论文中引用的\cite{fielding2000architectural},目的是促进不同的软件/程序的开发。在网络上互相传输数据。表示层状态转换基于超文本传输​​协议(HTTP)的一组约束,该协议是一种旨在提供万维网服务的软件构造样式。符合或兼容此体系结构样式(简称为REST或RESTful)的网络服务允许客户端发出使用统一资源标识符访问和操作网络资源的请求,这些资源与一组预定义的操作一致。因此,表示层状态转换提供了Internet上计算机系统之间相互使用资源的互操作性。与其他类型的网络服务(例如SOAP服务)相比,它们使用自己定义的一组操作来访问网络资源。
+
+得益于本系统使用了REST风格的API,本系统能更有效地使用缓存来提升响应速度,同时前后端间的通讯的无状态性可以让不同的服务器处理一连串请求中不同的请求,提高了本系统的可扩展性。与此同时,得益于REST风格语义化的接口,使前后端交互接口更清晰明了,使接口的使用者能更高效便捷地进行相关的开发工作。
+\subsection{前端技术}
+本系统前端使用Angular框架。Angular(通常指“Angular 2+”或“Angular v2及以上”)是一个基于TypeScript的开源网络应用框架,它的开发由Google的Angular团队领导同时也有个人及其他公司维护。Angular完全从相同团队开发的AngularJS重新编写而来。Angular常常作为MEAN技术栈的一部分。MEAN技术栈指MongoDB数据库、Express.js网络服务器框架、Angular/AngularJS以及Node.js服务器运行时。不同于MEAN技术栈,本系统将其中的“E”(指Express.js网络服务器框架)替换为了Flask网络服务器框架。
+
+通过使用Angular框架,本系统具有一个现代化、模块化、响应式的网页架构。同时借助于Angular Material Components官方组件库,本系统前端UI符合材料设计(Material Design)。
+\chapter{基于涟漪网络知识图谱的推荐算法}
+\label{ch:offline-recommendation}
+\section{涟漪网络}
+本算法基于文献\parencite{wang2018ripplenet}实现,并在其基础上进行了一定的改进:文献\parencite{wang2018ripplenet}中计算用户偏好时并未考虑用户收藏,本文在计算用户偏好时,将用户收藏考虑在内,这在一定程度上缓解了数据稀缺性问题和冷启动问题并改进了推荐性能。
+\subsection{架构}
+涟漪网络的总体架构如图\ref{fig:ripplenet-framework}所示,图上方的知识图谱中展示了由用户交互产生的涟漪。涟漪网络以一个用户$u$和一个电影$v$作为输入,并输出用户$u$与电影$v$之间产生交互的概率。对输入用户$u$而言,其历史交互记录$V_u$是知识图谱中的种子集,而后沿着知识图谱中的关系边形成多个涟漪集$S_u^{k}\ (k=1, 2, \dots, H)$。第k个涟漪集是种子集$V_u$经过$k$跳得到的知识三元组。然后迭代地利用这些涟漪集与电影$v$的嵌入表示(黄色的块)计算出用户$u$对电影$v$的的响应(绿色的块),最后结合得到用户的最终嵌入表示(灰色的块)。最终,利用用户$u$与电影$v$的嵌入表示计算出用户$u$对电影$v$感兴趣的预测概率$y_{uv}$。
+\begin{figure}
+ \includegraphics[width=\textwidth]{figures/ripplenet-framework.png}
+ \bicaption{涟漪网络的总体架构}{The overall framework of the Ripple Network}\label{fig:ripplenet-framework}
+\end{figure}
+\subsection{涟漪集}
+\begin{figure}
+ \includegraphics[width=\textwidth]{figures/illustration-of-ripple-sets.png}
+ \bicaption{电影知识图谱中由“阿甘正传”激发的涟漪集}{Sets of ripples of “Forest Gump” in Knowledge Graph of movies}\label{fig:illustration-of-ripple-sets}
+\end{figure}
+知识图谱常常含有丰富的事实信息与实体间的联系。比如,图\ref{fig:illustration-of-ripple-sets}(图中不同颜色的圆圈表示不同跳数的涟漪集,越浅的蓝色代表种子集与该区域内实体的关联程度越低)中电影“阿甘正传”与“罗伯特·泽米吉斯”相连,它们之间的联系为“罗伯特·泽米吉斯”是电影“阿甘正传”的导演。而“回到未来”也与“罗伯特·泽米吉斯”相连。因此,如果一个用户与电影“阿甘正传”交互过,则他很有可能也对“回到未来”感兴趣。为了描述用户在知识图谱中分层次的潜在偏好集,递归定义用户$u$的$k$跳相关实体如下:
+
+\textbf{定义1(相关实体集)} 给定交互矩阵$\Upsilon$与知识图谱$G$,则用户$u$的$k$跳相关实体集的定义为式\eqref{eq:relevant-entities}。
+
+\begin{equation}
+ E_u^k=\{t|(h, r, t)\in G \text{且} h\in E^{k-1}_u\}, k = 1, 2, \dots, H\label{eq:relevant-entities}
+\end{equation}
+
+式\eqref{eq:relevant-entities}中,$E_u^0=V_u=\{v | y_{uv}=1\}$是用户的历史偏好集(历史偏好集是指用户在最高为5的评分中给出的评分$\geqslant$4的物品以及用户已加入收藏的物品),可以看作是用户$u$在知识图谱中的种子集。
+
+相关实体集可以看作是用户的历史偏好集在知识图谱中的自然扩展。给定相关实体集的定义,以下定义用户$u$的$k$跳涟漪集:
+
+\textbf{定义2(涟漪集)}用户$u$的$k$跳涟漪集可以看作是知识图谱中以$E^{k-1}_u$为起点的知识三元组,定义如式\eqref{eq:ripple-set}所示。
+
+\begin{equation}
+ S_u^k = \{(h, r, t)|(h, r, t)\in G \text{且} h\in E^{k-1}_u\}, k = 1, 2, \dots, H\label{eq:ripple-set}
+\end{equation}
+
+“涟漪”这个词有两重意思:(1)对由多个雨点产生的真实涟漪的模拟,用户对电影的潜在兴趣集在知识图谱中由近及远地传递。这一过程如图\ref{fig:illustration-of-ripple-sets}所示。(2)用户的潜在兴趣随着知识图谱中传递的跳数$k$的增大逐渐递减。图\ref{fig:illustration-of-ripple-sets}中蓝色的变浅显示了潜在兴趣递减的过程。
+
+一个可能出现的问题是在跳数$k$增加的过程中涟漪集的大小可能过大。为了解决这个问题,注意到:
+
+(1)在真实使用的知识图谱中大量的实体是沉没实体,意思是它们只有传入链路而没有传出链路。
+
+(2)在电影推荐的具体情境下,关系可以限制在情境相关的分类中以减少涟漪集的数量并提高实体间的相关度。
+
+(3)最大跳数$H$通常在实际应用中不会过大,因为离用户历史偏好集较远的实体会带来更多的错误推荐而不是更丰富的推荐结果。
+
+(4)在涟漪网络中,我们可以对一个固定大小的邻集而不是对完整的涟漪集采样从而更进一步地减小计算工作量。设计这样的采样器是一个重要的工作,尤其是非统一的采样器能更好地捕获用户的分等级的潜在兴趣。
+\subsection{偏好扩散}
+\label{sec:osum}
+传统的协同过滤算法是通过学习用户与物品间的潜在联系来完成推荐,而在涟漪网络算法中,这一过程是通过偏好扩散完成的:对每个用户,涟漪网络将他的过往兴趣视为知识图谱中的种子集,然后沿知识图谱中的路径不断地拓展用户的潜在兴趣集,进而得到按等级划分的关于候选物品的潜在兴趣集。我们利用现实生活中的由雨滴产生的涟漪在水面上扩散来模拟偏好扩散的过程,其中多个“涟漪”重叠形成基于知识图谱的用户偏好分布。
+
+如图\ref{fig:ripplenet-framework},每部电影都有一个嵌入表示$v$,$v\in \mathbb{R}^{d}$,其中$\mathbb{R}$是实数集,$d$是嵌入表示向量的维数。给定电影的嵌入表示$v$以及用户$1$跳涟漪集$S_u^{1}$,可以利用电影$v$、$S_u^{1}$中的三元组中头节点$head_i$以及该三元组中的关系$r_i$来计算出电影$v$和实体$head_i$之间的相关度,如式\eqref{eq:item-entity-relevance}所示。
+
+\begin{equation}
+ p_i=softmax(v^TR_ih_i)=\frac{exp(v^TR_ih_i)}{\sum_{(h, r, t)\in S_u^1} exp(v^TRh)}\label{eq:item-entity-relevance}
+\end{equation}
+
+式\eqref{eq:item-entity-relevance}中,$R_i\in \mathbb{R}^{d\times d}$与$h_i\in \mathbb{R}^d$分别是关系$r_i$和头节点$h_i$的嵌入表示。相关度$p_i$为向量空间$R_i$中的电影$v$与实体$h_i$之间的相似度。同时还考虑了关系信息的嵌入表示矩阵在计算电影$v$与实体$h_i$之间的相似度,因为不同电影-实体对之间的相似度在不同关系的场景下可能有所不同。比如,“阿甘正传”与“回到未来”在导演方面有很高的相似度,但它们在体裁或剧作家方面可能没有联系。
+
+在完成相似度计算之后,将$S_u^{1}$中三元组的尾节点根据计算得到的相似度进行加权求和,得到向量$o^{1}_u$,如式\eqref{eq:o1}所示。
+
+\begin{equation}
+ o^1_u=\sum_{(h_i,r_i,t_i)\in S_u^1}p_it_i\label{eq:o1}
+\end{equation}
+
+式\eqref{eq:o1}中,$t_i\in \mathbb{R}^{d}$,$t_i$是事实三元组中的尾节点。向量$o^{1}_u$可以视为用户偏好集$V_u$关于电影$v$的$1$次响应。与协同过滤算法类似的是,它根据用户交互过的物品来表示用户嵌入而不是使用单独的参数来表示用户,从而减少了参数数量。通过式\eqref{eq:item-entity-relevance}与式\eqref{eq:o1},用户的偏好从其交互过的电影(即种子集)成功在知识图谱中进行了一次扩散,这称为涟漪网络中的偏好扩散。
+
+可以将式\eqref{eq:item-entity-relevance}中的$v$替换为$o_u^1$,我们可以再次进行偏好扩散以得到用户的2次响应$o_u^2$。以此类推,最终我们可以将该用户的偏好集扩散至$H$跳,得到用户的涟漪集$S_u^{i}, i=1,\dots,H$。从中可以得到用户的多次响应$o^{1}_u, o^{2}_u, o^{H}_u$。用户$u$关于电影$v$的嵌入表示是通过结合所有的不同响应并计算得到的,如式\eqref{eq:osum}所示。
+\begin{equation}
+ u=o_u^1+o_u^2+\dots+o_u^H\label{eq:osum}
+\end{equation}
+
+尽管最后一跳的用户响应中理论上包含了所有之前得到的信息,但是对$o^k_u$进行求和仍然是有必要的,因为之前得到的用户响应可能在偏好传递的过程中稀释了,因此仅使用最后一跳的响应不能很好地表示用户嵌入。最终,利用用户嵌入与电影嵌入,计算出用户对电影感兴趣的概率,如式\eqref{eq:predicted-possibility}所示。
+\begin{equation}
+ y_{uv}=\zeta(u^Tv)\label{eq:predicted-possibility}
+\end{equation}
+
+其中,$\zeta(x)=\frac{1}{1+exp(-x)}$是sigmoid函数。
+\section{学习算法}
+在涟漪网络算法中,我们的目标是通过式\eqref{eq:predicted-possibility}求出用户对电影感兴趣的概率。但是,为了将其计算出来我们需要先求出所有物品、用户以及关系的嵌入表示,如第\ref{sec:osum}节中所述,用户的嵌入表示可以通过其涟漪集来代替,以此消元。但物品及关系的嵌入表示却是需要求出来的。
+
+为了求出物品及关系的嵌入表示,这里使用最大后验概率估计的方法。
+
+我们的目标是在已经得到知识图谱$G$以及用户与电影的交互矩阵$\Upsilon$的情况下最大化模型参数$\Gamma$,如式\eqref{eq:max}所示。
+\begin{equation}
+ max\ p(\Gamma |G,\Upsilon)\label{eq:max}
+\end{equation}
+
+式\eqref{eq:max}中,参数$\Gamma$包含了全部的实体、关系和电影的嵌入表示。可以将式\eqref{eq:max}等价于最大化式\eqref{eq:equal-max}。
+
+\begin{equation}
+ p(\Gamma |G,\Upsilon)=\frac{p(\Gamma,G,\Upsilon)}{p(G,\Upsilon)}\varpropto p(\Gamma)\centerdot p(G|\Gamma)\centerdot p(\Upsilon|\Gamma,G)\label{eq:equal-max}
+\end{equation}
+
+根据贝叶斯公式,在式\eqref{eq:equal-max}中,第一项$p(\Gamma)$代表模型参数的先验概率。设$p(\Gamma)$为均值为0,方差为对角协方差矩阵的正态分布,如式\eqref{eq:normal-distribution}所示。
+
+\begin{equation}
+ p(\Gamma)=N(0,\lambda_1^{-1}I)\label{eq:normal-distribution}
+\end{equation}
+
+式\eqref{eq:equal-max}中,$p(G|\Gamma)$是给定$\Gamma$的知识图谱的最大似然函数。最近,有研究者提出了多种计算知识图谱嵌入的方法,包括基于距离的方法和基于语义匹配的方法。在本算法中,使用三路张量分解的方法来建立知识图谱嵌入的最大似然函数,如式\eqref{eq:term2}。
+
+\begin{equation}
+ p(G|\Gamma)=\prod_{(h,r,t)\in E\times R\times E}p((h,r,t)|\Gamma)=\prod_{(h,r,t)\in E\times R\times E}N(I_{h,r,t}-h^TRt,\lambda_2^{-1})\label{eq:term2}
+\end{equation}
+
+式\eqref{eq:term2}中,若$I_{h,r,t}\in G$则标志$I_{h,r,t}$等于1,否则为0。式\eqref{eq:equal-max}中的第三项是给定$\Gamma$与知识图谱的似然函数,可以看作伯努利分布的累乘,如式\eqref{eq:bernoulli}。
+
+\begin{equation}
+ p(\Upsilon|\Gamma,G)=\prod_{(u,v)\in \Upsilon}\zeta(u^Tv)^{y_{uv}}\centerdot (1-\zeta (u^Tv))^{1-y_{uv}}\label{eq:bernoulli}
+\end{equation}
+
+对式\eqref{eq:equal-max}取负对数,有如式\eqref{eq:term3}所示的损失函数:
+\begin{multline}
+ min\ L=-log(p(\Upsilon|\Gamma,G)\centerdot p(G|\Gamma)\centerdot p(\Gamma))\\
+=\sum_{(u,v)\in \Upsilon}-(y_{uv}log\ \zeta(u^Tv)+(1-y_{uv}log(1-\zeta(u^Tv))))\\
++\frac{\lambda_2}{2}\sum_{r\in R}\|I_r-E^TRE\|_2^2+\frac{\lambda_1}{2}(\|V\|^2_2+\|E\|^2_2+\sum_{r\in R}\|R\|^2_2)\label{eq:term3}
+\end{multline}
+
+式\eqref{eq:term3}中,$V$和$E$是所有电影与实体的嵌入表示,$I_r$是在知识图谱中对关系$r$的标志向量$I$的分向量。在式\eqref{eq:term3}中,第一项是交互矩阵$\Upsilon$与涟漪网络的估测值之间的交叉熵,第二项是真实的知识图谱分向量$I_r$以及人为构建的指示矩阵$E^{T}RE$之间的均方误差,最后一项是为防止过拟合加入的正则项。
+
+直接求解上式来得到参数$\Gamma$是不可能的,因此可以使用随机梯度下降算法递归地优化损失函数来求解模型参数,而后再计算参数$\Gamma$的损失函数的梯度,并根据采样得到的一小批数据反向传递,然后更新参数并最终得到参数$\Gamma$。
+\section{分析}
+\subsection{可解释性}
+可解释的推荐系统旨在阐释为什么用户会对一件物品感兴趣,这帮助提升用户对推荐结果的满意度以及对推荐系统的信任。对推荐结果的解释通常基于标签、语义分析等。因为涟漪网络探索用户基于知识图谱的兴趣,因此它提供了一种基于知识图谱中的关系路径来阐述推荐结果的全新方式。比如,在图\ref{fig:illustration-of-ripple-sets}中,当用户对“幸福终点站”感兴趣,则该用户也可能对“荒岛余生”感兴趣。因为在知识图谱中,“汤姆·汉克斯”与“幸福终点站”相连,关系是演员,而“汤姆·汉克斯”与“荒岛余生”也相连,关系也是演员,换句话说,“荒岛余生”与“幸福终点站”有相同的演员。这便解释了用户对“幸福终点站”和“荒岛余生”同时感兴趣的原因。涟漪网络算法通过在知识图谱中寻找与用户交互过的电影(种子集)相连的物品,并不断扩散,最终确保推荐结果具有较高的准确性。
+\subsection{涟漪重叠}
+在涟漪网络中,一个可能的问题是涟漪集中的电影非常多,从而在偏好传递的过程中不可避免地导致用户的真实潜在偏好信息被稀释。然而,用户点击记录中不同的电影常常高度重叠(从种子集出发到达一部电影常常有不止一条路径),这在很大程度上避免了真实潜在偏好信息被稀释的问题。比如,在图\ref{fig:illustration-of-ripple-sets}中,如果一个用户喜欢“阿甘正传”,则他也可能喜欢“荒岛余生”。在该知识图谱中,从“阿甘正传”到“荒岛余生”有两条路径:“阿甘正传-U.S.-荒岛余生”与“阿甘正传-汤姆·汉克斯-荒岛余生”,这正是涟漪重叠的表现。
+\section{测试}
+\subsection{数据集}
+本测试使用“MovieLens 1M Dataset”数据集。该数据集由电影信息、用户信息以及用户对电影的评价三部分组成。其中,含有电影数据3883条、用户数据6040条以及1000209条用户对电影的评价数据。因该数据集数据量适中,数据准确可靠,因此在推荐系统的性能测试中被广泛使用。
+
+本测试使用的知识图谱来自Microsoft Satori,是依据“MovieLens 1M Dataset”中的电影名称从Microsoft Satori中提取相关的节点的与关系数据得到的。
+\subsection{基线}
+本测试中,会将本算法的测试结果与以下算法的相比较:
+
+DKN\cite{wang2018dkn}是由微软团队在WWW2018会议上发表的。它是一个主要针对新闻任务提出的框架,知识图谱用于辅助计算新闻标题的嵌入表示。DKN提出对新闻标题内每一个关键实体,在知识图谱内找到其实体嵌入和上下文嵌入。
+
+CKE\cite{zhang2016collaborative}是微软在KDD2016年发表的,其模型结构在原有系统过滤得到$U$,$V$向量的基础上,将物品的嵌入与其他描述信息相结合,这些信息主要有:
+采用TransR算法计算知识图谱嵌入表示,知识图谱内每个实体嵌入表示被提取为物品的结构化向量信息。
+采用SDAE模型得到物品描述性文本的文本性嵌入表示。
+采用SCAE模型得到物品相关图像的视觉嵌入表示。
+
+SHINE\cite{wang2018shine}设计深度自编码器并嵌入语义网络以及社交网络来进行推荐。其为用户-物品的交互使用自动编码器并刻画用户感兴趣的概率。
+
+PER\cite{yu2014personalized}是以基于路径的方法来将知识图谱作为辅助信息中的比较经典的算法。其提出的元路径可以为推荐系统提供可靠的方向,但是需要使用者了解领域内知识,进行人为路径设计。
+
+LibFM\cite{rendle2012factorization}是一个广泛使用的在CTR场景中的分解推荐模型。
+
+Wide\&Deep\cite{cheng2016wide}是一个结合线性路径的推荐模型。类似于LibFM,我们将用户、物品及实体的嵌入表示作为其输入。
+\subsection{测试步骤}
+在涟漪网络中,设置跳数$H=2$。根据实验结果,较大的跳数几乎无法提高性能却会造成较大的计算开销。我们将数据划分为训练集、评估集与测试集,按照6:2:2的比例进行分配。实验进行5次,计算准确度以及AUC然后取平均值。
+\subsection{结果}
+测试结果如表\ref{tab:acc-auc}中所示,总体上涟漪网络算法的性能最佳,其次是Wide\&Deep算法,说明他们可以充分利用知识图谱中的有效信息来辅助推荐算法。而表现最差的是PER算法,这可能是因为手工定义的元路径在电影推荐方面效果较差。
+\begin{table}
+ \bicaption{在兴趣预测计算中的AUC和准确度}{AUC and ACC in interest prediction}\label{tab:acc-auc}
+ \begin{tabular}{lcl}
+ \toprule
+ 算法 & AUC & 准确度 \\
+ \midrule
+ 涟漪网络 & 0.899 & 0.835 \\
+ DKN & 0.655 & 0.589 \\
+ CKE & 0.796 & 0.739 \\
+ SHINE & 0.778 & 0.732\\
+ LibFM & 0.892 & 0.812\\
+ Wide\&Deep & 0.903 & 0.822\\
+ \bottomrule
+ \end{tabular}
+\end{table}
+\chapter{基于知识图谱的电影推荐系统}
+\section{系统整体设计}
+如第\ref{sec:tech-stack}节中所述,本系统使用的数据来自“MovieLens 1M Dataset”、IMDb和豆瓣网。其中IMDb和豆瓣网的数据是使用爬虫爬取得到的。最后再使用Python脚本对这些数据进行处理加工,并导入MongoDB数据库和Neo4j数据库。
+
+本系统使用MongoDB和Neo4j存储数据。其中,MongoDB作为非关系型的新兴NoSQL数据库,以灵活的非结构化的方式存储普通用户数据、管理员数据、电影数据等,并提供高并发的性能支持与可分布式存储的扩展性。而在以高性能著称的图数据库Neo4j中,存储用于推荐算法使用的电影知识图谱。
+
+本系统后端使用Python编写的Flask框架,Flask框架是轻量级的微框架,以高可扩展性著称,为本系统的后端网页应用服务器提供支持。在Flask中,基于REST风格构建API以供前端使用,REST风格的语义化API使后端API的构建与前端API的使用简单方便。
+
+本系统前端使用Angular作为前端网页框架。Angular是基于TypeScript的网页框架,以模块化及可重用的组件设计著称。Angular为本系统提供了模块化的网页设计,使本系统前端逻辑清晰,易于维护。此外,本系统使用了Angular材料组件库(Angular Material Components),得益于此,本系统遵循材料设计(Material Design)语言,使视觉传达风格简洁美观,具有响应式动化与过渡效过、光线与阴影等。
+\section{数据库设计}
+如前所述,本系统的MongoDB数据库用于存储普通用户数据、管理员数据、电影数据等,而Neo4j作为高性能的图数据库,用于存储知识图谱。以下逐一说明MongoDB数据库与Neo4j数据库的存储结构。
+
+不同于MySQL等关系型数据库,MongoDB数据库作为非结构化存储的NoSQL数据库,没有表、列与行的概念,而只有集合与文档的概念,即在数据库中存储集合(一定程度上对应于关系型数据库的表),在集合中存储文档(一定程度上对应于关系型数据库的行),而关系型数据库中的列则对应于MongoDB数据库中文档的属性。
+
+本系统在MongoDB数据库中建立4个集合,分别用于存储用户、管理员、体裁与电影数据。因其中的数据为非结构化数据,因此无法用表格的形式给出,目前习惯上以JSON形式给出数据的逻辑结构,以下以JSON形式来表示存储结构:
+
+以下为普通用户集合的数据结构,用户集合中的文档存储用户ID、哈希处理后的密码、其进行过评分的电影(包括电影ID、评分及时间)以及由推荐算法服务器写入的推荐列表、已购买电影及心愿单:
+\begin{verbatim}
+ {
+ _id: Integer,
+ password: String,
+ rating: Array([
+ {
+ movieId: Integer,
+ rating: Integer,
+ timestamp: Integer
+ },
+ ...
+ ]),
+ recommendation: Array([Interger, ...]),
+ bought: Array([Interger, ...]),
+ wishlist: Array([Interger, ...])
+ }
+\end{verbatim}
+
+以下为管理员集合的数据结构,其存储结构较简单,管理员集合中的文档存储管理员ID、哈希处理后的密码:
+\begin{verbatim}
+ {
+ _id: String,
+ password: String
+ }
+\end{verbatim}
+
+以下为体裁集合的数据结构,其存储结构较简单,体裁集合中的文档存储体裁名称:
+\begin{verbatim}
+ {
+ _id: String
+ }
+\end{verbatim}
+
+以下为电影集合的数据结构,电影集合中的文档存储电影ID、电影封面、体裁、价格、评分累加和、评分总数量、预告片图片、剧情介绍、导演、剧本作家及演员。需要说明的是评分累加和以及评分总数量对应于用户集合中的评分,但只起缓存作用,定期计算。(经测试表明,每次用户访问时计算的开销较大,用户得到响应的时间过长):
+\begin{verbatim}
+ {
+ _id: Integer,
+ title: String,
+ cover: String,
+ genres: Array([String, ...]),
+ price: Float,
+ ratingSum: Integer,
+ ratingCount: Integer,
+ trailer_image_url: String,
+ storyline: Array([String, ...]),
+ directors: Array([String, ...]),
+ writers: Array([String, ...]),
+ actors: Array([String, ...]),
+ }
+\end{verbatim}
+
+Neo4j数据库用于存储推荐算法使用的知识图谱,含有182011个结点、1241995条边,其数据结构可表示为:
+\begin{verbatim}
+ node: actor | country | director | film | genre | language
+ | person_or_entity_appearing_in_film | rating | star
+ | writer
+ relationship: actor.film | director.film | film.country
+ | film.director | film.genre | film.language | film.rating
+ | film.star | film.writer | genre.film
+ | person_or_entity_appearing_in_film.film | writer.film
+ edge = (node) - [relationship] -> (node)
+\end{verbatim}
+\section{系统功能说明}
+\begin{figure}
+ \includegraphics{figures/use-case.pdf}
+ \bicaption{系统功能用例图}{Use case diagram for the system }\label{fig:use-case}
+\end{figure}
+本系统用户角色分为未登录用户、普通用户与管理员用户,其用例说明如图\ref{fig:use-case}。
+\subsection{系统导航}
+本系统使用浮动侧边栏作为导航方式,如图\ref{fig:admin-navigation}。点击侧导航栏右下角的固定的按钮可以将浮动侧边栏设为固定,再次点击后将取消固定。
+\begin{figure}
+ \fbox{\includegraphics[width=.94\textwidth]{figures/admin-navigation.png}}
+ \bicaption{系统侧导航栏(管理员)}{Side navigation panel of the system (for administrators)}\label{fig:admin-navigation}
+\end{figure}
+
+\subsection{未登录用户}
+未登录用户能进行以下操作:
+
+\noindent (1)接收随机的电影推荐
+
+未登录用户首页随机显示50部电影,如图\ref{fig:anonymous-index}。
+\begin{figure}
+ \fbox{\includegraphics[width=.94\textwidth]{figures/anonymous-index.png}}
+ \bicaption{未登录用户首页}{Index page for anonymous users }\label{fig:anonymous-index}
+\end{figure}
+
+\noindent (2)按分类查看电影
+
+未登录用户可以根据电影的分类来查看电影,如图\ref{fig:anonymous-category}。
+\begin{figure}
+ \fbox{\includegraphics[width=.94\textwidth]{figures/anonymous-category.png}}
+ \bicaption{未登录用户分类页面}{Category page for anonymous users }\label{fig:anonymous-category}
+\end{figure}
+
+\noindent (3)查看电影详情
+
+未登录用户可以查看电影详情,如图\ref{fig:anonymous-details}。点击页面上的“添加至心愿单”和“购买”会跳转至登录界面。
+\begin{figure}
+ \fbox{\includegraphics[height=.7\textheight]{figures/anonymous-details.png}}
+ \bicaption{未登录用户电影详情页面}{Movie details page for anonymous users }\label{fig:anonymous-details}
+\end{figure}
+
+\noindent (4)搜索电影
+
+未登录用户可以使用应用栏右侧的搜索框搜索电影,如图\ref{fig:anonymous-search}。本系统支持模糊搜索,与此同时,随着用户搜索内容的不断输入,系统会在搜索框下方显示候选的匹配词条,方便用户直接点击查看,此外,用户也能通过回车跳转至完整的搜索结果页面。
+\begin{figure}
+ \fbox{\includegraphics[width=.94\textwidth]{figures/anonymous-search.png}}
+ \bicaption{未登录用户电影搜索界面(侧导航栏已固定)}{Movie search page for anonymous users (side navigation panel pinned)}\label{fig:anonymous-search}
+\end{figure}
+\subsection{注册与登录}
+\noindent(1)注册
+
+本系统对普通用户开放注册功能,并能提供用户名是否含不合法字符、是否与已注册用户名冲突、密码是否符合复杂度要求等的检测。
+
+\noindent (2)登录
+
+本系统提供登录功能,并能根据不同的登录错误类型相应地作出响应。
+\subsection{普通用户}
+普通用户具备未登录用户的所有功能。此外,还具备以下功能:
+
+\noindent (1)添加心愿单
+
+已登录用户能在电影详情页面添加电影至心愿单。
+
+\noindent (2)购买
+
+已登录用户能在电影详情页面购买电影。
+
+\noindent (3)评分
+
+已登录用户能在电影详情页面给电影评分。电影评分功能位于电影详情页面,如图\ref{fig:general-details}所示。
+
+\begin{figure}
+ \fbox{\includegraphics[width=.94\textwidth]{figures/general-details.png}}
+ \bicaption{电影评分页面}{Rating page for movies}\label{fig:general-details}
+\end{figure}
+
+\noindent (4)查看已购买的电影
+
+已登录用户能通过侧导航栏跳转至查看已购买的电影的页面。
+
+\noindent (5)查看已添加心愿单的电影
+
+已登录用户能通过侧导航栏跳转至查看已添加心愿单的电影的页面。
+\subsection{管理员用户}
+\noindent (1)管理电影信息
+
+管理员能增加电影、删除电影与修改电影信息,如图\ref{fig:admin-movie}所示。
+\begin{figure}
+ \fbox{\includegraphics[width=.94\textwidth]{figures/admin-movie.png}}
+ \bicaption{管理电影页面}{Movie administration page}\label{fig:admin-movie}
+\end{figure}
+
+\noindent (2)管理用户信息
+
+管理员能增加用户、删除用户与修改用户密码。
+
+\noindent (3)管理知识图谱
+
+管理员能增加、删除、修改以及查找知识图谱中的结点与关系,如图\ref{fig:admin-knowledge-graph}所示。该界面中的结点及关系可以以动态的方式呈现,同时支持以填写选项的方式以及使用Cypher语句的方式来增加、删除、修改以及查找知识图谱中的结点与关系。当鼠标悬浮于某一节点或关系之上时,将显示有关这一节点或关系的有关信息。
+\begin{figure}
+ \fbox{\includegraphics[width=.94\textwidth]{figures/admin-knowledge-graph.png}}
+ \bicaption{管理知识图谱页面}{Knowledge graph administration page}\label{fig:admin-knowledge-graph}
+\end{figure}
+\section{电影推荐流程}
+本系统的推荐流程分为离线推荐与实时推荐,如图\ref{fig:recommendation-procedure}所示。
+
+\begin{figure}
+ \includegraphics{figures/recommendation-procedure.pdf}
+ \bicaption{电影推荐流程}{Movie recommendation procedure}\label{fig:recommendation-procedure}
+\end{figure}
+
+其中,离线推荐使用第\ref{ch:offline-recommendation}章所述的涟漪网络算法,此算法是基于文献\parencite{wang2018ripplenet}实现的。不同于文献\parencite{wang2018ripplenet}中仅使用用户评分计算用户偏好,本推荐系统在用户偏好的计算过程中还结合了用户收藏,这在一定程度上缓解了冷启动问题并改进了推荐性能。
+此外,本推荐系统还结合了实时推荐机制作为补充,描述如下:
+
+(1)离线推荐服务器定期运行涟漪网络算法。离线推荐服务器从MongoDB数据库服务器获取用户信息与电影评分、电影是否加入心愿单等数据以及从Neo4j数据库服务器获取知识图谱数据信息。然后执行涟漪网络算法。最后离线推荐服务器将计算得到的各用户推荐列表存入MongoDB数据库中,等待用户访问时将该结果推荐给用户。
+
+(2)当用户访问时,网页后端服务器查询推荐列表中的电影数据是否达到阀值,如果推荐列表中的数量过少,则根据用户交互随机将同体裁电影加入推荐列表的末端作为补充并最终显示给用户。
+
+上述步骤中,(1)中的离线推荐准确度高,但算法运算时间长,无法做到即时响应用户请求。(2)中的实时推荐方法准确度低,但算法运算快,可以做到实时响应请求并即时发出响应。两者相互补充组成了本系统的电影推荐算法。
+\section{系统安全性}
+本系统对已登录普通用户与管理员在前后端交互过程中使用JSON网络令牌(JSON Web Token, JWT)实现授权与认证(Authorization and Authentication),以此保证系统的安全性,本系统的总体安全性设计如图\ref{fig:jwt}所示。
+
+\begin{figure}
+ \includegraphics{figures/jwt.pdf}
+ \bicaption{系统总体安全性设计}{Overall security design for the system}\label{fig:jwt}
+\end{figure}
+
+在用户登录时,Flask后端网页服务器会生成一个长期JSON网络令牌和一个临时JSON网络令牌,令牌中存储有用户id以及过期时间,并且该令牌使用非对称加密算法加密,其中含有由Flask后端网页服务器颁发的签名信息,这确保了JSON网络令牌不会被伪造。
+
+前端网页服务器在接收到令牌后会将令牌存储在浏览器的localStorage中,并在每一个接下来的请求头中附上该令牌,而后端服务器只有在该令牌有效(指确实为后端网页服务器颁发且该另令牌尚未过期)的情况下才会继续执行有关请求。与此同时,若该请求是用户内容相关的,则后端服务器还会检测令牌中的id是否与请求中使用的id相同。若不满足以上任意一项,则后端网页服务器返回未授权错误。
+
+其中,若后端网页服务器发现令牌过期,则会将该信息发送给前端网页服务器,前端网页服务器将会将长期令牌发送给后端服务器以刷新(renew)临时令牌。
+
+此外,本系统还使用了哈希算法对密码进行哈希处理,数据库中的密码全部为哈希处理后的密码。同时,用户登录过程是后端网页服务器使用原密码与哈希处理后的密码进行比较,而没有开放哈希处理后的密码与哈希处理后的密码进行比较的接口,这保障了本系统的安全性。这在同时令网站仅允许HTTPS(HTTPS-only)网络连接的情况下可以充分保证本系统的安全性。
+
+需要指出的是,虽然本系统在用户登录与注册时密码在前端没有进行哈希处理,但是本系统在部署时使用HTTPS-only的连接,在这种情况下,所有的数据传输都处于加密状态,避免了中间人攻击的可能,因此明文传输密码而不使用哈希处理是安全的,在实际使用的过程中可行。而本系统的后端网页服务器对前端网页服务器传入的明文密码进行哈希处理的目的是避免数据库中存入明文的密码。如果数据库中存入明文的密码,则当数据库中用户密码泄露时攻击者可以轻易使用泄露的密码登录本系统。而如上所述,本系统后端只开放了接收明文密码的接口,即只将数据库中哈希处理后的密码与用户请求中的明文密码进行对比,即使攻击者获取了用户哈希后的密码,要计算其对应的明文密码也是困难的,甚至在明文密码足够复杂的情况下是不可能的。因此,以上措施保证了本系统的安全性。
+\chapter{研究结论和展望}
+\section{工作总结}
+随着互联网的发展,用户可选择的电影数量不断增加,为了让用户快速找到感兴趣的电影,各种推荐算法应运而生。这些算法存在推荐准确性较低、数据稀缺性以及冷启动问题。本文针对此现状,以电影推荐为研究对象,使用知识图谱作为辅助信息,利用涟漪网络算法实现了电影推荐系统。具体地说,主要的研究工作如下:
+
+(1)使用基于Scrapy框架的爬虫从IMDb和豆瓣网上爬取了3684条电影数据。其中,从IMDb爬取了3494条电影数据,从豆瓣网爬取了190条电影数据(由于豆瓣网限制了每IP访问量故爬取的数据较少)。这些电影数据包括电影封面图片、电影情节介绍、电影预告片图片、电影演员列表、导演以及剧本作家等信息。
+
+(2)根据文献\parencite{wang2018ripplenet}实现了基于知识图谱的涟漪网络推荐算法,通过使用“MovieLens 1M Dataset”数据集以及从IMDb和豆瓣网上爬取的电影数据,实现了基于用户心愿单和用户评分并以知识图谱为辅助信息的推荐算法。不同于文献\parencite{wang2018ripplenet}中仅使用用户评分计算用户偏好,本文在用户偏好的计算过程中还结合了用户收藏,这在一定程度上缓解了冷启动问题并改进了推荐性能。并对实现的推荐算法进行了实验,计算了其AUC和准确度两个关键的性能指标,将该指标与DKN\cite{wang2018dkn}、CKE\cite{zhang2016collaborative}、PER\cite{yu2014personalized}、SHINE\cite{wang2018shine}、LibFM\cite{rendle2012factorization}以及Wide\&Deep\cite{cheng2016wide}算法的进行了对比。并以此发现,涟漪网络算法的性能最优。
+
+(3)基于涟漪网络算法实现了基于知识图谱的电影推荐系统。该系统为未登录用户提供按分类查看电影、查看电影详情的功能;为普通用户提供电影推荐、按分类查看电影、查看电影详情、电影评分、将电影加入心愿单以及购买电影功能;为管理员提供增加、删除、修改、查找电影及用户的功能。同时使用JSON网络令牌、HTTPS以及哈希化密码等手段保障系统的安全性。
+\section{工作展望}
+为了给用户提供准确的推荐电影,需要不断优化并改进推荐过程。推荐系统的基础是用户历史偏好集、知识图谱信息以及推荐算法本身。因此有效地记录用户历史偏好集,完善知识图谱信息并改进推荐算法本身是提高推荐结果的重要因素。本文虽然对基于知识图谱的推荐算法有了一定的研究,并且将其应用于电影推荐系统中,但是由于时间和能力所限,该系统仍存在着不足的地方,主要体现在以下两个方面:
+
+\noindent (1)需要完善知识图谱的信息
+
+知识图谱是本文使用的涟漪网络算法的基础,但本文所使用的知识图谱的信息还不够完善,因此在一定程度上影响了涟漪网络算法的性能。
+
+\noindent (2)涟漪网络算法有待进一步改进
+
+尽管涟漪网络算法相比于传统的推荐算法在准确度上有所提升,但涟漪网络算法目前仅适用于离线推荐,而无法用于实时推荐,这使它的适用场景受到了限制。未来可考虑改造该算法,使其能满足实时推荐的需求。
+
+对于以上提及的问题,未来还需要更深入地学习有关知识图谱、推荐算法、深度学习的有关知识,对系统进行改进,从而使其更完善。
\backmatter
\printbibliography
- \input{contents/acknowledge}
+ \chapter{致谢}
+论文的撰写工作已经接近尾声,在本文的撰写过程中我要特别感谢李冬梅老师的指导。在毕业论文完成期间,李冬梅老师多次对我的毕业论文提出意见与建议。同时,她多次询问论文的撰写进度,更是体现了她对学生无微不至的关怀。每每当我在论文编写中遇到艰深晦涩之处时,她都能不失时机而恰到好处地给予我最有用的提示与建议,使我的毕业论文得以顺利完成。
+
+其次,我要感谢我本科期间曾经为我上课的所有老师。比如,由我的概率论老师为我打下的数学基础才使我得以用最大后验概率估计法完成嵌入表示的学习算法,蓝海洋老师任教的网站设计课程是我完成电影推荐系统的基石。总之,我要感谢大学四年来所有老师孜孜不倦的谆谆教诲与夜以继日的无私奉献。
+
+接着,我还要感谢我的同学,是他们思维的火花激起了论文写作中的灵感。与他们的交流使我受益匪浅。
+
+最后,我还要感谢我的父母,他们一直以来对我生活上与学习上的鼓励与引导是我得益完成论文的关键要素。
+
+感谢所有在论文撰写工作中为我提供过帮助的人。
\end{document}
diff --git a/macros/latex/contrib/colorist/colorart.cls b/macros/latex/contrib/colorist/colorart.cls
index 8e6fd2d020..c0040549ce 100644
--- a/macros/latex/contrib/colorist/colorart.cls
+++ b/macros/latex/contrib/colorist/colorart.cls
@@ -17,7 +17,7 @@
%%
\NeedsTeXFormat{LaTeX2e}[2020-10-01]
\ProvidesClass{colorart}
- [2021/06/07 A colorful article style]
+ [2021/06/07a A colorful article style]
\def\colorclass@baseclass{article}
\RequirePackage{kvoptions}
\RequirePackage{etoolbox}
diff --git a/macros/latex/contrib/colorist/colorbook.cls b/macros/latex/contrib/colorist/colorbook.cls
index 8f24678596..78d7969e64 100644
--- a/macros/latex/contrib/colorist/colorbook.cls
+++ b/macros/latex/contrib/colorist/colorbook.cls
@@ -17,7 +17,7 @@
%%
\NeedsTeXFormat{LaTeX2e}[2020-10-01]
\ProvidesClass{colorbook}
- [2021/06/07 A colorful book style]
+ [2021/06/07a A colorful book style]
\def\colorclass@baseclass{book}
\RequirePackage{kvoptions}
\RequirePackage{etoolbox}
diff --git a/macros/latex/contrib/colorist/colorist-doc.pdf b/macros/latex/contrib/colorist/colorist-doc.pdf
index 47c828dc1e..cb99ee3a3a 100644
--- a/macros/latex/contrib/colorist/colorist-doc.pdf
+++ b/macros/latex/contrib/colorist/colorist-doc.pdf
Binary files differ
diff --git a/macros/latex/contrib/colorist/colorist-doc.tex b/macros/latex/contrib/colorist/colorist-doc.tex
index c3ffef02e7..38db3b3d8c 100644
--- a/macros/latex/contrib/colorist/colorist-doc.tex
+++ b/macros/latex/contrib/colorist/colorist-doc.tex
@@ -88,7 +88,7 @@
\title{{\normalfont\textbf{\textsf{colorist}}}, write your articles or books in a colorful way}
\author{Jinwen XU}
-\thanks{Corresponding to: \texttt{\colorist{} 2021/06/07}}
+\thanks{Corresponding to: \texttt{\colorist{} 2021/06/07a}}
\date{June 2021, Beijing}
\maketitle
diff --git a/macros/latex/contrib/colorist/colorist.sty b/macros/latex/contrib/colorist/colorist.sty
index af8050fe4d..5ced409d17 100644
--- a/macros/latex/contrib/colorist/colorist.sty
+++ b/macros/latex/contrib/colorist/colorist.sty
@@ -17,7 +17,7 @@
%%
\NeedsTeXFormat{LaTeX2e}[2020-10-01]
\ProvidesPackage{colorist}
- [2021/06/07 A colorful style for articles and books]
+ [2021/06/07a A colorful style for articles and books]
\RequirePackage{kvoptions}
\RequirePackage{etoolbox}
\SetupKeyvalOptions{%
@@ -318,6 +318,12 @@
{\contentslabel{2.75em}}
{\hspace*{-2.75em}}
{\titlerule*[1em]{\textcolor{gray!30!paper}{.}}\color{paper!55!-paper}\contentspage}
+ \titlecontents{subsubsection}
+ [9em] % i.e., 7em (subsection) + 2em
+ {\normalfont\colorist@sffamily}
+ {\contentslabel{2.75em}}
+ {\hspace*{-2.75em}}
+ {\titlerule*[1em]{\textcolor{gray!30!paper}{.}}\contentspage}
}{
\titlecontents{section}
[2em] % i.e., 0em (part) + 2em
@@ -331,6 +337,12 @@
{\contentslabel{2.75em}}
{\hspace*{-2.75em}}
{\titlerule*[1em]{\textcolor{gray!30!paper}{.}}\color{paper!55!-paper}\contentspage}
+ \titlecontents{subsubsection}
+ [7em] % i.e., 5em (subsection) + 2em
+ {\normalfont\colorist@sffamily}
+ {\contentslabel{2.75em}}
+ {\hspace*{-2.75em}}
+ {\titlerule*[1em]{\textcolor{gray!30!paper}{.}}\contentspage}
}
%%================================
@@ -399,19 +411,25 @@
%%================================
\RequirePackage{mathtools}
\RequirePackage{amsthm}
-\def\simpleqed{\hfill\makebox[1em]{\rlap{\textcolor{gray!25!paper}{\rule[-0.1em]{.95em}{.95em}}}{\kern.07em\raisebox{.07em}{\textcolor{paper}{\rule[-0.1em]{.81em}{.81em}}}\kern.07em}}}
+\def\simpleqedsymbol{%
+ \makebox[1em]{\rlap{\textcolor{gray!25!paper}{\rule[-0.1em]{.95em}{.95em}}}{\kern.07em\raisebox{.07em}{\textcolor{paper}{\rule[-0.1em]{.81em}{.81em}}}\kern.07em}}}
\newtheoremstyle{simple}%
{}{}%
{\normalfont}{}%
{\normalfont}{}%
{0pt}%
- {\conditionalbfseries\thmname{#1}\thmnumber{ #2}\hspace{.4em}%
+ {\global\let\qedsymbol\simpleqedsymbol%
+ {\conditionalbfseries\thmname{#1}\thmnumber{ #2}}\hspace{.4em}%
\textcolor{gray!55!paper}{$|$}\hspace{.4em}%
- \color{gray}\thmnote{\ensuremath{(\text{#3})}~~}\pushQED{\simpleqed}}
-\def\@endtheorem{\popQED\endtrivlist\@endpefalse }
+ \color{gray}\thmnote{\ensuremath{(\text{#3})}~~}%
+ \pushQED{\qed}%
+ }
+\def\@endtheorem{\popQED\endtrivlist\@endpefalse
+\global\let\qedsymbol\qedsymbolOriginal}
\renewcommand{\qedsymbol}{%
\makebox[1em]{\color{gray!55!paper}\rule[-0.1em]{.95em}{.95em}}}
+\let\qedsymbolOriginal\qedsymbol
\newtheoremstyle{basic}
{0pt}{0pt}{\normalfont}{0pt}
@@ -1004,7 +1022,7 @@
\hspace*{-.5em}%
\fi%
}\normalmarginpar%
-}{}{\FAIL}
+}{}{}
\pretocmd{\conjecture}{%
\if@twoside\checkoddpage%
\ifoddpage\reversemarginpar\fi%
@@ -1019,7 +1037,7 @@
\hspace*{-.5em}%
\fi%
}\normalmarginpar%
-}{}{\FAIL}
+}{}{}
}
\RequirePackage{iftex}
@@ -1342,6 +1360,7 @@
{\scshape\@author}\\\smallskip%
{\@date}%
\end{center}%
+\ifx\@date\@empty\bigskip\fi%
\medskip%
}
\apptocmd{\maketitle}{\thispagestyle{fancy}}{}{\FAIL}
diff --git a/macros/latex/contrib/easybook/easybook.dtx b/macros/latex/contrib/easybook/easybook.dtx
index 30042d55b4..8b0f06cada 100644
--- a/macros/latex/contrib/easybook/easybook.dtx
+++ b/macros/latex/contrib/easybook/easybook.dtx
@@ -23,12 +23,12 @@
%
% \changes{v1.20}{2021/01/09}{修改和完善用户文档。}
% \changes{v1.20}{2021/01/09}{模板更改为使用 CC-BY 许可协议。}
-% \changes{v1.25u}{2021/05/03}{取消附带的示例文件,可查看历史版本及其它来源的使用样例。}
-% \changes{v1.25u}{2021/06/02}{将模块的代码独立出来为 \pkg{easybase} 宏包,适用于 \CTeX 文档类。}
+% \changes{v1.25v}{2021/05/03}{取消附带的示例文件,可查看历史版本及其它来源的使用样例。}
+% \changes{v1.25v}{2021/06/02}{将模块的代码独立出来为 \pkg{easybase} 宏包,适用于 \CTeX 文档类。}
%
% \title{\sffamily easybook 文档类手册}
% \author{瞿毅}
-% \date{2021/06/06\hskip\ccwd\relax v1.25u\thanks{\url{https://gitee.com/texl3/easybook}}}
+% \date{2021/06/07\hskip\ccwd\relax v1.25v\thanks{\url{https://gitee.com/texl3/easybook}}}
%
% \maketitle
% \begin{abstract}
@@ -134,7 +134,7 @@
% \end{syntax}
% 传递给 \cls{ctexbook} 设置字体,最好不要使用原有的 \opt{fontset} 选项,默认情况下使用自定义字体而不开启这个选项,可根据安装的字体及电脑系统选取。\opt{noto} 与 \opt{none} 选项的相关描述见小节 \ref{subsec:font settings},\opt{overleaf} 是一个各系统通用选项,会检测系统环境选取对应字体。
% \changes{v1.21}{2021/01/12}{默认字体与 \CTeX 一致,不再是自定义字体。}
-% \changes{v1.25u}{2021/05/04}{修复使用 \pkg{xeCJK} 与 \pkg{fontspec} 宏包的字体设置命令在 \hologo{LuaLaTeX} 下失效的问题。}
+% \changes{v1.25v}{2021/05/04}{修复使用 \pkg{xeCJK} 与 \pkg{fontspec} 宏包的字体设置命令在 \hologo{LuaLaTeX} 下失效的问题。}
% \end{function}
%
% \begin{function}[rEXP,added = 2021-01-05,updated = 2021-01-13]{paper}
@@ -184,7 +184,7 @@
% \tn{listoflstlistings*+}\oarg{键值列表}
% \end{syntax}
% \tn{listoffigures} 命令输出图片目录,\tn{listoftables} 输出表格目录,\tn{listoflstlistings} 输出代码目录。带有星号的目录命令不将标题添加进主文档目录,带有+号的目录命令可以使当前标题编号。\tn{tableofcontents+} 与其它命令不同是用于输出双语目录,需要与双语目录标题命令 \tn{bichapter} 等或设置图片、表格和代码等英文目录的标题配合使用,附加代码是中文与英文目录之间的代码,可以插入文本和换页命令等。目录的键值列表选项如下
-% \changes{v1.25u}{2021/05/05}{命令 \tn{tableofcontents} 可以输出双语目录。}
+% \changes{v1.25v}{2021/05/05}{命令 \tn{tableofcontents} 可以输出双语目录。}
% \end{function}
%
% \begin{function}{multoc,columns,title,format,aftertitle,pagestyle,chapter,section}
@@ -201,29 +201,26 @@
% 在书籍模式且 \opt{chapter} 选项开启或者文章模式的情况下,\opt{format} 用于设置目录标题的格式,\opt{aftertitle} 选项的代码将被插入到目录标题内容之后,\opt{pagestyle} 是目录标题所在页的页面格式,除此之外还支持 \opt{ctexset/chapter} 或 \opt{ctexset/section} 所有的章节标题样式选项。\opt{chapter} 选项使目录标题按照 chapter 级别输出,\opt{section} 选项使目录标题按照 section 级别输出,默认为 chapter 级别。
% \changes{v1.23}{2021/03/15}{为几个目录增加键值列表的选项,可设置标题输出级别以及是否加入主目录。}
% \changes{v1.24}{2021/04/04}{目录命令的可选参数增加标题键值。}
-% \changes{v1.25u}{2021/06/02}{目录可设置多栏,并在 article 模式仍然生效。}
+% \changes{v1.25v}{2021/06/02}{目录可设置多栏,并在 article 模式仍然生效。}
% \end{function}
%
% \subsubsection{标题命令}
-% \begin{function}[added = 2021-05-05]{\bichapter,\bichapter*,\bisection,\bisection*,\bisubsection,\bisubsection*}
+% \begin{function}[added = 2021-05-05]{\bichapter,\bisection,\bisubsection}
% \begin{syntax}
-% \tn{bichapter}\oarg{目录中文标题}\marg{中文标题}\marg{目录英文标题}
% \tn{bichapter*}\oarg{目录中文标题}\marg{中文标题}\marg{目录英文标题}
-% \tn{bisection}\oarg{目录中文标题}\marg{中文标题}\marg{目录英文标题}
% \tn{bisection*}\oarg{目录中文标题}\marg{中文标题}\marg{目录英文标题}
-% \tn{bisubsection}\oarg{目录中文标题}\marg{中文标题}\marg{目录英文标题}
% \tn{bisubsection*}\oarg{目录中文标题}\marg{中文标题}\marg{目录英文标题}
% \end{syntax}
% 双语目录的标题命令目前设置了常用的三个级别,它们将中文标题正常输出,并使中英文标题加入双语目录,这个功能是为国内一些大学的学位论文模板的要求设计,在一般情况和英文模式下不需要使用。
%
% 它们的星号变体命令使文中标题不编号,但是仍然加入双语目录,若英文标题参数空置那么仅加入中文目录而不加入英文目录,这一特点与 \tn{chapter*} 等命令的行为不太一样,在一些情况下会用到。可选参数是目录中的中文标题,默认与中文标题一致,正文标题过长时可用它设置在目录中显示的标题。双语目录的格式是一致的,共享使用 \tn{tocset} 的设置,英文目录的章级别标题名及编号的修改方式如下
-% \changes{v1.25u}{2021/05/05}{增加与双语目录配合的标题命令。}
+% \changes{v1.25v}{2021/05/05}{增加与双语目录配合的标题命令。}
% \end{function}
%
-% \begin{function}{biname,binmuber}
+% \begin{function}{chapter/biname,chapter/binmuber}
% \begin{syntax}
-% chapter/biname = \{<英文目录前名字|(Chapter\tn{space})>,<英文目录后名字>\}
-% chapter/binmuber = <英文目录数字输出命令|(\tn{arabic\{chapter\}})>
+% biname = \{<英文目录前名字|(Chapter\tn{space})>,<英文目录后名字>\}
+% binmuber = <英文目录数字输出命令|(\tn{arabic\{chapter\}})>
% \end{syntax}
% 类似 \CTeX 的 \opt{name} 和 \opt{nmuber} 选项,它们用于设置主文区 \tn{bichapter} 等标题命令在英文目录中的前后名字与编号,目前只支持通常改变名字与编号的 chapter 级别。
% \end{function}
@@ -317,7 +314,7 @@
% \changes{v1.10}{2021/01/08}{修复了 \opt{linktopage} 选项关闭时目录中标题编号无超链接的问题。}
% \changes{v1.23}{2021/03/19}{修复在 \pkg{ctex} v2.5.6 更新后 \cls{easybook} 与 \pkg{hyperref} 冲突问题。}
% \changes{v1.24}{2021/04/05}{增加 \pkg{hyperref} 超链接选项完整的支持。}
-% \changes{v1.25u}{2021/05/06}{模块名 \opt{link} 改为 \opt{refset},\opt{link} 作为兼容性保留。}
+% \changes{v1.25v}{2021/05/06}{模块名 \opt{link} 改为 \opt{refset},\opt{link} 作为兼容性保留。}
% \end{function}
%
% \begin{optdesc}
@@ -374,7 +371,7 @@
% \ding{229} 以上选项路径为 \opt{subfont/...}
% \changes{v1.10}{2021/01/08}{加入自定义非正文字体选项。}
% \changes{v1.23}{2021/02/08}{修复使用 \tn{zihao} 命令设置字体失效的问题。}
-% \changes{v1.25u}{2021/05/31}{其它字体模块名由 \opt{elsefont} 改为 \opt{subfont},并增加数学字体的选项 \opt{subfont/math}。}
+% \changes{v1.25v}{2021/05/31}{其它字体模块名由 \opt{elsefont} 改为 \opt{subfont},并增加数学字体的选项 \opt{subfont/math}。}
% \end{function}
%
% \begin{optdesc}
@@ -399,7 +396,7 @@
% \changes{v1.21}{2021/01/11}{增加 \opt{bibset} 选项,可以使用 \hologo{BibTeX} 或 \hologo{biber} 编译参考文献。}
% \changes{v1.23}{2021/02/23}{使用 \opt{bibset} 选项时可设置标注风格。}
% \changes{v1.24}{2021/04/09}{可以不载入参考文献包手动配置参考文献格式。}
-% \changes{v1.25u}{2021/05/12}{取消 \opt{bib-loadpkg} 选项,由是否设置参考文献数据库来决定载入宏包。}
+% \changes{v1.25v}{2021/05/12}{取消 \opt{bib-loadpkg} 选项,由是否设置参考文献数据库来决定载入宏包。}
% \end{function}
%
% \begin{optdesc}
@@ -605,7 +602,7 @@
% 上面几个选项用于设置脚注格式,\opt{fnparskip} 和 \opt{fnparindent} 选项仅在 \opt{fnhang = true} 时有效。\opt{fnhang} 用于将脚注设置为悬挂缩进的格式,\opt{fnmark-pos} 选项设置脚注编号的位置,正常文本或是上标形式。\opt{fnmark-num} 选项设置脚注编号的格式,默认为原生样式 \opt{plain},还可以改为 \opt{pifont} 的各个版本,从左往右依次为普通版、阴文衬线版、阳文无衬线版和阴文无衬线版,缺点是它们的编号仅包括1-10。
%
% \opt{fnmark-form} 是脚注标记的格式,在此设置字体命令会覆盖 \opt{subfont/footnote} 的设置,最后一个格式命令可以带有一个参数,这个参数接受脚注编号,一般配合 \opt{fnmark-num = plain} 使用。\opt{afterfnmark} 是脚注标记后的代码,一般用于设置标记与文本间的距离。
-% \changes{v1.25u}{2021/05/12}{增加脚注样式设置选项。}
+% \changes{v1.25v}{2021/05/12}{增加脚注样式设置选项。}
% \end{function}
%
% \subsection{目录样式}
@@ -624,7 +621,7 @@
% \opt{format} 是目录中标题的格式,可以设置字体和加入垂直间距等,垂直间距最好使用无间距重合的 \tn{addvspace} 命令,带有加号的 \opt{format+} 选项用于在已有的格式命令后附加内容。\opt{indent} 是目录中标题在页面左侧的缩进距离,应该有长度单位。\opt{rule} 选项中一般应当使用 \tn{tocrule} 命令,将会在接下来介绍。\opt{numsep} 是有编号的标题在目录中编号与标题的间距。
% \changes{v1.21}{2021/01/13}{增加配置目录样式的选项。}
% \changes{v1.24}{2021/04/20}{增加目录中编号与标题的间距选项 \opt{numsep}。}
-% \changes{v1.25u}{2021/05/14}{可以分别设置图片、表格和代码目录的格式。}
+% \changes{v1.25v}{2021/05/14}{可以分别设置图片、表格和代码目录的格式。}
% \end{function}
%
% \begin{function}[added = 2021-01-13,updated = 2021-04-20]{\tocrule,\EbNumberLine}
@@ -709,7 +706,7 @@
% \tn{end}\marg{环境名}
% \end{syntax}
% \pkg{tabularray} 是一个较新的宏包,不仅提供了 \pkg{tabularx}、\pkg{multirow}、和 \pkg{booktabs} 宏包的功能,并且不依赖其它宏包与它们同时使用不会产生冲突,还实现了用简便的键值列表方式设置表格样式。目前除了表头斜线以及跨页功能存在不足,其它方面已满足对表格绝大多数格式的需求,具体用法可见宏包的说明文档。
-% \changes{v1.25u}{2021/05/17}{使用功能更便捷齐全的 \pkg{tabularray} 宏包设置表格样式。}
+% \changes{v1.25v}{2021/05/17}{使用功能更便捷齐全的 \pkg{tabularray} 宏包设置表格样式。}
% \end{function}
%
% \subsection{列表}
@@ -780,7 +777,7 @@
% \ \tn{item} <习题内容>
% \tn{end}\marg{exercise}
% \end{syntax}
-% 习题环境 \env{exercise} 的标题紧接上一节编号并加入目录与页眉,当使用星号参数时不进行编号,使用+号参数独立编号并启用 \pkg{tcolorbox} 支持生成标题,并使 \opt{color} 生效。第二个键值列表的选项与小节 \ref{subsec:sort list} 排序列表相同,\opt{number} 的编号格式也是如此。第一个键值列表中包含的选项如下
+% 习题环境 \env{exercise} 的标题紧接上一节编号并加入目录与页眉,当使用星号参数时不进行编号,使用+号参数独立编号并启用 \pkg{tcolorbox} 支持生成标题,并使 \opt{color} 生效。第三个键值列表的选项与小节 \ref{subsec:sort list} 排序列表相同,\opt{number} 的编号格式也是如此。第一个键值列表中包含的选项如下
% \changes{v1.23}{2021/02/08}{增加准确的习题盒子标题目录锚点。}
% \end{function}
%
@@ -791,12 +788,12 @@
% number = <习题编号格式|(1.)>
% numsep = <编号与标题的间距|(0.5\tn{ccwd})>
% \end{syntax}
-% 第三个键值列表选项在是否使用+号参数时用法不同,使用+号参数时为 \pkg{tcolorbox} 的盒子选项,例如 \opt{boxrule} 和 \opt{fontupper}。不使用+号参数时相当于设置 \tn{ctexset}\{section = {\#1}\} 键值选项列表,例如 \opt{format} 和 \opt{beforeskip}。另外还可以使用 \tn{exerprologue} 命令在习题环境开始前插入一段内容,可以是文本或者代码,需要在每一个习题环境前使用。
+% 第二个键值列表选项在是否使用+号参数时用法不同,使用+号参数时为 \pkg{tcolorbox} 的盒子选项,例如 \opt{boxrule} 和 \opt{fontupper}。不使用+号参数时相当于设置 \tn{ctexset}\{section = {\#1}\} 键值选项列表,例如 \opt{format} 和 \opt{beforeskip}。另外还可以使用 \tn{exerprologue} 命令在习题环境开始前插入一段内容,可以是文本或者代码,需要在每一个习题环境前使用。
% \end{function}
%
% \begin{ctexexam}
% \exerprologue{习题前的一段文本}
-% \begin{exercise}+[color = LightSkyBlue][itemsep = 1ex]
+% \begin{exercise}+[color = LightSkyBlue](after skip = 3.25ex)[itemsep = 1ex]
% \item 习题内容
% \item 习题内容
% \end{exercise}
@@ -882,7 +879,7 @@
% \tn{qtyrange}\oarg{键值列表}\marg{数字1}\marg{数字2}\marg{单位}
% \end{syntax}
% \pkg{siunitx} 宏包的 \tn{num} 命令可以输出以科学计数法表示的数值,单位格式化命令 \tn{unit} 包含文字项目(例如字母或数字)时,使用 . 和 \~{} 放置在单元乘积中间,并使用 \_ 和 \^{} 正确放置指定的下标和上标。格式化方法可在数学和文本模式下使用。而 \tn{qty} 命令可用来输出带有单位的量,\tn{qtyrange} 可以输出带有范围和单位的量。
-% \changes{v1.25u}{2021/05/18}{\pkg{siunitx} 宏包 v3.0.0 更新后用法改变,修改相关配置选项。}
+% \changes{v1.25v}{2021/05/18}{\pkg{siunitx} 宏包 v3.0.0 更新后用法改变,修改相关配置选项。}
% \end{function}
%
% \begin{ctexexam}
@@ -1020,7 +1017,7 @@
%<*class>
\NeedsTeXFormat{LaTeX2e}[2020/10/01]
\RequirePackage{l3keys2e}
-\ProvidesExplClass{easybook}{2021/06/06}{1.25u}{beta}
+\ProvidesExplClass{easybook}{2021/06/07}{1.25v}{beta}
\bool_set_false:N \l__eb_compile_draft_bool
\bool_set_false:N \l__eb_title_newline_bool
@@ -1264,7 +1261,7 @@
%<*package>
\NeedsTeXFormat{LaTeX2e}[2020/10/01]
\RequirePackage{etoolbox}
-\ProvidesExplPackage{easybase}{2021/06/06}{1.25u}{beta}
+\ProvidesExplPackage{easybase}{2021/06/07}{1.25v}{beta}
\cs_generate_variant:Nn \eb_ctex_define:nn { nx }
\cs_generate_variant:Nn \int_to_arabic:n { v }
@@ -2007,7 +2004,7 @@
{ chapter,section,subsection }
\seq_map_inline:Nn \c__eb_bitoc_title_level_seq
{
- \exp_args:Nc \NewDocumentCommand {bi#1}{sO{##3}mm}
+ \exp_args:Nc \NewDocumentCommand { bi#1 }{sO{##3}mm}
{
\IfBooleanTF{##1}
{
@@ -2390,9 +2387,11 @@
\captionsetup[figure][bi-second]{name = Figure}
\captionsetup[table][bi-second]{name = Table}
}
-\prop_gset_from_keyval:Nn \g__tblr_default_tblr_table_prop
- { stretch = \fp_use:N \l__eb_spread_table_fp }
-\SetTblrDefault{rows = {abovesep = 4pt,belowsep = 2pt}}
+\SetTblrDefault
+ {
+ rows = {abovesep = 4pt,belowsep = 2pt},
+ stretch = \fp_use:N \l__eb_spread_table_fp
+ }
\eb_at_begin_environment:nn { tabular,tabularx }
{
\exp_args:Nx \linespread { \fp_use:N \l__eb_spread_table_fp }
@@ -2699,9 +2698,9 @@
fonttitle = \sffamily,
boxrule = \eb@rule@width@dim
}
- \newtcbox[auto~counter]{\eb@exercise@box}[1]{tc-exercise,#1}
- \tl_new:N \eb@list@prologue
- \cs_new:Npn \exerprologue #1 { \tl_set:Nn \eb@list@prologue {#1} }
+ \newtcbox[auto~counter]{\eb@tc@exercise@box}[1]{tc-exercise,#1}
+ \tl_new:N \eb@tc@list@prologue
+ \cs_new:Npn \exerprologue #1 { \tl_set:Nn \eb@tc@list@prologue {#1} }
\NewDocumentEnvironment{outline}{O{}D(){\abstractname}o+b}
{
\begin{tcolorbox}[tc-outline,title = #2,IfValueT = {#3}{#3}]
@@ -2715,7 +2714,7 @@
\IfValueT{#3}{ \keys_set:nn { eb/exercise } {#3} }
\IfBooleanTF{#2}
{
- \eb@exercise@box
+ \eb@tc@exercise@box
{
fuzzy~halo = 5pt~with~\eb@tc@background@color,
IfValueT = {#4}{#4},
@@ -2748,11 +2747,11 @@
{\section{\eb@tc@exercise@title}}
\group_end:
}
- \tl_if_empty:NF \eb@list@prologue { \eb@list@prologue }
+ \tl_if_empty:NF \eb@tc@list@prologue { \eb@tc@list@prologue }
\begin{enumerate}[\eb@tc@list@number,labelsep = 0.5\ccwd,#5]
#6
\end{enumerate}
- \tl_gclear:N \eb@list@prologue
+ \tl_gclear:N \eb@tc@list@prologue
}{}
\DeclareTColorBox{easybox}{sO{DarkCyan}d()O{}}
{
@@ -2801,7 +2800,7 @@
{
standard~jigsaw,
nobeforeafter,tcbox~raise~base,
- top = 1.25ut,bottom = 1.25ut,left = 1.25ut,right = 1.25ut,
+ top = 1.25vt,bottom = 1.25vt,left = 1.25vt,right = 1.25vt,
boxrule = 0.75pt,arc = 1pt,
colback = #1,opacityback = 0.12,colframe = #1,#3
}{#2}
diff --git a/macros/latex/contrib/easybook/easybook.pdf b/macros/latex/contrib/easybook/easybook.pdf
index 599c35aff2..99052846ad 100644
--- a/macros/latex/contrib/easybook/easybook.pdf
+++ b/macros/latex/contrib/easybook/easybook.pdf
Binary files differ
diff --git a/macros/latex/contrib/hvfloat/Changes b/macros/latex/contrib/hvfloat/Changes
index 90d8f75e71..18e87aded3 100644
--- a/macros/latex/contrib/hvfloat/Changes
+++ b/macros/latex/contrib/hvfloat/Changes
@@ -1,4 +1,7 @@
hvfloat.sty:
+2.27 2021-06-07 - added \tabcaptionbelow
+ - fix bug with vertical alignment for top captions
+ - fix for local caption and subcaption setting
2.26 2021-05-31 - allow option wide in twocolumn mode
- allow a stretched minipage for
multifloat and multisubfloat by using
diff --git a/macros/latex/contrib/hvfloat/doc/examples/capPos.inc b/macros/latex/contrib/hvfloat/doc/examples/capPos.inc
new file mode 100644
index 0000000000..0acdf34bf0
--- /dev/null
+++ b/macros/latex/contrib/hvfloat/doc/examples/capPos.inc
@@ -0,0 +1,129 @@
+
+\subsection{\texttt{default}}
+\blindtext
+
+\begin{lstlisting}
+\hvFloat{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+\begin{lstlisting}
+\hvFloat{figure}{\includegraphics{frose}}{\capLongText}{}
+\end{lstlisting}
+
+\hvFloat{figure}{\includegraphics{frose}}{\capLongText}{}
+
+\blindtext
+
+\NewColumn
+
+
+
+%----------------------top-----------------------------------
+\subsection{\texttt{capPos=top}}
+
+\begin{lstlisting}
+\hvFloat[capPos=top]{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=top]{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+\begin{lstlisting}
+\hvFloat[capPos=top]{figure}{\includegraphics{frose}}{\capLongText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=top]{figure}{\includegraphics{frose}}{\capLongText}{}
+
+\blindtext
+
+\NewColumn
+
+%----------------------before-----------------------------------
+\subsection{\texttt{capPos=before}, same as \texttt{capPos=left}}
+
+\begin{lstlisting}
+\hvFloat[capPos=before]{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=before]{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+\begin{lstlisting}
+\hvFloat[capPos=before]{figure}{\includegraphics{frose}}{\capLongText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=before]{figure}{\includegraphics{frose}}{\capLongText}{}
+
+\blindtext
+\NewColumn
+
+%----------------------after-----------------------------------
+\subsection{\texttt{capPos=after}, same as \texttt{capPos=right}}
+
+\begin{lstlisting}
+\hvFloat[capPos=after]{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=after]{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+\begin{lstlisting}
+\hvFloat[capPos=after]{figure}{\includegraphics{frose}}{\capLongText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=after]{figure}{\includegraphics{frose}}{\capLongText}{}
+
+\blindtext
+
+\NewColumn
+
+%----------------------inner-----------------------------------
+\subsection{\texttt{capPos=inner}}
+
+\begin{lstlisting}
+\hvFloat[capPos=inner]{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=inner]{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+\begin{lstlisting}
+\hvFloat[capPos=inner]{figure}{\includegraphics{frose}}{\capLongText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=inner]{figure}{\includegraphics{frose}}{\capLongText}{}
+
+\blindtext
+
+\NewColumn
+
+
+%----------------------outer-----------------------------------
+\subsection{\texttt{capPos=outer}}
+
+\begin{lstlisting}
+\hvFloat[capPos=outer]{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=outer]{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+\begin{lstlisting}
+\hvFloat[capPos=outer]{figure}{\includegraphics{frose}}{\capLongText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=outer]{figure}{\includegraphics{frose}}{\capLongText}{}
+
+\blindtext
+
+\NewColumn
+
diff --git a/macros/latex/contrib/hvfloat/doc/examples/capPos.ltx b/macros/latex/contrib/hvfloat/doc/examples/capPos.ltx
deleted file mode 100644
index 9fcd593abb..0000000000
--- a/macros/latex/contrib/hvfloat/doc/examples/capPos.ltx
+++ /dev/null
@@ -1,34 +0,0 @@
-\documentclass[twoside,DIV=11]{scrartcl}
-%% $Id: capPos.ltx 72 2021-05-02 11:40:10Z herbert $
-
-\input{preamble.ltx}
-\usepackage{multicol}
-\usepackage[all=!htb]{hvfloat-fps}
-
-\setlength\columnseprule{0.4pt}
-\def\capShortText{A short caption}
-\def\capLongText{Here comes a caption to show the justification of the text relative to the object. It refers to
-the optional argument \texttt{capPos}.}
-
-\let\OrigBlindtext\blindtext
-\def\blindtext{\TeX\ is a typesetting language. Instead of visually formatting your text, you enter y
-our manuscript text intertwined with \TeX\ commands in a plain text file. You then run \TeX\ to
-produce formatted output, such as a PDF file. %Thus, in contrast to standard word processors,
-%your document is a separate file that does not pretend to be a representation of the final
-%typeset output, and so can be easily edited and manipulated.
-}
-
-
-
-\begin{document}
-\part{Examples for \texttt{capPos} and onecolumn mode}\clearpage
-\let\NewColumn\clearpage
-\input{capPos}
-
-\twocolumn[\part{Examples for \texttt{capPos} and twocolumn mode}]
-\def\blindtext{\OrigBlindtext}
-\let\NewColumn\columnbreak
-\input{capPos}
-
-
-\end{document} \ No newline at end of file
diff --git a/macros/latex/contrib/hvfloat/doc/examples/capPos.tex b/macros/latex/contrib/hvfloat/doc/examples/capPos.tex
index db2e889f6e..3887dfd06e 100644
--- a/macros/latex/contrib/hvfloat/doc/examples/capPos.tex
+++ b/macros/latex/contrib/hvfloat/doc/examples/capPos.tex
@@ -1,129 +1,50 @@
+\documentclass[twoside,DIV=13]{scrartcl}
+%% $Id: capPos.tex 103 2021-05-31 12:37:11Z herbert $
-\section{\texttt{default}}
-\blindtext
+\input{preamble.ltx}
+\usepackage{multicol}
+\usepackage[all=!htb]{hvfloat-fps}
-\begin{lstlisting}
-\hvFloat{figure}{\includegraphics{frose}}{\capShortText}{}
-\end{lstlisting}
+\setlength\columnseprule{0.4pt}
+\def\capShortText{A short caption}
+\def\capLongText{Here comes a caption to show the justification of the text relative to the object. It refers to
+the optional argument \texttt{capPos}.}
-\hvFloat{figure}{\includegraphics{frose}}{\capShortText}{}
+\let\OrigBlindtext\blindtext
+\def\myblindtext{\TeX\ is a typesetting language. Instead of visually formatting your text, you enter y
+our manuscript text intertwined with \TeX\ commands in a plain text file. You then run \TeX\ to
+produce formatted output, such as a PDF file. %Thus, in contrast to standard word processors,
+%your document is a separate file that does not pretend to be a representation of the final
+%typeset output, and so can be easily edited and manipulated.
+}
-\blindtext
-\begin{lstlisting}
-\hvFloat{figure}{\includegraphics{frose}}{\capLongText}{}
-\end{lstlisting}
-\hvFloat{figure}{\includegraphics{frose}}{\capLongText}{}
+\begin{document}
-\blindtext
+\tableofcontents
-\NewColumn
+\newpage
+\section{Examples for \texttt{capPos} and onecolumn mode}
+\let\NewColumn\clearpage
+\let\blindtext\myblindtext
+\input{capPos.inc}
+\section{Examples for \texttt{capVPos} and onecolumn mode }
+Horizontal alignment with the optional arguments from package \texttt{caption}, e.g. \texttt{singlelinecheck=off} for short captions.
-%----------------------top-----------------------------------
-\section{\texttt{capPos=top}}
+\input{capVPos.inc}
-\begin{lstlisting}
-\hvFloat[capPos=top]{figure}{\includegraphics{frose}}{\capShortText}{}
-\end{lstlisting}
-\hvFloat[capPos=top]{figure}{\includegraphics{frose}}{\capShortText}{}
+\twocolumn[\section{Examples for \texttt{capPos} and twocolumn mode}]
+\let\NewColumn\columnbreak
+\input{capPos.inc}
-\blindtext
+\let\blindtext\OrigBlindtext
+\section{Examples for \texttt{capVPos} and twocolumn mode (\texttt{capPos=right})}
+\let\NewColumn\columnbreak
+\input{capVPos.inc}
-\begin{lstlisting}
-\hvFloat[capPos=top]{figure}{\includegraphics{frose}}{\capLongText}{}
-\end{lstlisting}
-
-\hvFloat[capPos=top]{figure}{\includegraphics{frose}}{\capLongText}{}
-
-\blindtext
-
-\NewColumn
-
-%----------------------before-----------------------------------
-\section{\texttt{capPos=before}, same as \texttt{capPos=left}}
-
-\begin{lstlisting}
-\hvFloat[capPos=before]{figure}{\includegraphics{frose}}{\capShortText}{}
-\end{lstlisting}
-
-\hvFloat[capPos=before]{figure}{\includegraphics{frose}}{\capShortText}{}
-
-\blindtext
-
-\begin{lstlisting}
-\hvFloat[capPos=before]{figure}{\includegraphics{frose}}{\capLongText}{}
-\end{lstlisting}
-
-\hvFloat[capPos=before]{figure}{\includegraphics{frose}}{\capLongText}{}
-
-\blindtext
-\NewColumn
-
-%----------------------after-----------------------------------
-\section{\texttt{capPos=after}, same as \texttt{capPos=right}}
-
-\begin{lstlisting}
-\hvFloat[capPos=after]{figure}{\includegraphics{frose}}{\capShortText}{}
-\end{lstlisting}
-
-\hvFloat[capPos=after]{figure}{\includegraphics{frose}}{\capShortText}{}
-
-\blindtext
-
-\begin{lstlisting}
-\hvFloat[capPos=after]{figure}{\includegraphics{frose}}{\capLongText}{}
-\end{lstlisting}
-
-\hvFloat[capPos=after]{figure}{\includegraphics{frose}}{\capLongText}{}
-
-\blindtext
-
-\NewColumn
-
-%----------------------inner-----------------------------------
-\section{\texttt{capPos=inner}}
-
-\begin{lstlisting}
-\hvFloat[capPos=inner]{figure}{\includegraphics{frose}}{\capShortText}{}
-\end{lstlisting}
-
-\hvFloat[capPos=inner]{figure}{\includegraphics{frose}}{\capShortText}{}
-
-\blindtext
-
-\begin{lstlisting}
-\hvFloat[capPos=inner]{figure}{\includegraphics{frose}}{\capLongText}{}
-\end{lstlisting}
-
-\hvFloat[capPos=inner]{figure}{\includegraphics{frose}}{\capLongText}{}
-
-\blindtext
-
-\NewColumn
-
-
-%----------------------outer-----------------------------------
-\section{\texttt{capPos=outer}}
-
-\begin{lstlisting}
-\hvFloat[capPos=outer]{figure}{\includegraphics{frose}}{\capShortText}{}
-\end{lstlisting}
-
-\hvFloat[capPos=outer]{figure}{\includegraphics{frose}}{\capShortText}{}
-
-\blindtext
-
-\begin{lstlisting}
-\hvFloat[capPos=outer]{figure}{\includegraphics{frose}}{\capLongText}{}
-\end{lstlisting}
-
-\hvFloat[capPos=outer]{figure}{\includegraphics{frose}}{\capLongText}{}
-
-\blindtext
-
-\NewColumn
+\end{document} \ No newline at end of file
diff --git a/macros/latex/contrib/hvfloat/doc/examples/capVPos.inc b/macros/latex/contrib/hvfloat/doc/examples/capVPos.inc
new file mode 100644
index 0000000000..10ef70e88c
--- /dev/null
+++ b/macros/latex/contrib/hvfloat/doc/examples/capVPos.inc
@@ -0,0 +1,133 @@
+%\define@choicekey*+{hvSet}{capVPos}[\val\nr]{bottom,center,top}[center]{%
+
+
+\iffalse
+justification=
+ justified
+ centering
+ centerlast
+ centerfirst
+ raggedright
+ RaggedRight
+ raggedleft
+\fi
+
+\subsection{\texttt{default}, same as \texttt{center}}
+\blindtext
+
+\begin{lstlisting}
+\hvFloat[capPos=right]{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=right]{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+\begin{lstlisting}
+\hvFloat[capPos=right,capFormat={singlelinecheck=off}]{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=right,capFormat={singlelinecheck=off}]{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+\begin{lstlisting}
+\hvFloat[capPos=right]{figure}{\includegraphics{frose}}{\capLongText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=right]{figure}{\includegraphics{frose}}{\capLongText}{}
+
+\blindtext
+
+\NewColumn
+
+
+
+%----------------------top-----------------------------------
+\subsection{\texttt{capVPos=top}}
+
+\begin{lstlisting}
+\hvFloat[capPos=right,capVPos=top]{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=right,capVPos=top]{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+
+\begin{lstlisting}
+\hvFloat[capPos=right,capFormat={singlelinecheck=off},capVPos=top]{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=right,capFormat={singlelinecheck=off},capVPos=top]{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+
+\begin{lstlisting}
+\hvFloat[capPos=right,capVPos=top]{figure}{\includegraphics{frose}}{\capLongText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=right,capVPos=top]{figure}{\includegraphics{frose}}{\capLongText}{}
+
+\blindtext
+
+\NewColumn
+
+%----------------------bottom-----------------------------------
+\subsection{\texttt{capVPos=bottom}}
+
+\begin{lstlisting}
+\hvFloat[capPos=right,capVPos=bottom]{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=right,capVPos=bottom]{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+
+\begin{lstlisting}
+\hvFloat[capPos=right,capFormat={singlelinecheck=off},capVPos=bottom]{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=right,capFormat={singlelinecheck=off},capVPos=bottom]{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+\begin{lstlisting}
+\hvFloat[capPos=right,capVPos=bottom]{figure}{\includegraphics{frose}}{\capLongText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=right,capVPos=bottom]{figure}{\includegraphics{frose}}{\capLongText}{}
+
+\blindtext
+\NewColumn
+
+%----------------------center-----------------------------------
+\subsection{\texttt{capPos=center}}
+
+\begin{lstlisting}
+\hvFloat[capPos=right,capVPos=center]{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=right,capVPos=center]{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+\begin{lstlisting}
+\hvFloat[capPos=right,capFormat={singlelinecheck=off},capVPos=center]{figure}{\includegraphics{frose}}{\capShortText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=right,capFormat={singlelinecheck=off},capVPos=center]{figure}{\includegraphics{frose}}{\capShortText}{}
+
+\blindtext
+
+\begin{lstlisting}
+\hvFloat[capPos=right,capVPos=center]{figure}{\includegraphics{frose}}{\capLongText}{}
+\end{lstlisting}
+
+\hvFloat[capPos=right,capVPos=center]{figure}{\includegraphics{frose}}{\capLongText}{}
+
+\blindtext
+
+\NewColumn
diff --git a/macros/latex/contrib/hvfloat/doc/hvfloat.pdf b/macros/latex/contrib/hvfloat/doc/hvfloat.pdf
index 981f685c0a..ce628eaf57 100644
--- a/macros/latex/contrib/hvfloat/doc/hvfloat.pdf
+++ b/macros/latex/contrib/hvfloat/doc/hvfloat.pdf
Binary files differ
diff --git a/macros/latex/contrib/hvfloat/doc/hvfloat.tex b/macros/latex/contrib/hvfloat/doc/hvfloat.tex
index 807a63415e..df1729be27 100644
--- a/macros/latex/contrib/hvfloat/doc/hvfloat.tex
+++ b/macros/latex/contrib/hvfloat/doc/hvfloat.tex
@@ -1,4 +1,4 @@
-%% $Id: hvfloat.tex 103 2021-05-31 12:37:11Z herbert $
+%% $Id: hvfloat.tex 105 2021-06-07 07:30:15Z herbert $
\listfiles
\errorcontextlines=100
\documentclass[twoside,paper=a4,]{scrartcl}
@@ -261,7 +261,8 @@ be used for own purposes.
\begin{BDef}
\Lcs{figcaption}\OptArg{short caption text}\Largb{caption text}\\
-\Lcs{tabcaption}\OptArg{short caption text}\Largb{caption text}
+\Lcs{tabcaption}\OptArg{short caption text}\Largb{caption text}\\
+\Lcs{tabcaptionbelow}\OptArg{short caption text}\Largb{caption text}\\
\end{BDef}
They are used for the \Lkeyword{nonFloat} keyword, where these macros write captions in the same way but outside of
diff --git a/macros/latex/contrib/hvfloat/latex/hvfloat.sty b/macros/latex/contrib/hvfloat/latex/hvfloat.sty
index 66a354eae6..cb9f1b0742 100644
--- a/macros/latex/contrib/hvfloat/latex/hvfloat.sty
+++ b/macros/latex/contrib/hvfloat/latex/hvfloat.sty
@@ -1,4 +1,4 @@
-%% $Id: hvfloat.sty 103 2021-05-31 12:37:11Z herbert $
+%% $Id: hvfloat.sty 105 2021-06-07 07:30:15Z herbert $
%%
%%
%% IMPORTANT NOTICE:
@@ -15,8 +15,8 @@
%% `hvfloat' offers rotating of captions and objects for floats
%%
\NeedsTeXFormat{LaTeX2e}
-\def\fileversion{2.26}
-\def\filedate{2021/05/26}
+\def\fileversion{2.27}
+\def\filedate{2021/06/07}
\message{`hvfloat' v\fileversion, \filedate\space (Herbert Voss)}
\ProvidesPackage{hvfloat}[\filedate\ rotating of floating objects]
\let\hvFloatFileVersion\fileversion
@@ -29,6 +29,7 @@
\DeclareOption{fbox}{\hv@fboxtrue\setlength{\fboxsep}{1pt}}
\DeclareOption{hyperref}{\hv@hyperreftrue}
\DeclareOption{nostfloats}{\hv@nostfloatstrue}
+\DeclareOption{no-stfloats}{\hv@nostfloatstrue}
\ProcessOptions
@@ -41,6 +42,9 @@
\PassOptionsToPackage{hypcap}{caption}
\RequirePackage{caption}
+\RequirePackage{varwidth}
+\DeclareCaptionBox{varwidth}{\varwidth[b]{#1}#2\endvarwidth}
+
\PassOptionsToPackage{hypcap}{subcaption}
\RequirePackage{subcaption}
\RequirePackage{atbegshi}
@@ -48,6 +52,7 @@
\RequirePackage{expl3,multido}
\RequirePackage{graphicx}
+\RequirePackage{varwidth}
\RequirePackage{xkeyval}
\RequirePackage{ifoddpage}
@@ -136,7 +141,20 @@
\else
\gdef\hv@@capVPos{t}%
\fi
-}{\PackageWarning{hvfloat}{erroneous input (#1) for capVPos ignored. Using bottom.}%
+}{\PackageWarning{hvfloat}{erroneous input (#1) for capVPos ignored. Using center.}%
+ \def\hvSet@capVPos{center}% it is relativ to the object
+ }
+
+\define@choicekey*+{hvSet}{allHPos}[\val\nr]{left,center,right}[center]{%
+ \def\hvSet@allHPos{#1}%
+ \ifcase\nr\relax
+ \gdef\hv@@allHPos{l}%
+ \or
+ \gdef\hv@@allHPos{c}%
+ \else
+ \gdef\hv@@allHPos{r}%
+ \fi
+}{\PackageWarning{hvfloat}{erroneous input (#1) for allHPos ignored. Using center.}%
\def\hvSet@capVPos{center}% it is relativ to the object
}
@@ -230,8 +248,8 @@
%
\newcommand\setDefaults{%
\hv@set{%
- floatPos=, rotAngle=0, capWidth=n, capAngle=0,
- capPos=bottom, capVPos=center, objectPos=center, objectAngle=0,
+ floatPos=, rotAngle=0, capWidth=n, capAngle=0, objectAngle=0,
+ capPos=bottom, capVPos=center, objectPos=center, allHPos=center,
floatCapSep=5pt, useOBox=false, nonFloat=false,
onlyText=false, wide=false, fullpage=false, FULLPAGE=false,
doubleFULLPAGE=false, doublePage=false, doublePAGE=false,
@@ -273,15 +291,28 @@
\setlength\abovecaptionskip{\hvAboveCaptionSkip}%
\setlength\belowcaptionskip{\hvBelowCaptionSkip}%
}
+
+\providecommand\figcaption[2][]{}%
+\providecommand\tabcaption[2][]{}%
+\providecommand\tabcaptionbelow[2][]{}%
%
-\newcommand\figcaption[2][]{%
- \def\@captype{figure}%
+\renewcommand\figcaption[2][]{%
\begingroup
+ \def\@captype{figure}%
\ifx\relax\hv@caption@format\relax\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi
\if$#1$ \caption{#2}\else\caption[#1]{#2}\fi
\endgroup}
-\newcommand\tabcaption[2][]{\def\@captype{table}%
+\renewcommand\tabcaption[2][]{%
+ \begingroup
+ \def\@captype{table}%
+ \edef\hv@caption@format{position=top,\hv@caption@format}%
+ \expandafter\captionsetup\expandafter{\hv@caption@format}%
+ \ifx\relax#1\relax \caption{#2}\else\caption[#1]{#2}\fi
+ \endgroup}
+\renewcommand\tabcaptionbelow[2][]{%
\begingroup
+ \def\@captype{table}%
+ \edef\hv@caption@format{position=below,\hv@caption@format}%
\ifx\relax\hv@caption@format\relax\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi
\ifx\relax#1\relax \caption{#2}\else\caption[#1]{#2}\fi
\endgroup}
@@ -372,6 +403,21 @@
\fi
}
+
+\def\drawSepLine{%
+ \par\noindent
+ \if@twocolumn
+ \ifhv@twoColumnCaption
+ \rule{\linewidth}{0.4pt}\\[-2.5ex]
+ \else
+ \rule{\columnwidth}{0.4pt}\\[-2.5ex]
+ \fi
+ \else
+ \rule{\linewidth}{0.4pt}\\[-2.5ex]
+ \fi
+ \vspace{\hv@sepLineskip}%
+}
+
\newcounter{hv@tempCNTfigA}%
\newcounter{hv@tempCNTfigB}%
\newcounter{hv@tempCNTtabA}%
@@ -415,6 +461,12 @@
\setcounter{hv@tempCNTtabB}{\value{table}}%
\gdef\hv@save@setting{#1}%
\ifx\relax#1\relax\else\setkeys{hvSet}{#1}\fi
+ \ifx\hv@caption@format\@empty\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi
+ \ifx\hv@subcaption@format\@empty\else
+ \expandafter
+ \captionsetup\expandafter[\expandafter s\expandafter u\expandafter b\expandafter]\expandafter
+ {\hv@subcaption@format}%
+ \fi
\gdef\hv@floatType{figure}% presetting
\@ifnextchar+{\do@multiFloat}{\hvFloat@ii[#1]}%
}
@@ -466,20 +518,6 @@
-\def\drawSepLine{%
- \par\noindent
- \if@twocolumn
- \ifhv@twoColumnCaption
- \rule{\linewidth}{0.4pt}\\[-2.5ex]
- \else
- \rule{\columnwidth}{0.4pt}\\[-2.5ex]
- \fi
- \else
- \rule{\linewidth}{0.4pt}\\[-2.5ex]
- \fi
- \vspace{\hv@sepLineskip}%
-}
-
\newcount\hv@cnta
\newcount\hv@cntb
@@ -597,8 +635,7 @@
\saveCaptionSkip% we put this space ourselve
\ifnum\hvSet@capAngle=0 % need rotation?
\savebox\hvCaptionBox{% NO rotation
- \begin{minipage}[b]{\hvCapWidth}%% minipage, to get hyphenation
- \ifx\hv@caption@format\@empty\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi
+ \minipage[b]{\hvCapWidth}%% minipage, to get hyphenation
\ifhv@nonFloat
\ifhv@onlyText
\hv@longCap
@@ -625,22 +662,22 @@
\ifx\hv@shortCap\@empty\caption{\hv@longCap}\else\caption[\hv@shortCap]{\hv@longCap}\fi
\fi
\fi
- \ifx\hv@label\@empty\else\label{\hv@label}\fi
- \end{minipage}%
+ \ifx\hv@label\@empty\else\label{\hv@label}\fi
+ \endminipage
}%
\else
\savebox\hvCaptionBox{% Rotation
\rotatebox{\hvSet@capAngle}{%
- \begin{minipage}[b]{\hvCapWidth}%% minipage, to get hyphenation
- \ifx\relax\hv@caption@format\relax\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi
+ \minipage[b]{\hvCapWidth}%% minipage, to get hyphenation
+% \ifx\relax\hv@caption@format\relax\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi
\ifhv@nonFloat
\ifhv@onlyText
\hv@longCap
\else
\ifx\hv@floatType\hv@figure
- \ifx\relax\hv@shortCap\relax \figcaption{\hv@longCap}\else\figcaption[\hv@shortCap]{\hv@longCap}\fi
+ \ifx\hv@shortCap\@empty \figcaption{\hv@longCap}\else\figcaption[\hv@shortCap]{\hv@longCap}\fi
\else
- \ifx\relax\hv@shortCap\relax \tabcaption{\hv@longCap}\else\tabcaption[\hv@shortCap]{\hv@longCap}\fi
+ \ifx\hv@shortCap\@empty \tabcaption{\hv@longCap}\else\tabcaption[\hv@shortCap]{\hv@longCap}\fi
\fi
\fi
\else
@@ -648,12 +685,12 @@
\hv@longCap
\else
\let\@captype\hv@floatType
- \ifx\relax\hv@shortCap\relax \caption{\hv@longCap}\else\caption[\hv@shortCap]{\hv@longCap}%
+ \ifx\hv@shortCap\@empty \caption{\hv@longCap}\else\caption[\hv@shortCap]{\hv@longCap}%
\fi
\fi
\fi
\ifx\hv@label\@empty\else\label{\hv@label}\fi
- \end{minipage}%
+ \endminipage
}% rotatebox
}% \sbox
\fi
@@ -735,7 +772,7 @@
\savebox{\@tempboxa}{% ***** @tempbox start
\expandafter\ifcase\the\hv@@capPos% 0 is LEFT START \ifcase
\ifx\hvSet@capVPos\hv@Center
- \put@CaptionBox
+ \put@CaptionBox
\hspace{\hvSet@floatCapSep}% capfloatsep
\put@ObjectBox
\else
@@ -847,8 +884,8 @@
}
%
\newenvironment{hvFloatEnv}[1][\textwidth]
- {\minipage{#1}\center}
- {\endcenter\endminipage}
+ {\minipage{#1}}
+ {\endminipage}
%
\ExplSyntaxOn
@@ -1010,6 +1047,7 @@
\global\setlength\hv@leftPageObjectWidth{\dimexpr\paperwidth-1in-\evensidemargin-\hvSet@bindCorrection}%
\global\setlength\hv@tempWidthA{\the\dimexpr-1in-\oddsidemargin+\hvSet@bindCorrection}%
\xdef\hv@@capAngle{\hvSet@capAngle}%
+ \xdef\hv@caption@format@temp{\hv@caption@format}% it gets lost otherwise for next afterpage
\checkoddpage
\ifoddpage
\if@twocolumn
@@ -1036,7 +1074,7 @@
\afterpage{\afterpage{\do@hvFloat@doublePageCaptionRight{#1}}}%
\fi
\fi
- \endgroup% started at main macro \hvFloat
+ \endgroup% started at main macro \hvFloat
}
%
\def\do@hvFloat@doublePageCaptionRight#1{% image on left and right page with caption on the right page ----------------------------------
@@ -1046,9 +1084,9 @@
\setcounter{totalnumber}{0}%
\setcounter{dbltopnumber}{0}%
\def\dblfloatpagefraction{0.5}%
- \begin{\hv@floatType*}[!thb]
+ \begin{\hv@floatType*}[!t]
\global\savebox{\hvObjectBox}{\ifhv@useOBox\usebox{\hvOBox}\else\hv@floatObject\fi}%
- \clipbox*{0 -\depth{} \hv@leftPageObjectWidth{} \height}{\usebox\hvObjectBox}%
+ \clipbox*{0 -\depth{} \hv@leftPageObjectWidth{} \height}{\usebox\hvObjectBox}%
\ifx\hv@label\@empty
\else
\ifx\hv@floatType\hv@figure
@@ -1060,7 +1098,7 @@
\fi
\end{\hv@floatType*}%
\afterpage{%
- \begin{\hv@floatType*}[!thb]
+ \begin{\hv@floatType*}[!t]
\global\savebox{\hvObjectBox}{\ifhv@useOBox\usebox{\hvOBox}\else\hv@floatObject\fi}%
\hspace*{\hv@tempWidthA}%
\noindent
@@ -1078,45 +1116,37 @@
\fi
\label{\hv@label-2}%
\fi
- \ifnum#1>0 % caption on the right
-% \medskip
- \ifnum\hv@@capAngle > 0
-% \ifdim\dp\hvObjectBox > \z@
-% \rotatebox[origin=c]{\hv@@capAngle}{\parbox{\the\dimexpr\ht\hvObjectBox+\dp\hvObjectBox}{%
-% \ifx\relax\hv@shortCap\relax
-% \captionof{\hv@floatType}{\hv@longCap}%
-% \else
-% \captionof{\hv@floatType}[\hv@shortCap]{\hv@longCap}%
-% \fi
-% \ifx\hv@label\@empty\else\label{\hv@label-cap}\fi
-% }}%
-% \else
- \rotatebox[origin=c]{\hv@@capAngle}{\parbox{\the\dimexpr\ht\hvObjectBox+\dp\hvObjectBox}{%
- \ifx\relax\hv@shortCap\relax
- \captionof{\hv@floatType}{\hv@longCap}%
- \else
- \captionof{\hv@floatType}[\hv@shortCap]{\hv@longCap}%
- \fi
- }}%
- \ifx\relax\hv@label\relax\else\label{\hv@label-cap}\fi
-% \fi
+ \ifx\hv@caption@format@temp\@empty\else
+ \expandafter\captionsetup\expandafter{\hv@caption@format@temp}%
+ \fi
+ \ifnum#1>\z@ % caption on the right
+ \ifnum\hv@@capAngle > \z@
+ \rotatebox[origin=c]{\hv@@capAngle}{\parbox{\the\dimexpr\ht\hvObjectBox+\dp\hvObjectBox}{%
+ \ifx\relax\hv@shortCap\relax
+ \caption{\hv@longCap}%
+ \else
+ \caption[\hv@shortCap]{\hv@longCap}%
+ \fi
+ }}%
+ \ifx\relax\hv@label\relax\else\label{\hv@label-cap}\fi
\else
\hspace{\marginparsep}%
\parbox[\hv@@capVPos]{\hv@tempWidthB}{%
+ \abovecaptionskip=0pt% local inside parbox
\vspace{0pt}%
\ifx\hv@shortCap\@empty
- \captionof{\hv@floatType}{\hv@longCap\ifx\hv@label\@empty\else\label{\hv@label-cap}\fi}%
+ \caption{\hv@longCap}%
\else
- \captionof{\hv@floatType}[\hv@shortCap]{\hv@longCap}
+ \caption[\hv@shortCap]{\hv@longCap}
\fi
}%
\ifx\hv@label\@empty\else\label{\hv@label-cap}\fi
\fi
\else % #1 = 0 caption below
\ifx\relax\hv@shortCap\relax
- \captionof{\hv@floatType}{\hv@longCap}%
+ \caption{\hv@longCap}%
\else
- \captionof{\hv@floatType}[\hv@shortCap]{\hv@longCap}%
+ \caption[\hv@shortCap]{\hv@longCap}%
\fi
\ifx\hv@label\@empty\else\label{\hv@label-cap}\fi
\fi
@@ -1162,7 +1192,7 @@
\afterpage{\do@hvFloat@doublePAGECaptionRight{#1}}%
\fi
\fi
- \endgroup
+ \endgroup% startet at main macro
}
%
\def\do@hvFloat@doublePAGECaptionRight#1{% image on left and right page with caption on the right ----------------------------------
@@ -1226,7 +1256,7 @@
\global\setlength\hv@leftPageObjectWidth{\dimexpr\paperwidth-\hvSet@bindCorrection}%
% \savebox\hv@leftBox{\clipbox*{0 0 \the\hv@leftPageObjectWidth{} \height}{\usebox\hvObjectBox}}%
% \savebox\hv@rightBox{\clipbox*{\the\hv@leftPageObjectWidth{} \depth{} \width{} \height}{\usebox\hvObjectBox}}%
- \expandafter\captionsetup\expandafter{\hv@caption@format}%
+% \expandafter\captionsetup\expandafter{\hv@caption@format}%
\ifoddpage
\ifcase\hv@@capPos % =0 Caption before
\if@twocolumn
@@ -1326,8 +1356,8 @@
\def\set@Normal@Bottom@Caption@{%
\begin{\hv@floatType}[!b]
\ifhv@separatorLine\drawSepLine\fi
- \expandafter\captionsetup\expandafter{\hv@caption@format}%
- \ifx\relax\hv@shortCap\relax
+% \expandafter\captionsetup\expandafter{\hv@caption@format}%
+ \ifx\hv@shortCap\@empty
\captionof{\hv@floatType}{\hv@longCap}%
\else
\captionof{\hv@floatType}[\hv@shortCap]{\hv@longCap}%
@@ -1338,8 +1368,8 @@
\def\set@Normal@Bottom@CaptionStar*{%
\begin{\hv@floatType*}[!b]
\ifhv@separatorLine\drawSepLine\fi
- \expandafter\captionsetup\expandafter{\hv@caption@format}%
- \ifx\relax\hv@shortCap\relax
+% \expandafter\captionsetup\expandafter{\hv@caption@format}%
+ \ifx\hv@shortCap\@empty
\captionof{\hv@floatType}{\hv@longCap}%
\else
\captionof{\hv@floatType}[\hv@shortCap]{\hv@longCap}%
@@ -1416,8 +1446,8 @@
\newpage\if@twocolumn\null\newpage\fi
\begin{\hv@floatType}[!b]
\ifhv@separatorLine\drawSepLine\fi
- \expandafter\captionsetup\expandafter{\hv@caption@format}%
- \ifx\relax\hv@shortCap\relax
+% \expandafter\captionsetup\expandafter{\hv@caption@format}%
+ \ifx\hv@shortCap\@empty
\captionof{\hv@floatType}{\hv@longCap}%
\else
\captionof{\hv@floatType}[\hv@shortCap]{\hv@longCap}%
@@ -1457,8 +1487,8 @@
\begin{\hv@floatType*}[!b]
\hv@twoColumnCaptiontrue
\ifhv@separatorLine\drawSepLine\fi
- \expandafter\captionsetup\expandafter{\hv@caption@format}%
- \ifx\relax\hv@shortCap\relax
+% \expandafter\captionsetup\expandafter{\hv@caption@format}%
+ \ifx\hv@shortCap\@empty
\captionof{\hv@floatType}{\hv@longCap}%
\else
\captionof{\hv@floatType}[\hv@shortCap]{\hv@longCap}%
@@ -1500,8 +1530,8 @@
% \setlength\hv@tempWidthB{\dimexpr\ht\hvCaptionBox+\wd\hvObjectBox+2\hvSet@bindCorrection}%
\ifdim\hv@tempWidthB < 2\paperwidth
\rotatebox[origin=lb]{90}{\makebox[\paperheight][c]{\parbox{0.8\ht\hvObjectBox}{%
- \expandafter\captionsetup\expandafter{\hv@caption@format}%
- \ifx\relax\hv@shortCap\relax
+% \expandafter\captionsetup\expandafter{\hv@caption@format}%
+ \ifx\hv@shortCap\@empty
\captionof{\hv@floatType}{\hv@longCap}%
\else
\captionof{\hv@floatType}[\hv@shortCap]{\hv@longCap}%
@@ -1511,7 +1541,7 @@
\else% ifdim: no space left on page
\put(-2\ht\hvCaptionBox,0.5\ht\hvObjectBox){\makebox(0,0){\rotatebox{90}{\minipage{\textwidth}\centering
\parbox{0.8\textwidth}{%
- \ifx\relax\hv@shortCap\relax
+ \ifx\hv@shortCap\@empty
\captionof{\hv@floatType}{\hv@longCap}%
\else
\captionof{\hv@floatType}[\hv@shortCap]{\hv@longCap}%
@@ -1525,8 +1555,8 @@
\ifdim\hv@tempWidthA > \ht\hvCaptionBox
\else
\put(\the\dimexpr1.5\paperwidth-\wd\hvObjectBox-\hvSet@bindCorrection,\the\dimexpr\ht\hvCaptionBox+\abovecaptionskip+\belowcaptionskip){\makebox[0pt][c]{\parbox{\textwidth}{%%
- \expandafter\captionsetup\expandafter{\hv@caption@format}%
- \ifx\relax\hv@shortCap\relax
+% \expandafter\captionsetup\expandafter{\hv@caption@format}%
+ \ifx\hv@shortCap\@empty
\captionof{\hv@floatType}{\hv@longCap}%
\else
\captionof{\hv@floatType}[\hv@shortCap]{\hv@longCap}%
@@ -1583,7 +1613,7 @@
\def\getMultiCaptionAndLabel{%
\global\sbox\hvCaptionBox{\minipage[b]{\linewidth}%
- \ifx\relax\hv@caption@format\relax\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi
+% \ifx\relax\hv@caption@format\relax\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi
\setlength\belowcaptionskip{5pt}%
\setlength\abovecaptionskip{0pt}%
\hv@cntb=\clist_count:N\l_clist_Type
@@ -1614,7 +1644,7 @@
\else
\minipage{\columnwidth}%
\fi
- \ifx\relax\hv@caption@format\relax\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi
+% \ifx\relax\hv@caption@format\relax\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi
\ifx\hvSet@objectPos\hv@Right\raggedleft\else
\ifx\hvSet@objectPos\hv@Left\raggedleft\else
\ifx\hvSet@objectPos\hv@Center\centering
@@ -1643,7 +1673,7 @@
\def\getMultiSubCaptionAndLabel{%
\global\sbox\hvCaptionBox{\minipage{\linewidth}%
- \ifx\hv@caption@format\@empty\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi
+% \ifx\hv@caption@format\@empty\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi
\setlength\belowcaptionskip{5pt}%
\setlength\abovecaptionskip{0pt}%
\xdef\@captype{\clist_item:Nn\l_clist_Type{1}}% the same for all subfloats
@@ -1665,11 +1695,11 @@
\else
\minipage{\columnwidth}%
\fi
- \ifx\hv@subcaption@format\@empty\else
- \expandafter
- \captionsetup\expandafter[\expandafter s\expandafter u\expandafter b\expandafter]\expandafter
- {\hv@subcaption@format}%
- \fi
+% \ifx\hv@subcaption@format\@empty\else
+% \expandafter
+% \captionsetup\expandafter[\expandafter s\expandafter u\expandafter b\expandafter]\expandafter
+% {\hv@subcaption@format}%
+% \fi
\ifx\hvSet@objectPos\hv@Right\raggedleft\else
\ifx\hvSet@objectPos\hv@Left\raggedleft\else
\ifx\hvSet@objectPos\hv@Center\centering
@@ -1712,7 +1742,6 @@
\def\getSingleCaptionAndLabel{%
\global\sbox\hvCaptionBox{\minipage{\linewidth}%
- \ifx\relax\hv@caption@format\relax\else\expandafter\captionsetup\expandafter{\hv@caption@format}\fi
\setlength\belowcaptionskip{5pt}%
\setlength\abovecaptionskip{0pt}%
\edef\@captype{\hv@floatType}%
diff --git a/macros/latex/contrib/hyperref/ChangeLog.txt b/macros/latex/contrib/hyperref/ChangeLog.txt
index ba313e8abe..bfe05e95ec 100644
--- a/macros/latex/contrib/hyperref/ChangeLog.txt
+++ b/macros/latex/contrib/hyperref/ChangeLog.txt
@@ -1,3 +1,6 @@
+2021-06-07 Ulrike Fischer/David Carlisle
+ * fix colons in label, issue #194
+
2021-06-05 Ulrike Fischer/David Carlisle
* handle non-ascii labels, issue #185
* suppress break points after whatsits issue #187
diff --git a/macros/latex/contrib/hyperref/README.md b/macros/latex/contrib/hyperref/README.md
index 7c883e7808..410e5da5f9 100644
--- a/macros/latex/contrib/hyperref/README.md
+++ b/macros/latex/contrib/hyperref/README.md
@@ -1,6 +1,6 @@
# README for hyperref bundle
-Version 2021-06-05 v7.00l
+Version 2021-06-07 v7.00m
## INTRODUCTION
diff --git a/macros/latex/contrib/hyperref/doc/backref.pdf b/macros/latex/contrib/hyperref/doc/backref.pdf
index 5d94d8f215..f1ecb3f127 100644
--- a/macros/latex/contrib/hyperref/doc/backref.pdf
+++ b/macros/latex/contrib/hyperref/doc/backref.pdf
Binary files differ
diff --git a/macros/latex/contrib/hyperref/doc/hyperref-doc.html b/macros/latex/contrib/hyperref/doc/hyperref-doc.html
index 83fa1d4537..cc1f8fb634 100644
--- a/macros/latex/contrib/hyperref/doc/hyperref-doc.html
+++ b/macros/latex/contrib/hyperref/doc/hyperref-doc.html
@@ -25,7 +25,7 @@ href="https://github.com/latex3/hyperref/issues" class="url" ><span
class="ec-lmvtt-10x-x-120">https://github.com/latex3/hyperref/issues</span></a><span
class="ec-lmr-12">)</span></div><br />
<div class="date" ><span
-class="ec-lmr-12">2021-06-05 v7.00l</span></div>
+class="ec-lmr-12">2021-06-07 v7.00m</span></div>
</div>
<h3 class="likesectionHead"><a
id="x1-1000"></a>Contents</h3>
diff --git a/macros/latex/contrib/hyperref/doc/hyperref-doc.pdf b/macros/latex/contrib/hyperref/doc/hyperref-doc.pdf
index 51a1372af1..4d024bd239 100644
--- a/macros/latex/contrib/hyperref/doc/hyperref-doc.pdf
+++ b/macros/latex/contrib/hyperref/doc/hyperref-doc.pdf
Binary files differ
diff --git a/macros/latex/contrib/hyperref/doc/hyperref-doc.tex b/macros/latex/contrib/hyperref/doc/hyperref-doc.tex
index ce9a213c8c..f4b06157c3 100644
--- a/macros/latex/contrib/hyperref/doc/hyperref-doc.tex
+++ b/macros/latex/contrib/hyperref/doc/hyperref-doc.tex
@@ -166,7 +166,7 @@
}
\makeatother
\title{Hypertext marks in \hologo{LaTeX}: a manual for \xpackage{hyperref}}
-\date{2021-06-05 v7.00l}
+\date{2021-06-07 v7.00m}
\begin{document}
diff --git a/macros/latex/contrib/hyperref/doc/hyperref.pdf b/macros/latex/contrib/hyperref/doc/hyperref.pdf
index 509003fa47..cf3b9eab1f 100644
--- a/macros/latex/contrib/hyperref/doc/hyperref.pdf
+++ b/macros/latex/contrib/hyperref/doc/hyperref.pdf
Binary files differ
diff --git a/macros/latex/contrib/hyperref/doc/nameref.pdf b/macros/latex/contrib/hyperref/doc/nameref.pdf
index 31cafb8c57..40e6cc259a 100644
--- a/macros/latex/contrib/hyperref/doc/nameref.pdf
+++ b/macros/latex/contrib/hyperref/doc/nameref.pdf
Binary files differ
diff --git a/macros/latex/contrib/hyperref/hluatex.dtx b/macros/latex/contrib/hyperref/hluatex.dtx
index e16c9e1d8e..bbceb38076 100644
--- a/macros/latex/contrib/hyperref/hluatex.dtx
+++ b/macros/latex/contrib/hyperref/hluatex.dtx
@@ -1,6 +1,6 @@
% \iffalse
% Source File: hluatex.dtx
-% 2021-06-05 v7.00l
+% 2021-06-07 v7.00m
%
% Copyright
% 2016-2019 Oberdiek Package Support Group
@@ -31,7 +31,7 @@
%
% \begin{macrocode}
%<*luatex>
-%% 2021-06-05 v7.00l
+%% 2021-06-07 v7.00m
%% force unicode encoding, see issue #101
%% code mostly copied from hxetex.def
\HyPsd@LoadUnicode
diff --git a/macros/latex/contrib/hyperref/hyperref.dtx b/macros/latex/contrib/hyperref/hyperref.dtx
index f07e832470..0a573a038b 100644
--- a/macros/latex/contrib/hyperref/hyperref.dtx
+++ b/macros/latex/contrib/hyperref/hyperref.dtx
@@ -53,7 +53,7 @@
%<puarenc>\ProvidesFile{puarenc.def}
%<psdextra>\ProvidesFile{psdextra.def}
%<lang>\ProvidesFile{hyperref-langpatches.def}
-%<!none> [2021-06-05 v7.00l %
+%<!none> [2021-06-07 v7.00m %
%<package> Hypertext links for LaTeX]
%<nohyperref> Dummy hyperref (SR)]
%<driver> Hyperref documentation driver file]
@@ -7745,7 +7745,7 @@
\def\Hy@babelnormalise#1[#2]{%
\begingroup
\Hy@safe@activestrue
- \let\protect\@unexpandableprotect
+ \let\protect\@unexpandable@protect
\edef\Hy@tempa{%
\endgroup
\noexpand#1[{#2}]%
@@ -12980,7 +12980,7 @@
\def\HyRef@StarSetRef#1{%
\begingroup
\Hy@safe@activestrue
- \let\protect\@unexpandableprotect
+ \let\protect\@unexpandable@protect
\edef\x{#1}%
\@onelevel@sanitize\x
\edef\x{\endgroup
diff --git a/macros/latex/contrib/hyperref/xr-hyper.sty b/macros/latex/contrib/hyperref/xr-hyper.sty
index 25b2c24f83..525fb0330d 100644
--- a/macros/latex/contrib/hyperref/xr-hyper.sty
+++ b/macros/latex/contrib/hyperref/xr-hyper.sty
@@ -61,7 +61,7 @@
%%
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{xr-hyper}
- [2021-06-05 v7.00l eXternal References (DPC)]
+ [2021-06-07 v7.00m eXternal References (DPC)]
\def\externaldocument{\@testopt\XR@cite{}}
\let\externalcitedocument\externaldocument
diff --git a/macros/latex/contrib/mathcommand/README.md b/macros/latex/contrib/mathcommand/README.md
index ee2f7779ca..aba303a9d4 100644
--- a/macros/latex/contrib/mathcommand/README.md
+++ b/macros/latex/contrib/mathcommand/README.md
@@ -1,13 +1,36 @@
+ mathcommand.dtx
+
+ Copyright (C) 2019-2021 by Thomas Colcombet
+
+ This work may be distributed and/or modified under the
+ conditions of the LaTeX Project Public License, either version 1.3
+ 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.
+
+ This work has the LPPL maintenance status ‘maintained’.
+
+ The Current Maintainer of this work is Thomas Colcombet.
+
+ This work consists of the files
+ mathcommand.dtx, mathcommand.ins, and makefile,
+ and the derived files
+ mathcommand.sty and readme.md.
+
%%%%%%%%
This directory contains the package
name: mathcommand
- license: LaTeX Project Public License version 1.2 or above
- version: v1.03
- date: 2019/12/06
+ license: LaTeX Project Public License version 1.3 or above
+ version: v1.04
+ date: 2021/06/07
author: Thomas Colcombet
mail: thomas.colcombet@irif.fr
- web: -
+ web: https://www.ctan.org/pkg/mathcommand
Purpose:
The mathcommand package provides functionalities for defining macros:
@@ -24,11 +47,11 @@ Install:
Content of the file mathcommand-ctan.zip:
- README.md: this file generated while compiling mathcommand.ins,
- - mathcommand.sty: the package file (generated using knowledge.ins)
+ - mathcommand.sty: the package file (generated using mathcommand.ins)
- mathcommand.pdf: the user documentation (generated by compiling
mathcommand.dtx)
- makefile: the makefile. Use 'make all' to generate mathcommand.sty
- and knowledge.pdf. It can also: clean the directory, make zip
+ and mathcommand.pdf. It can also: clean the directory, make zip
version of the sources, or ready for CTAN.
- mathcommand.ins: is the file generating mathcommand.sty and
README.md from mathcommand.dtx (using docstrip).
diff --git a/macros/latex/contrib/mathcommand/mathcommand.dtx b/macros/latex/contrib/mathcommand/mathcommand.dtx
index e269646e1f..7b2bb48485 100644
--- a/macros/latex/contrib/mathcommand/mathcommand.dtx
+++ b/macros/latex/contrib/mathcommand/mathcommand.dtx
@@ -4,26 +4,34 @@
%
%
%
-% meta-comment
-%
-% Copyright (C) 2019-2019 by Thomas Colcombet
-% -----------------------------------
-%
-% This file may be distributed and/or modified under the
-% conditions of the LaTeX Project Public License, either version 1.2
-% 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.2 or later is part of all distributions of LaTeX
-% version 1999/12/01 or later.
-%
+%% mathcommand.dtx
+%%
+%% Copyright (C) 2019-2021 by Thomas Colcombet
+%%
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3
+%% 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.
+%%
+%% This work has the LPPL maintenance status ‘maintained’.
+%%
+%% The Current Maintainer of this work is Thomas Colcombet.
+%%
+%% This work consists of the files
+%% mathcommand.dtx, mathcommand.ins, and makefile,
+%% and the derived files
+%% mathcommand.sty and readme.md.
+%%
% \fi
%
% \iffalse
%<head>\usepackage{expl3}
-%<head>\ProvidesExplPackage{mathcommand}{2019/12/06}{1.03}{}
+%<head>\ProvidesExplPackage{mathcommand}{2021/06/07}{1.04}{}
%<*driver>
\documentclass{ltxdoc}
\usepackage[utf8]{inputenc}
@@ -40,6 +48,7 @@
\changes{1.01}{2019/05/12}{Initial version} %
\changes{1.02}{2019/07/03}{Bug correction} %
\changes{1.03}{2019/12/06}{added disabling commands} %
+\changes{1.04}{2021/06/05}{correction with respect to modification of xparse package} %
\GetFileInfo{mathcommand.sty} %
\DoNotIndex{}
\edef\mathcommandversiondate{\fileversion--\filedate}
@@ -160,6 +169,7 @@
\knowledge{knowledge}{package,url = {https://www.ctan.org/pkg/knowledge}}
\knowledge{xcolor}{package,url = {https://www.ctan.org/pkg/xcolor}}
\knowledge{amsfonts}{package,url = {https://www.ctan.org/pkg/amsfonts}}
+\knowledge{amssymb}{package,url = {https://www.ctan.org/pkg/amssymb}}
\knowledge{mathcommand}{package}
\knowledge{math variant}{doc notion}
@@ -204,6 +214,7 @@
\item[2019-05-14] New macros \cs\IfEmptyTF, \cs\GetExponent, and \cs\GetIndex.
\item[2019-07-03] Corrects bug of functions declaring PIE's issuing an error when already existing. Version 1.02 on CTAN.
\item[2019-12-06] Added disabling commands, and package options. Version 1.03 on CTAN.
+\item[2021-06-07] Corrected code that was broken due to an update in "xparse". Version 1.04 on CTAN.
\end{compactdesc}
@@ -230,10 +241,9 @@
\end{center}
If the macro \cs{\macro} already exists, it is stored
- under the name \cs{\LaTeXmacro}, and then everything's happen as
+ under the name \cs{\LaTeXmacro}, and then everything happens as
if it had already been defined both in math and text mode.
-
- This is interesting for redefining known macros.
+ This is useful for redefining known macros.
For instance \cs{\c} is a convenient way to producing cedillas in \LaTeX, as in \smallcode{\cs\c\ a}
which yields `\c a'. However, one may want \cs{\c} to reprensent a variable $c$ in math mode.
This is done using, e.g.:
@@ -414,7 +424,7 @@ defined with as main body \texttt{\cs\overline\{u\#2\}\#1\#3}
Hence, for instance:
\begin{code}[10cm]
\cs\LoopCommands\cs\lettersUppercase[bb\#1]\\
- \indent~~~~~~\{\cs\newmathcommand\{\cs\mathbb \#1\}\}\\
+ \indent~~~~~~\{\cs\newmathcommand\#2\{\cs\mathbb \#1\}\}\\
\cs\LoopCommands\cs\lettersGreekLowercase[\#1][LaTeX\#1]\\
\indent~~~~~~\{\cs\renewmathcommand\#2\{\cs\textcolor\{blue\}\{\#3\}\}
\end{code}
@@ -422,7 +432,7 @@ defined with as main body \texttt{\cs\overline\{u\#2\}\#1\#3}
the letters in blackboard bold alphabet (e.g. with the "amsfonts" package),
and the lowercase greek letters \cs\alpha,\dots\ to
be displayed in blue (with the "xcolor" package loaded). Note in the last case
- the use of the third parameter used for accessing the macros \cs\LaTeXalpha,\dots\
+ the use of the third parameter for accessing the macros \cs\LaTeXalpha,\dots\
that are automatically generated by the \cs\renewmathcommand\ macro.
\section{Disabling command}
@@ -439,7 +449,7 @@ The result of this command is that the control sequences appearing in the sequen
\item The original macro is stored as \cs\LaTeXmacro, and thus can still be used.
\item Using \cs\macro\ now displays an error message explaining that it has been disabled, that~\cs\LaTeXmacro\ can be used instead, and also provides a list suggestions of replacement that are defined by the command \cs\suggestcommand.
\end{itemize}
-However, be careful: disabling a command which is used in the system or in the the style will yield an error.
+However, be careful: disabling a command which is used in the system or in the the style may cause problems.
Hence, it is possible to disable all math symbols but macros like \cs\dagger\ would yield problem if used in footnotes or for the affiliation of the authors.
\AP The syntax of~\cs\suggestcommand\ is as follows:
\begin{center}
@@ -462,7 +472,7 @@ Now, executing \cs\leq\ yields:
\section{Options}
-\AP Options can either be triggered either when the package is loaded, or using:
+\AP Options can be triggered either when the package is loaded, or using:
\begin{center}
\csintro\mathcommandconfigure\{option list\}
\end{center}
@@ -495,12 +505,12 @@ The available options are:
This directory contains the package
name: mathcommand
- license: LaTeX Project Public License version 1.2 or above
- version: v1.03
- date: 2019/12/06
+ license: LaTeX Project Public License version 1.3 or above
+ version: v1.04
+ date: 2021/06/07
author: Thomas Colcombet
mail: thomas.colcombet@irif.fr
- web: -
+ web: https://www.ctan.org/pkg/mathcommand
Purpose:
The mathcommand package provides functionalities for defining macros:
@@ -517,11 +527,11 @@ Install:
Content of the file mathcommand-ctan.zip:
- README.md: this file generated while compiling mathcommand.ins,
- - mathcommand.sty: the package file (generated using knowledge.ins)
+ - mathcommand.sty: the package file (generated using mathcommand.ins)
- mathcommand.pdf: the user documentation (generated by compiling
mathcommand.dtx)
- makefile: the makefile. Use 'make all' to generate mathcommand.sty
- and knowledge.pdf. It can also: clean the directory, make zip
+ and mathcommand.pdf. It can also: clean the directory, make zip
version of the sources, or ready for CTAN.
- mathcommand.ins: is the file generating mathcommand.sty and
README.md from mathcommand.dtx (using docstrip).
@@ -676,7 +686,7 @@ Content of the file mathcommand-ctan.zip:
%
% \begin{macrocode}
\NewDocumentCommand\newcommandPIE{ m o o m }{
- \__xparse_check_definable:nNT {#1} \newcommandPIE
+ \__mathcommand_check_definable:nNT {#1} \newcommandPIE
{
\cs_if_exist:NTF #1
{
@@ -688,7 +698,7 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\renewcommandPIE{ m o o m }{
- \__xparse_check_definable:nNT {#1} \renewcommandPIE
+ \__mathcommand_check_definable:nNT {#1} \renewcommandPIE
{
\cs_if_exist:NTF #1
{ \__mathcommand_declarecommandPIE:Nnnn #1{#2}{#3}{#4} }
@@ -700,7 +710,7 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\declarecommandPIE{ m o o m }{
- \__xparse_check_definable:nNT {#1} \declarecommandPIE
+ \__mathcommand_check_definable:nNT {#1} \declarecommandPIE
{ \__mathcommand_declarecommandPIE:Nnnn #1{#2}{#3}{#4} }
}
% \end{macrocode}
@@ -721,7 +731,7 @@ Content of the file mathcommand-ctan.zip:
% \end{macrocode}
% \begin{macrocode}
\cs_new_protected:Npn\NewDocumentCommandPIE#1#2#3{
- \__xparse_check_definable:nNT {#1} \NewDocumentCommandPIE
+ \__mathcommand_check_definable:nNT {#1} \NewDocumentCommandPIE
{
\cs_if_exist:NTF #1
{
@@ -735,12 +745,12 @@ Content of the file mathcommand-ctan.zip:
% \end{macrocode}
% \begin{macrocode}
\cs_new_protected:Npn\RenewDocumentCommandPIE#1#2#3{
- \__xparse_check_definable:nNT {#1} \RenewDocumentCommandPIE
+ \__mathcommand_check_definable:nNT {#1} \RenewDocumentCommandPIE
{
\cs_if_exist:NTF #1
{ \__mathcommand_DeclareDocumentCommandPIE:Nnn #1 {#2} {#3} }
{
- \__kernel_msg_error:nnxx { xparse } { command-not-yet-defined }
+ \__kernel_msg_error:nnxx { mathcommand } { command-not-yet-defined }
{ \use:nnn \token_to_str:N #1 { } }
{ \token_to_str:N \RenewDocumentCommandPIE }
}
@@ -749,7 +759,7 @@ Content of the file mathcommand-ctan.zip:
% \end{macrocode}
% \begin{macrocode}
\cs_new_protected:Npn\DeclareDocumentCommandPIE#1#2#3{
- \__xparse_check_definable:nNT {#1} \DeclareDocumentCommandPIE
+ \__mathcommand_check_definable:nNT {#1} \DeclareDocumentCommandPIE
{
\__mathcommand_DeclareDocumentCommandPIE:Nnn #1 {#2} {#3}
}
@@ -757,7 +767,7 @@ Content of the file mathcommand-ctan.zip:
% \end{macrocode}
% \begin{macrocode}
\cs_new_protected:Npn\ProvideDocumentCommandPIE#1#2#3{
- \__xparse_check_definable:nNT {#1} \ProvideDocumentCommandPIE
+ \__mathcommand_check_definable:nNT {#1} \ProvideDocumentCommandPIE
{
\cs_if_exist:NTF #1{}
{
@@ -970,7 +980,7 @@ Content of the file mathcommand-ctan.zip:
% \subsection{Definition of the high level commands}
% \begin{macrocode}
\NewDocumentCommand\declarecommand{m}{
- \__xparse_check_definable:nNT {#1} \declarecommand
+ \__mathcommand_check_definable:nNT {#1} \declarecommand
{
\cs_if_exist:NTF#1
{\renewcommand#1}
@@ -978,7 +988,7 @@ Content of the file mathcommand-ctan.zip:
}
}
\newrobustcmd\storecommand[2][\__mathcommand_prefix_store_tl]{
- \__xparse_check_definable:nNT {#2} \storecommand
+ \__mathcommand_check_definable:nNT {#2} \storecommand
{
\cs_if_exist:NTF#2{
\cs_set_eq:cN{#1\cs_to_str:N#2}#2
@@ -992,7 +1002,7 @@ Content of the file mathcommand-ctan.zip:
}
\NewDocumentCommand\NewDocumentMathCommand{m}{
- \__xparse_check_definable:nNT {#1} \NewDocumentMathCommand
+ \__mathcommand_check_definable:nNT {#1} \NewDocumentMathCommand
{
\__mathcommand_create_fork:N#1
\__mathcommand_error_if_exist_math:NF#1
@@ -1000,7 +1010,7 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\NewDocumentTextCommand{m}{
- \__xparse_check_definable:nNT {#1} \NewDocumentTextCommand
+ \__mathcommand_check_definable:nNT {#1} \NewDocumentTextCommand
{
\__mathcommand_create_fork:N#1
\__mathcommand_error_if_exist_text:NF#1
@@ -1008,7 +1018,7 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\newmathcommand{m}{
- \__xparse_check_definable:nNT {#1} \newmathcommand
+ \__mathcommand_check_definable:nNT {#1} \newmathcommand
{
\__mathcommand_create_fork:N#1
\__mathcommand_error_if_exist_math:NF#1
@@ -1016,7 +1026,7 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\newtextcommand{m}{
- \__xparse_check_definable:nNT {#1} \newtextcommand
+ \__mathcommand_check_definable:nNT {#1} \newtextcommand
{
\__mathcommand_create_fork:N#1
\__mathcommand_error_if_exist_text:NF#1
@@ -1024,7 +1034,7 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\RenewDocumentMathCommand{m}{
- \__xparse_check_definable:nNT {#1} \RenewDocumentMathCommand
+ \__mathcommand_check_definable:nNT {#1} \RenewDocumentMathCommand
{
\__mathcommand_create_fork:N#1
\__mathcommand_error_if_not_exist_math:NF#1
@@ -1032,7 +1042,7 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\RenewDocumentTextCommand{m}{
- \__xparse_check_definable:nNT {#1} \RenewDocumentMathCommand
+ \__mathcommand_check_definable:nNT {#1} \RenewDocumentMathCommand
{
\__mathcommand_create_fork:N#1
\__mathcommand_error_if_not_exist_text:NF#1
@@ -1040,7 +1050,7 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\renewmathcommand{m}{
- \__xparse_check_definable:nNT {#1} \renewmathcommand
+ \__mathcommand_check_definable:nNT {#1} \renewmathcommand
{
\__mathcommand_create_fork:N#1
\__mathcommand_error_if_not_exist_math:NF#1
@@ -1048,7 +1058,7 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\renewtextcommand{m}{
- \__xparse_check_definable:nNT {#1} \renewtextcommand
+ \__mathcommand_check_definable:nNT {#1} \renewtextcommand
{
\__mathcommand_create_fork:N#1
\__mathcommand_error_if_not_exist_text:NF#1
@@ -1056,14 +1066,14 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\declaremathcommand{m}{
- \__xparse_check_definable:nNT {#1} \renewmathcommand
+ \__mathcommand_check_definable:nNT {#1} \renewmathcommand
{
\__mathcommand_create_fork:N#1
\exp_args:Nc\declarecommand{\__mathcommand_to_mathtl:N#1}
}
}
\NewDocumentCommand\declaretextcommand{m}{
- \__xparse_check_definable:nNT {#1} \renewtextcommand
+ \__mathcommand_check_definable:nNT {#1} \renewtextcommand
{
\__mathcommand_create_fork:N#1
\exp_args:Nc\declarecommand{\__mathcommand_to_texttl:N#1}
@@ -1071,28 +1081,28 @@ Content of the file mathcommand-ctan.zip:
}
\NewDocumentCommand\DeclareDocumentMathCommand{m}{
- \__xparse_check_definable:nNT {#1} \DeclareDocumentMathCommand
+ \__mathcommand_check_definable:nNT {#1} \DeclareDocumentMathCommand
{
\__mathcommand_create_fork:N#1
\exp_args:Nc\DeclareDocumentCommand{\__mathcommand_to_mathtl:N#1}
}
}
\NewDocumentCommand\DeclareDocumentTextCommand{m}{
- \__xparse_check_definable:nNT {#1} \DeclareDocumentTextCommand
+ \__mathcommand_check_definable:nNT {#1} \DeclareDocumentTextCommand
{
\__mathcommand_create_fork:N#1
\exp_args:Nc\DeclareDocumentCommand{\__mathcommand_to_texttl:N#1}
}
}
\NewDocumentCommand\ProvideDocumentMathCommand{mmm}{
- \__xparse_check_definable:nNT {#1} \ProvideDocumentMathCommand
+ \__mathcommand_check_definable:nNT {#1} \ProvideDocumentMathCommand
{
\__mathcommand_create_fork:N#1
\exp_args:Nc\ProvideDocumentCommand{\__mathcommand_to_mathtl:N#1}{#2}{#3}
}
}
\NewDocumentCommand\ProvideDocumentTextCommand{m}{
- \__xparse_check_definable:nNT {#1} \ProvideDocumentTextCommand
+ \__mathcommand_check_definable:nNT {#1} \ProvideDocumentTextCommand
{
\__mathcommand_create_fork:N#1
\exp_args:Nc\ProvideDocumentCommand{\__mathcommand_to_texttl:N#1}
@@ -1104,7 +1114,7 @@ Content of the file mathcommand-ctan.zip:
%
% \begin{macrocode}
\NewDocumentCommand\NewDocumentMathCommandPIE{m}{
- \__xparse_check_definable:nNT {#1} \NewDocumentMathCommandPIE
+ \__mathcommand_check_definable:nNT {#1} \NewDocumentMathCommandPIE
{
\__mathcommand_create_fork:N#1
\__mathcommand_error_if_exist_math:NF#1
@@ -1112,7 +1122,7 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\newmathcommandPIE{m}{
- \__xparse_check_definable:nNT {#1} \newmathcommandPiE
+ \__mathcommand_check_definable:nNT {#1} \newmathcommandPiE
{
\__mathcommand_create_fork:N#1
\__mathcommand_error_if_exist_math:NF#1
@@ -1120,7 +1130,7 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\RenewDocumentMathCommandPIE{m}{
- \__xparse_check_definable:nNT {#1} \RenewDocumentMathCommandPIE
+ \__mathcommand_check_definable:nNT {#1} \RenewDocumentMathCommandPIE
{
\__mathcommand_create_fork:N#1
\__mathcommand_error_if_not_exist_math:NF#1
@@ -1128,7 +1138,7 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\renewmathcommandPIE{m}{
- \__xparse_check_definable:nNT {#1} \renewmathcommandPIE
+ \__mathcommand_check_definable:nNT {#1} \renewmathcommandPIE
{
\__mathcommand_create_fork:N#1
\__mathcommand_error_if_not_exist_math:NF#1
@@ -1136,14 +1146,14 @@ Content of the file mathcommand-ctan.zip:
}
}
\NewDocumentCommand\DeclareDocumentMathCommandPIE{m}{
- \__xparse_check_definable:nNT {#1} \DeclareDocumentMathCommand
+ \__mathcommand_check_definable:nNT {#1} \DeclareDocumentMathCommand
{
\__mathcommand_create_fork:N#1
\exp_args:Nc\DeclareDocumentCommand{\__mathcommand_to_mathtl:N#1}
}
}
\NewDocumentCommand\declaremathcommandPIE{m}{
- \__xparse_check_definable:nNT {#1} \declaremathcommandPIE
+ \__mathcommand_check_definable:nNT {#1} \declaremathcommandPIE
{
\__mathcommand_create_fork:N#1
\exp_args:Nc\declarecommandPIE{\__mathcommand_to_mathtl:N#1}
@@ -1151,7 +1161,7 @@ Content of the file mathcommand-ctan.zip:
}
\NewDocumentCommand\ProvideDocumentMathCommandPIE{mmm}{
- \__xparse_check_definable:nNT {#1} \ProvideDocumentMathCommandPIE
+ \__mathcommand_check_definable:nNT {#1} \ProvideDocumentMathCommandPIE
{
\__mathcommand_create_fork:N#1
\exp_args:Nc\ProvideDocumentCommandPIE{\__mathcommand_to_mathtl:N#1}{#2}{#3}
@@ -1265,7 +1275,7 @@ Content of the file mathcommand-ctan.zip:
\cs_new:Nn\mathcommand_disablecommand:N
{ \cs_if_exist:NTF#1{
- \__xparse_check_definable:nNT#1\disablecommand
+ \__mathcommand_check_definable:nNT#1\disablecommand
{\tl_if_exist:cTF{\__mathcommand_to_disabled_help_tl:N#1}
{}
{\storecommand#1
@@ -1312,6 +1322,44 @@ Content of the file mathcommand-ctan.zip:
\NewDocumentCommand\mathcommandconfigure{ m }
{\keys_set:nn{ mathcommand}{ #1} }
% \end{macrocode}
+%
+% \subsection{Testing control sequence for definition}
+% This part of the code is an import of a previous version of xparse (Frank Mittelbach, Chris Rowley, David Carlisle, The LaTeX Project). It is done in a very ugly hack: the code is copied and past, and \texttt{mathcommand} substituted to \texttt{xparse} wherever necessary.
+% \begin{macrocode}
+\cs_new_protected:Npn \__mathcommand_check_definable:nNT #1
+ { \tl_trim_spaces_apply:nN {#1} \__mathcommand_check_definable_aux:nN }
+\group_begin:
+ \char_set_catcode_active:n { `? }
+ \cs_new_protected:Npn \__mathcommand_check_definable_aux:nN #1#2
+ {
+ \group_begin:
+ \tl_if_single_token:nTF {#1}
+ {
+ \int_set:Nn \tex_escapechar:D { 92 }
+ \exp_args:Nx \tl_if_empty:nTF
+ { \exp_args:No \str_tail:n { \token_to_str:N #1 } }
+ {
+ \exp_args:Nx \char_set_lccode:nn
+ { ` \str_head:n {#1} } { `? }
+ \tex_lowercase:D { \tl_if_eq:nnTF {#1} } { ? }
+ { \group_end: \use_iii:nnn }
+ { \group_end: \use_i:nnn }
+ }
+ { \group_end: \use_iii:nnn }
+ }
+ { \group_end: \use_ii:nnn }
+ {
+ \__kernel_msg_error:nnxx { mathcommand } { not-definable }
+ { \tl_to_str:n {#1} } { \token_to_str:N #2 }
+ }
+ {
+ \__kernel_msg_error:nnxx { mathcommand } { not-one-token }
+ { \tl_to_str:n {#1} } { \token_to_str:N #2 }
+ }
+ }
+\group_end:
+% \end{macrocode}
+% \subsection{Closure}
% \begin{macrocode}
\ExplSyntaxOff
% \end{macrocode}
diff --git a/macros/latex/contrib/mathcommand/mathcommand.ins b/macros/latex/contrib/mathcommand/mathcommand.ins
index b8104498c5..ac79f74974 100644
--- a/macros/latex/contrib/mathcommand/mathcommand.ins
+++ b/macros/latex/contrib/mathcommand/mathcommand.ins
@@ -1,33 +1,52 @@
+%% mathcommand.ins
%%
-%% Copyright (C) 2017 by Thomas Colcombet
+%% Copyright (C) 2019-2021 by Thomas Colcombet
%%
-%% This file may be distributed and/or modified under the
-%% conditions of the LaTeX Project Public License, either
-%% version 1.2 of this license or (at your option) any later
-%% version. The latest version of this license is in:
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either version 1.3
+%% 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
+%% 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.
+%%
+%% This work has the LPPL maintenance status ‘maintained’.
+%%
+%% The Current Maintainer of this work is Thomas Colcombet.
%%
-%% and version 1.2 or later is part of all distributions of
-%% LaTeX version 1999/12/01 or later.
+%% This work consists of the files
+%% mathcommand.dtx, mathcommand.ins, and makefile,
+%% and the derived files
+%% mathcommand.sty and readme.md.
%%
\input docstrip.tex
\keepsilent
\askforoverwritefalse
\preamble
+ This is a generated file.
+
+ Copyright (C) 2019-2021 by Thomas Colcombet
+
+ This work may be distributed and/or modified under the
+ conditions of the LaTeX Project Public License, either version 1.3
+ 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
-This is a generated file. Copyright (C) 2019 by Thomas Colcombet
+ and version 1.3 or later is part of all distributions of LaTeX
+ version 2005/12/01 or later.
-This file may be distributed and/or modified under the
-conditions of the LaTeX Project Public License, either
-version 1.2 of this license or (at your option) any later
-version. The latest version of this license is in:
+ This work has the LPPL maintenance status ‘maintained’.
- http://www.latex-project.org/lppl.txt
+ The Current Maintainer of this work is Thomas Colcombet.
-and version 1.2 or later is part of all distributions of
-LaTeX version 1999/12/01 or later.
+ This work consists of the files
+ mathcommand.dtx, mathcommand.ins, and makefile,
+ and the derived files
+ mathcommand.sty and readme.md.
\endpreamble
@@ -57,10 +76,11 @@ LaTeX version 1999/12/01 or later.
\Msg{* To finish the installation you have to move the }
\Msg{* following file into a directory searched by TeX:}
\Msg{*}
-\Msg{* knowledge.sty}
+\Msg{* mathcommand.sty }
\Msg{*}
-\Msg{* To produce the documentation run the file *}
-\Msg{* knowledge.dtx through LaTeX.}
+\Msg{* To produce the documentation run the file}
+\Msg{* mathcommand.dtx through LaTeX. or use}
+\Msg{* the makefile }
\Msg{*}
\Msg{****************************************************}
diff --git a/macros/latex/contrib/mathcommand/mathcommand.pdf b/macros/latex/contrib/mathcommand/mathcommand.pdf
index 8e836ed0e4..b1716e32ed 100644
--- a/macros/latex/contrib/mathcommand/mathcommand.pdf
+++ b/macros/latex/contrib/mathcommand/mathcommand.pdf
Binary files differ
diff --git a/macros/latex/contrib/minimalist/minimalist-doc.pdf b/macros/latex/contrib/minimalist/minimalist-doc.pdf
index 969688dff0..8835eef229 100644
--- a/macros/latex/contrib/minimalist/minimalist-doc.pdf
+++ b/macros/latex/contrib/minimalist/minimalist-doc.pdf
Binary files differ
diff --git a/macros/latex/contrib/minimalist/minimalist-doc.tex b/macros/latex/contrib/minimalist/minimalist-doc.tex
index 1ba08ae37f..0d1fc5d29f 100644
--- a/macros/latex/contrib/minimalist/minimalist-doc.tex
+++ b/macros/latex/contrib/minimalist/minimalist-doc.tex
@@ -85,7 +85,7 @@
\title{\minimalist{}, write your articles or books in a simple and clear way}
\author{Jinwen XU}
-\thanks{Corresponding to: \texttt{\minimalist{} 2021/06/07}}
+\thanks{Corresponding to: \texttt{\minimalist{} 2021/06/07a}}
\date{June 2021, Beijing}
\maketitle
diff --git a/macros/latex/contrib/minimalist/minimalist.sty b/macros/latex/contrib/minimalist/minimalist.sty
index 11d2e62035..fdea2527fb 100644
--- a/macros/latex/contrib/minimalist/minimalist.sty
+++ b/macros/latex/contrib/minimalist/minimalist.sty
@@ -17,7 +17,7 @@
%%
\NeedsTeXFormat{LaTeX2e}[2020-10-01]
\ProvidesPackage{minimalist}
- [2021/06/07 A simple and clear style for articles and books]
+ [2021/06/07a A simple and clear style for articles and books]
\RequirePackage{kvoptions}
\RequirePackage{etoolbox}
\SetupKeyvalOptions{%
@@ -370,7 +370,7 @@
%% Subsubsection
\titleformat{\subsubsection}
{\LocallyStopLineNumbers%
- \color{paper!30!-paper}\subsubsecfont}{\thesubsubsection}{1em}
+ \color{paper!30!-paper}\subsubsecfont}{\thesubsubsection}{.6em}
{#1}
[\ResumeLineNumbers]
@@ -408,6 +408,12 @@
{\contentslabel{2.75em}}
{\hspace*{-2.75em}}
{\titlerule*[1em]{\textcolor{gray!30!paper}{.}}\contentspage}
+ \titlecontents{subsubsection}
+ [9em] % i.e., 7em (subsection) + 2em
+ {\normalfont}
+ {\contentslabel{2.75em}}
+ {\hspace*{-2.75em}}
+ {\titlerule*[1em]{\textcolor{gray!30!paper}{.}}\contentspage}
}{
\titlecontents{section}
[2em] % i.e., 0em (part) + 2em
@@ -421,6 +427,12 @@
{\contentslabel{2.75em}}
{\hspace*{-2.75em}}
{\titlerule*[1em]{\textcolor{gray!30!paper}{.}}\contentspage}
+ \titlecontents{subsubsection}
+ [7em] % i.e., 5em (subsection) + 2em
+ {\normalfont}
+ {\contentslabel{2.75em}}
+ {\hspace*{-2.75em}}
+ {\titlerule*[1em]{\textcolor{gray!30!paper}{.}}\contentspage}
}
%%================================
@@ -476,20 +488,26 @@
{\color{gray}\thmnote{\ensuremath{(\text{#3})}~~}}}
\fi
\else
-\def\simpleqed{\hfill\makebox[1em]{\rlap{\textcolor{gray!25!paper}{\rule[-0.1em]{.95em}{.95em}}}{\kern.07em\raisebox{.07em}{\textcolor{paper}{\rule[-0.1em]{.81em}{.81em}}}\kern.07em}}}
+\def\simpleqedsymbol{%
+ \makebox[1em]{\rlap{\textcolor{gray!25!paper}{\rule[-0.1em]{.95em}{.95em}}}{\kern.07em\raisebox{.07em}{\textcolor{paper}{\rule[-0.1em]{.81em}{.81em}}}\kern.07em}}}
\newtheoremstyle{simple}%
{}{}%
{\normalfont}{}%
{\normalfont}{}%
{0pt}%
- {{\conditionalbfseries\thmname{#1}\thmnumber{ #2}}\hspace{.4em}%
+ {\global\let\qedsymbol\simpleqedsymbol%
+ {\conditionalbfseries\thmname{#1}\thmnumber{ #2}}\hspace{.4em}%
\textcolor{gray!55!paper}{$|$}\hspace{.4em}%
- \color{gray}\thmnote{\ensuremath{(\text{#3})}~~}\pushQED{\simpleqed}}
-\def\@endtheorem{\popQED\endtrivlist\@endpefalse }
+ \color{gray}\thmnote{\ensuremath{(\text{#3})}~~}%
+ \pushQED{\qed}%
+ }
+\def\@endtheorem{\popQED\endtrivlist\@endpefalse
+\global\let\qedsymbol\qedsymbolOriginal}
\fi
\renewcommand{\qedsymbol}{%
\makebox[1em]{\color{gray!55!paper}\rule[-0.1em]{.95em}{.95em}}}
+\let\qedsymbolOriginal\qedsymbol
\if@minimalist@fast
\providecommand{\phantomsection}{}
@@ -719,6 +737,7 @@
{\small\scshape\@author}\\[2pt]%
{\small\@date}%
\end{center}%
+ \ifx\@date\@empty\bigskip\fi%
\bigskip\par%
\ResumeLineNumbers%
}
@@ -739,7 +758,7 @@
% \vspace{-\parskip}%
\vspace{-.5\baselineskip}%
\ifx\@date\@empty%
- \vspace{-.2\baselineskip}%
+ \vspace{1.6\baselineskip}%
\else%
\vspace{-.5\baselineskip}%
\fi%
diff --git a/macros/latex/contrib/minimalist/minimart.cls b/macros/latex/contrib/minimalist/minimart.cls
index cf4f084590..e3babb2c3d 100644
--- a/macros/latex/contrib/minimalist/minimart.cls
+++ b/macros/latex/contrib/minimalist/minimart.cls
@@ -17,7 +17,7 @@
%%
\NeedsTeXFormat{LaTeX2e}[2020-10-01]
\ProvidesClass{minimart}
- [2021/06/07 A simple and clear article style]
+ [2021/06/07a A simple and clear article style]
\def\minimclass@baseclass{article}
\RequirePackage{kvoptions}
\RequirePackage{etoolbox}
diff --git a/macros/latex/contrib/minimalist/minimbook.cls b/macros/latex/contrib/minimalist/minimbook.cls
index ec1c656a15..5091782a7d 100644
--- a/macros/latex/contrib/minimalist/minimbook.cls
+++ b/macros/latex/contrib/minimalist/minimbook.cls
@@ -17,7 +17,7 @@
%%
\NeedsTeXFormat{LaTeX2e}[2020-10-01]
\ProvidesClass{minimbook}
- [2021/06/07 A simple and clear book style]
+ [2021/06/07a A simple and clear book style]
\def\minimclass@baseclass{book}
\RequirePackage{kvoptions}
\RequirePackage{etoolbox}
diff --git a/macros/latex/contrib/pmdb/README.md b/macros/latex/contrib/pmdb/README.md
index aa2763ff79..8b791ba171 100644
--- a/macros/latex/contrib/pmdb/README.md
+++ b/macros/latex/contrib/pmdb/README.md
@@ -1,6 +1,6 @@
The pmdb Package
Author: D. P. Story
-Dated: 2019-12-09
+Dated: 2021-06-07
This "poor man's database" (pmdb) package promotes a workflow
for building exams, homework, and other content. The package
@@ -20,6 +20,12 @@ aeb-reader.js needs to be installed. As the filename suggests,
this file will work for Adobe Acrobat Reader (DC), as well as
for the magnificent Adobe Acrobat itself.
+What's New (2021-06-07) New command \editSourceOn, which inserts
+a pushbutton in the margin; pressing the button loads the source
+file in the default editor. Expanding \useEditLnk replaces the
+marginal pushbutton with a link annotation. A new input mode
+\InputProbs, allows inputting problems for a eqexam document.
+
Enjoy!
Now, I must get back to my retirement.
diff --git a/macros/latex/contrib/pmdb/docs/pmdb-man.pdf b/macros/latex/contrib/pmdb/docs/pmdb-man.pdf
index 2405eb3c96..8594cf4644 100644
--- a/macros/latex/contrib/pmdb/docs/pmdb-man.pdf
+++ b/macros/latex/contrib/pmdb/docs/pmdb-man.pdf
Binary files differ
diff --git a/macros/latex/contrib/pmdb/docs/pmdb-man.tex b/macros/latex/contrib/pmdb/docs/pmdb-man.tex
index d9e387e55c..d2a5e950de 100644
--- a/macros/latex/contrib/pmdb/docs/pmdb-man.tex
+++ b/macros/latex/contrib/pmdb/docs/pmdb-man.tex
@@ -15,6 +15,7 @@
\usepackage[dbmode]{pmdb}
%\previewOn\pmpvOn
+\editSourceOn
\pmCBPresets{\textColor{red}}
@@ -83,7 +84,7 @@
email={dpstory@acrotex.net},
subject=Documentation for the pmdb package,
talksite={\url{www.acrotex.net}},
- version={0.4, 2019/12/09},
+ version={1.0, 2021/06/07},
Keywords={DB, LaTeX, AcroTeX},
copyrightStatus=True,
copyrightNotice={Copyright (C) \the\year, D. P. Story},
@@ -190,10 +191,10 @@ this package, a list of all \emph{selected} \cs{input} statements is
displayed in the JavaScript console. This list can then be copied and pasted
into another document the author is developing. If you
\uif{Ctrl+Click}\FmtMP{\uif{Ctrl+Click}} on a checkbox, the associated
-content is opened in the default TEX editor. For this workflow, the document
+content is opened in the default browser. For this workflow, the document
author can see a typeset of the content and decide whether the content should
-be included in the developing document, and can optionally, view the source
-file to edit it.
+be included in the developing document, and can optionally view the source
+file to edit it by clicking on the button or link to the right of the checkbox.
\section{Requirements and options}
@@ -212,7 +213,12 @@ procedure of folder JavaScript files is described in the file
\texttt{docs/install\_jsfiles.pdf}. The folder JS file \texttt{\fnJS} (or
\texttt{aeb\_pro.js}) enables the `\uif{Ctrl+Click}' to be operational for
both \app{Adobe Acrobat} (\app{AA}) and \app{Adobe Acrobat Reader}
-(\app{AR})\FmtMP{\app{AA} and \app{AR}}.
+(\app{AR})\FmtMP{\app{AA} and \app{AR}}. However, when the command
+\cs{editSourceOn}\FmtMP{\cs{editSourceOn}} is expanded, a pushbutton appears
+to the right of the checkbox; click on this pushbutton opens the content in
+the default editor. The use of the button generated by \cs{editSourceOn} requires
+neither \texttt{aeb-reader.js} nor \texttt{aeb\_pro.js}.
+
\paragraph*{Options.} There are four options: \opt{dbmode} and \opt{!dbmode}\FmtMP{\opt{dbmode}\\\relax\opt{!dbmode}},
and \opt{tight} and
@@ -228,7 +234,7 @@ checkboxes. The default location of the checkboxes are flush left. The
Refer to the \textbf{\nameref{para:CB}} paragraph for more information.
\paragraph*{Requirements.} The \pkg{eforms} package is required for the creation of
-checkboxes and push buttons.
+checkboxes and push\-buttons.
\section{The DB stage}
@@ -239,7 +245,7 @@ use the checkboxes in the margin to select content you want to include in
another document; you can use the \uif{Ctrl+Click} feature to view the source
file of that content as well.
-\newtopic
+\newtopic\noindent
The following comments are apropos to the creation of a DB document:
\begin{itemize}
\item\textbf{PDF creators:} Any PDF creator current in the {\LaTeX} world
@@ -248,8 +254,8 @@ is valid for use with this package.
\item\textbf{PDF viewers:} The ideal viewer is \app{AA}; however, \app{AR}
and \app{PDF-XChange Editor} can also be used. In the case of
\app{Adobe Reader}, there is an annoying security dialog box that
- appears each time you use the \uif{Ctrl+Click} feature of the check
- box;\footnote{This assumes the file \texttt{\fnJS} is properly
+ appears each time you use the \uif{Ctrl+Click} feature of the
+ checkbox;\footnote{This assumes the file \texttt{\fnJS} is properly
installed.} the \uif{Ctrl+Click} feature \emph{does not work} with
\app{PDF-XChange Editor}.
@@ -267,19 +273,22 @@ uses the \pkg{pmdb} package. The document itself uses \cs{pmInput} to input
its content.
\begin{Verbatim}[xleftmargin=\amtIndent,fontsize=\small,commandchars=!()]
\documentclass{article}
-\usepackage[forcolorpaper]{web} % optional
-% !sffamily Additional packages that may be required by any content
-% !sffamily that is !texttt(\pmInput). For example, ...
-\usepackage{exerquiz} % if needed
+\usepackage[forcolorpaper]{web} %!textsf( optional)
+% !sffamily( Additional packages that may be required by any content)
+% !sffamily( that is input with !texttt(\pmInput). For example, ...)
+\usepackage{exerquiz} %!textsf( if needed)
\usepackage[dbmode]{pmdb}
...
+\editSourceOn %(!sffamily!space or, )\editSourceOff
+%\useEditLnk %(!sffamily!space !cs(useEditBtn), the default)
+...
\begin{document}
-% Declares input for quiz items
+% !textsf(Declares input for quiz items)
%\InputQuizItems
-% Declares input paragraph content
+% !textsf(Declares input paragraph content)
%\InputParas
-% Declares input items
+% !textsf(Declares input items)
%\InputItems
\pmInput{!ameta(path!SUB1)}
@@ -294,11 +303,45 @@ its content.
\end{document}
\end{Verbatim}
Descriptions of the various commands \cs{pmInput}, \cs{InputQuizItems},
-\cs{InputParas}, \cs{InputItems}, \cs{displayChocies}, and \cs{clrChoices}
+\cs{InputParas}, \cs{InputItems}, \cs{InputProbs}, \cs{editSourceOn}, \cs{displayChocies}, and \cs{clrChoices}
appear later in this documentation.\medskip
+\begingroup
+
+\InputParas
+
+\pmCBPresets{\Ff\FfReadOnly}
+\editSourceBtn[\TU{View in default editor}\Ff\FfReadOnly\S{S}]{11bp}{11bp}
+
\pmInput{sample-para.tex}
+\endgroup
+
+\paragraph*{Functionality of the boxes in the margin.}
+By default, only one box appears in the margins, a checkbox. If the command
+\cs{editSourceOn} is in effect, a small pushbutton appears to the left of the
+checkbox.
+\begin{description}
+ \item[checkbox:] Selecting the checkbox (a check mark) appears
+ declares that you want that problem (or item) in the document you
+ are creating. \uif{Ctrl+Click} opens the source file for viewing
+ (not editing) in the default browser. A \uif{Shift+Click} action
+ jumps---if \cs{InputQuizItems} is in effect---to the solution
+ of the selected item, if a solution is provided. The
+ \uif{Ctrl+Click} functionality requires the successful installation
+ of the \texttt{aeb-reader.js} or \texttt{aeb\_pro.js} JavaScript
+ file.
+ \item[pushbutton:] If \cs{editSourceOn} has been expanded prior, a
+ little pushbutton appears to the right of the checkbox. Clicking
+ the pushbutton opens the default viewer (for a TEX file) and the
+ source file is loaded into the viewer for possible editing.
+ \item[link annotation:] If \cs{editSourceOn} and \cs{useEditLnk} are
+ expanded, a link annotation having the same functionality as the
+ pushbutton appears in the margins, in place of the pushbutton.
+\end{description}
+The checkbox/pushbutton pair above have been disabled for this documentation.
+Experience the functionality with the example files, listed below.
+
\paragraph*{Sample files.}
The four sample files are found in the \texttt{examples} folder:
\begin{itemize}
@@ -312,8 +355,12 @@ The four sample files are found in the \texttt{examples} folder:
and \cs{InputParas} to input chapters.
\item\texttt{tst-items}: An example that demonstrates the \cs{InputItems}
input mode.
+\item\texttt{tst-eqedb.tex}: An example that demonstrates the \cs{InputProbs}
+ input mode.
\end{itemize}
+
+
\section{The production stage}
After your DB document has been assembled (using \pkg{pmdb}), you are ready
@@ -340,9 +387,9 @@ document, you can compile into a PDF. Done!
\section{Package commands}
The package defines several commands and these are discussed now.
-\bVerb\small\takeMeasure{\string\pmInput[\ameta{arg}]\darg{\ameta{path}}}%
+\bVerb\small\takeMeasure{\string\pmInput*[\ameta{arg}]\darg{\ameta{path}}}%
\begin{dCmd}[fontsize=\small,commandchars=!()]{\bxSize}
-\pmInput[!ameta(arg)]{!ameta(path)}
+\pmInput*[!ameta(arg)]{!ameta(path)}
\end{dCmd}
\eVerb Within a DB source document, content is inserted using \cs{pmInput}. This
command both inputs the referenced \ameta{path} (using the {\LaTeX} command
@@ -354,12 +401,14 @@ path needs to be enclosed in \emph{double quotes} (\texttt"); for example,
latex/aeb/pmdb/examples/chapters/doc2.tex"}
\end{Verbatim}
The optional argument \ameta{arg} is only obeyed when \cs{InputItems} is active and \cs{pmInput} is expanded
-within a list environment.
+within a list environment; \ameta{arg} is passed to the underlying \cs{item} in the list (\cs{item[\ameta{arg}]}). When
+the \texttt* option is taken, the rest of the arguments are gobbled and the command does nothing; this is a convenient
+way of \emph{not inputting} a \ameta{path}.
\paragraph*{Important requirement:} Unlike the normal \cs{input} command\FmtMP{extension required}, we require the file name to include
the extension, `\texttt{.tex}' in the above example.
-\paragraph{Input modes.} There are three `input modes':%\vskip-6pt\par
+\paragraph{Input modes.} There are four `input modes':%\vskip-6pt\par
\bVerb\small\takeMeasure{\string\InputQuizItems}%
\setlength{\eflength}{\widthof{\sffamily(\cs{thQuizName})}}%
\edef\x{\the\eflength}%
@@ -370,6 +419,7 @@ the extension, `\texttt{.tex}' in the above example.
!1\InputParas
\InputQuizItems
\InputItems
+\InputProbs
\end{dCmd}
\eVerb A brief description of each follows.
\begin{description}
@@ -381,6 +431,8 @@ the extension, `\texttt{.tex}' in the above example.
(as created by the \env{quiz} environment).
\item [\cs{InputItems}:] Sets the input mode to input items in a list
environment.
+ \item [\cs{InputProbs}:] Set the input mode to input problems for an exam
+ created by the \pkg{eqexam} package.
\end{description}
In all cases, the {\LaTeX} command \cs{marginpar}\FmtMP{\cs{marginpar} used} is used; as a result, the
checkbox appears in the margins when the \cs{marginpar} command is supported; in
@@ -388,12 +440,21 @@ particular, \cs{marginpar} does not work in a \env{tabular} environment or a
\env{multicols} environment, for example.
\newtopic\noindent
-Below is an example of \cs{InputItems}
+Below is an example of \cs{InputItems}.\footnote{The marginal form fields have been made readonly
+for this documentation.}
+
+\begingroup
+\pmCBPresets{\Ff\FfReadOnly}
+\editSourceBtn[\TU{View in default editor}\Ff\FfReadOnly\S{S}]{11bp}{11bp}
+\editSourceLnk[\cmd{\let\A\noexpand\A}\linktxtcolor{red}
+ \A{\JS{app.alert("The link to source file has been removed for this documentation.");}}]{11bp}{11bp}{E}
+%\previewOn
\begin{itemize}\pmdbtighttrue\InputItems %\normalmarginpar
\pmInput{sample-item.tex}
\item Another item, not input by \cs{pmInput}
+\useEditLnk
\pmInput[*]{sample-item.tex}
\end{itemize}
The verbatim listing is,
@@ -401,6 +462,7 @@ The verbatim listing is,
\begin{itemize}!textbf(\pmdbtighttrue\InputItems)
\pmInput{sample-item.tex}
\item Another item, not input by \verb|\pmInput|.
+!textbf(!string\useEditLnk) %!textsf( Use marginal link for illustrative purposes)
\pmInput[*]{sample-item.tex}
\end{itemize}
\end{Verbatim}
@@ -411,9 +473,10 @@ margin (flush right, in this case). You can (locally) move the checkboxes to
the right margin by expanding \cs{normalmarginpar} within the \env{itemize}
environment group.
+\endgroup
-\paragraph*{Checkboxes.}\label{para:CB} The document produces checkboxes in the margins, you can set
-the appearance of the checkboxes using the \cs{pmCBPresets} command
+\paragraph*{Marginal Checkboxes.}\label{para:CB} The document produces checkboxes in the margins, you can set
+the appearance of the checkboxes using the \cs{pmCBPresets} command.
\bVerb\small\takeMeasure{\string\pmCBPresets\darg{\ameta{opts}}}%
\begin{dCmd}[fontsize=\small,commandchars=!()]{\bxSize}
\pmCBPresets{!ameta(opts)}
@@ -431,7 +494,61 @@ class-type document, the checkboxes alternate between the left and right
margins. The option \opt{tight} can be used to move the checkboxes to the
inner margins of the text block.
-\paragraph*{Push buttons.} The package defines two push buttons that should be utilized
+\paragraph*{Marginal pushbuttons.} When \cs{editSourceOn} is in effect, a pushbutton
+appears to the right of the marginal checkbox. The action of this pushbutton is to open
+the source file in the default editor. Modify the appearance using the \cs{editSourceBtn} command:
+\bVerb\small\takeMeasure{\string\editSourceBtn[\ameta{opts}]\darg{\ameta{wd}}\darg{\ameta{ht}}}%
+\setlength{\eflength}{\bxSize}%
+\def\1{\rlap{\hskip\linewidth\textsf{(required for the button to appear)}}}%
+\def\2{\rlap{\hskip\linewidth\textsf{(the default)}}}%
+\begin{dCmd}[fontsize=\small,commandchars=!()]{\bxSize}
+!1\editSourceOn
+!2\useEditBtn
+\editSourceBtn[!ameta(opts)]{!ameta(wd)}{!ameta(ht)}
+\end{dCmd}
+\eVerb The first line \cs{editSourceOn} is required for the button to appear;
+usually this command is expanded in the preamble, but it can be expanded in
+the body of the document to turn on or off (\cs{editSourceOff}). The second
+line specifies that pushbutton form field should be used (the default). The
+third line is the general syntax; here, \ameta{opts} are key-values that are
+passed to the underlying \cs{pushButton} command of \pkg{eforms}.
+\bVerb\small\takeMeasure{\string\editSourceBtn[\string\TU\darg{View in default editor}\string\S\darg{S}]\darg{11bp}\darg{11bp}}%
+\setlength{\eflength}{\bxSize}%
+\def\2{\rlap{\hskip\linewidth\textsf{(the default)}}}%
+\begin{pCmd*}[fontsize=\small,commandchars=!()]{\bxSize}
+!2\editSourceBtn[\TU{View in default editor}\S{S}]{11bp}{11bp}
+\end{pCmd*}
+The above is the default definition for the marginal link.
+
+
+\paragraph*{Marginal links.} As an alternative to using marginal pushbuttons, \pkg{pmdb} also
+provides link annotations. When \cs{editSourceOn} is expanded\FmtMP{\cs{useEditLnk} and \cs{useEditBtn} discussed}, marginal
+buttons appear in the margin, by default. To obtain link annotations also
+expand the macro \cs{useEditLnk} (\cs{useEditBtn} is the default). Use
+\cs{editSourceLnk} to customized the link:
+\bVerb\small\takeMeasure{\string\editSourceLnk[\ameta{opts}]\darg{\ameta{wd}}\darg{\ameta{ht}}\darg{\ameta{txt}}}%
+\setlength{\eflength}{\bxSize}\def\2{\rlap{\hskip\linewidth\textsf{(the default)}}}%
+\def\1{\rlap{\hskip\linewidth\textsf{(required for the link to appear)}}}%
+\begin{dCmd}[fontsize=\small,commandchars=!()]{\bxSize}
+!1\editSourceOn
+\editSourceLnk
+\editSourceLnk[!ameta(opts)]{!ameta(wd)}{!ameta(ht)}{!ameta(txt)}
+\end{dCmd}
+\eVerb where \ameta{opts} are key-values that are passed to the underlying
+link command \cs{setLink} of \pkg{eforms}. The dimensions provided should be
+the same as those used by the marginal checkboxes so they are properly
+aligned.
+
+\bVerb\small\takeMeasure{\string\editSourceLnk[\string\linktxtcolor\darg{red}\string\H\darg{N}]\darg{11bp}\darg{11bp}\darg{E}}%
+\setlength{\eflength}{\bxSize}%
+\def\2{\rlap{\hskip\linewidth\textsf{(the default)}}}%
+\begin{pCmd*}[fontsize=\small,commandchars=!()]{\bxSize}
+!2\editSourceLnk[\linktxtcolor{red}\H{N}]{11bp}{11bp}{E}
+\end{pCmd*}
+The above is the default definition for the marginal button.
+
+
+\paragraph*{Pushbuttons.} The package defines two push buttons that should be utilized
in your DB document. They can be placed at the end of the document, or in a
running footer.
@@ -440,11 +557,12 @@ running footer.
\displayChoices[!ameta(opts)]{!ameta(wd)}{!ameta(ht)}
\clrChoices[!ameta(opts)]{!ameta(wd)}{!ameta(ht)}
\end{dCmd}
-\eVerb \cs{displayChoices} displays the choices made in the console window of \app{AA/AR}, while
-\cs{clrChoices} clears all the marginal checkboxes. For example,
+\eVerb The \cs{displayChoices} command displays the choices made in the
+console window of \app{AA/\allowbreak AR}, while \cs{clrChoices} clears all
+the marginal checkboxes. For example,
\begin{quote}
\begin{tabular}{@{}ll}
-\displayChoices{}{11bp}&\clrChoices{}{11bp}\\
+\displayChoices{}{11bp}&\clrChoices{}{11bp}\\[3bp]
\footnotesize\cs{displayChoices\darg{}\darg{11bp}}&
\footnotesize\cs{clrChoices\darg{}\darg{11bp}}
\end{tabular}
@@ -456,9 +574,9 @@ convenience commands associate with \cs{displayChoices} and \cs{clrChoices}:
%\edef\x{\the\eflength}%
\setlength{\eflength}{\bxSize}%
\def\1{\rlap{\hskip\eflength\sffamily(Display Choices)}}
-\def\2{\rlap{\hskip\eflength\sffamily(Lists all choices in the console window)}}
+\def\2{\rlap{\hskip\eflength\sffamily(Display all choices in the console window)}}
\def\3{\rlap{\hskip\eflength\sffamily(Clear Choices)}}
-\def\4{\rlap{\hskip\eflength\sffamily(Clears all checkboxes created by pmdb)}}
+\def\4{\rlap{\hskip\eflength\sffamily(Clear all checkboxes created by pmdb)}}
%{Display Choices}
%{Lists all choices in the console window}
%{Clear Choices}
@@ -482,18 +600,20 @@ must accompany the DB document. As long as all references to DB files are
supporting DB files. Just ZIP the whole folder containing the DB document and
all DB files. They can now be moved to another computer system, unzipped, and
total functionality attained. For the \uif{Ctrl+Click} feature to work, the
-\texttt{\fnJS} file must also be installed.
+\texttt{\fnJS} file must also be installed. However, recall that the use of
+the marginal edit button or link annotation does not require installation of
+a JavaScript file.
\section{Final comments}
The method of producing the checkboxes in the margins work for many of the
-situations that arise in producing a {\LaTeX} document; however, the three
-`input modes' \cs{InputParas}, \cs{InputQuizItems}, and \cs{InputItems} may
-fail in some situations. By studying the DTX file perhaps you can create more
-input modes that solve your problem.
+situations that arise in producing a {\LaTeX} document; the four
+`input modes' \cs{InputParas}, \cs{InputQuizItems}, \cs{InputProbs}, and
+\cs{InputItems}, however, may fail in some situations. By studying the DTX file perhaps
+you can create more input modes that solve your problem.
\newtopic\noindent
-It was lovely, but now I must return to my retirement. \dps
+It has been lovely, but now I must return to my retirement. \dps
\end{document}
diff --git a/macros/latex/contrib/pmdb/docs/pmdb.pdf b/macros/latex/contrib/pmdb/docs/pmdb.pdf
index 9c3394b494..7b80a8910a 100644
--- a/macros/latex/contrib/pmdb/docs/pmdb.pdf
+++ b/macros/latex/contrib/pmdb/docs/pmdb.pdf
Binary files differ
diff --git a/macros/latex/contrib/pmdb/docs/sample-item.tex b/macros/latex/contrib/pmdb/docs/sample-item.tex
deleted file mode 100644
index 21d93a9ea4..0000000000
--- a/macros/latex/contrib/pmdb/docs/sample-item.tex
+++ /dev/null
@@ -1,4 +0,0 @@
-\item
-This is content destined for an list environment and was input by \verb|\pmInput|.
-
-\endinput
diff --git a/macros/latex/contrib/pmdb/docs/sample-para.tex b/macros/latex/contrib/pmdb/docs/sample-para.tex
deleted file mode 100644
index c70612ccd8..0000000000
--- a/macros/latex/contrib/pmdb/docs/sample-para.tex
+++ /dev/null
@@ -1,7 +0,0 @@
-These methods are not restricted to inputting quiz items or whole
-chapters. This paragraph was input into the main document with
-\cs{pmInput\darg{sample-para.tex}}. Note the check box in the left margin. If
-you have \texttt{aeb-reader.js} or \texttt{aeb\_pro.js} properly installed, you can \uif{Ctrl+Click} to
-see this paragraph at the source.
-
-\endinput
diff --git a/macros/latex/contrib/pmdb/examples/probs/prob2.tex b/macros/latex/contrib/pmdb/examples/probs/prob2.tex
index 033fe41fb3..f633c48f81 100644
--- a/macros/latex/contrib/pmdb/examples/probs/prob2.tex
+++ b/macros/latex/contrib/pmdb/examples/probs/prob2.tex
@@ -1,4 +1,4 @@
\item \PTs{4} Select which of the following is true.
-\begin{answers}{4}
+\begin{answers}{4}%
\Ans1 True &\Ans0 False &\Ans0 Maybe &\Ans0 Sometimes
\end{answers}
diff --git a/macros/latex/contrib/pmdb/examples/probs/prob4.tex b/macros/latex/contrib/pmdb/examples/probs/prob4.tex
index 924d5da033..6110595a37 100644
--- a/macros/latex/contrib/pmdb/examples/probs/prob4.tex
+++ b/macros/latex/contrib/pmdb/examples/probs/prob4.tex
@@ -1,3 +1,6 @@
\essayQ{5} % num points assigned
\item\PTs{5} Write a short history of Acro\negthinspace\TeX.\par
-\RespBoxEssay{\linewidth}{1in}
+\RespBoxEssay*{\linewidth}{1in}
+\begin{solution}
+The history is well-known.
+\end{solution} \ No newline at end of file
diff --git a/macros/latex/contrib/pmdb/examples/tst-eqedb.tex b/macros/latex/contrib/pmdb/examples/tst-eqedb.tex
new file mode 100644
index 0000000000..40de899102
--- /dev/null
+++ b/macros/latex/contrib/pmdb/examples/tst-eqedb.tex
@@ -0,0 +1,94 @@
+\documentclass{article}
+\usepackage[%nosolutions,
+ forcolorpaper,
+ pointsonright,totalsonright,
+ links,
+ vspacewithsolns
+ ]{eqexam} %online,
+\usepackage[dbmode,tight]{pmdb}
+
+
+\email{dpstory@uakron.edu}
+
+\university
+{%
+ NORTHWEST FLORIDA STATE COLLEGE\\
+ Department of Mathematics
+}
+\email{storyd@nwfsc.edu}
+\subject[MAC1105]{College Algebra}
+\examNum{1}\numVersions{1}\forVersion{a}
+\longTitleText
+ {Test~\nExam}
+\endlongTitleText
+\shortTitleText
+ {T\nExam}
+\endshortTitleText
+\altTitle{\vA{11:00 am, C-204}\vB{12:30 pm, L-138}}
+\title[\sExam]{\Exam}
+\author{Dr.\ D. P. Story}
+\date{\thisterm, \the\year}
+\duedate{10/09/14}
+\keywords{MAC 1105, Exam \nExam, {\thisterm} semester, \theduedate, at NWFSC}
+
+%\previewOn\pmpvOn
+\editSourceOn
+%\useEditBtn % the default
+\useEditLnk % try it with links
+\InputProbs
+\reversemarginpar
+
+\let\env\texttt
+\def\cs#1{\texttt{\eqbs#1}}
+
+\cfooteqe{\displayChoices{}{11bp}\cgBdry[1em]\clrChoices{}{11bp}}
+
+%\NoTotals
+\TotalsOnRight
+%\advance\marginparwidth12pt
+
+
+\begin{document}
+
+\maketitle
+
+\section{My first exam}
+
+Welcome to this section. Now that you've learned quite a lot, we can have
+a little quiz.
+
+
+\begin{exam}{dps1}
+\begin{instructions}
+Solve each without error.
+\end{instructions}
+
+\pmInput{eqexam/prob1.tex}
+
+\pmInput{eqexam/prob2.tex}
+
+\begin{eqComments}
+There are two ways of inputting content for a \env{problem*}: (1) in the source file, input items
+of the \env{parts} environment; (2) and input the whole \env{problem*} environment. The next problem
+is input using method (1); a \env{problem*} shell is placed in this source file and the individual items
+within the \env{parts} environment are input with \cs{pmInput}.
+\end{eqComments}
+
+\begin{problem*}[5ea]
+Solve each.
+\begin{parts}
+ \pmInput{eqexam/item1.tex}
+ \pmInput{eqexam/item2.tex}
+\end{parts}
+\end{problem*}
+
+\begin{eqComments}
+The whole of the next \env{problem*} environment is input with \cs{pmInput}. Interestingly, the items
+of the \env{parts} environment are still itemized by \cs{pmInput}.
+\end{eqComments}
+
+\pmInput{eqexam/prob3.tex}
+
+\end{exam}
+
+\end{document}
diff --git a/macros/latex/contrib/pmdb/examples/tst-items.tex b/macros/latex/contrib/pmdb/examples/tst-items.tex
index 46b25a10fe..b065a52f92 100644
--- a/macros/latex/contrib/pmdb/examples/tst-items.tex
+++ b/macros/latex/contrib/pmdb/examples/tst-items.tex
@@ -2,7 +2,12 @@
\usepackage[forcolorpaper]{web}
\usepackage[dbmode,!tight]{pmdb}
-\previewOn
+\previewOn\pmpvOn
+
+\editSourceOn
+\useEditBtn % the default
+%\useEditLnk % try it with links
+
\reversemarginpar
@@ -19,7 +24,7 @@ The \texttt{itemize} environment
\end{itemize}
\medskip\noindent
-The \texttt{environment} environment
+The \texttt{enumerate} environment
\begin{enumerate}
\item One\marginpar{One}
\item Two\marginpar{Two}
diff --git a/macros/latex/contrib/pmdb/examples/tst-paras.tex b/macros/latex/contrib/pmdb/examples/tst-paras.tex
index 550e58dbe7..cd9794f0c4 100644
--- a/macros/latex/contrib/pmdb/examples/tst-paras.tex
+++ b/macros/latex/contrib/pmdb/examples/tst-paras.tex
@@ -4,12 +4,14 @@
\usepackage{eforms}
\usepackage[dbmode]{pmdb}
-%\usepackage{srcltx}
-
%\previewOn\pmpvOn
+\editSourceOn
+%\useEditBtn % the default
+\useEditLnk % try it with links
+
% The default input mode
-%\InputParas
+\InputParas
\def\cs#1{\texttt{\eqbs#1}}
@@ -30,8 +32,8 @@ in the margins and executes an \cs{input} command.
% Adjust paths as needed
\pmInput{chapters/doc1.tex}
-%\input{"my doc2.tex"}
-\pmInput{"C:/Users/Public/Documents/My TeX Files/tex/latex/aeb/pmdb/examples/chapters/doc2.tex"}
+\input{"my doc2.tex"}
+%\pmInput{"C:/Users/Public/Documents/My TeX Files/tex/latex/aeb/pmdb/examples/chapters/doc2.tex"}
\medskip\noindent
\displayChoices{}{11bp}\cgBdry[1em]\clrChoices{}{11bp}
diff --git a/macros/latex/contrib/pmdb/examples/tst-qzdb-paras.pdf b/macros/latex/contrib/pmdb/examples/tst-qzdb-paras.pdf
new file mode 100644
index 0000000000..96680eefab
--- /dev/null
+++ b/macros/latex/contrib/pmdb/examples/tst-qzdb-paras.pdf
Binary files differ
diff --git a/macros/latex/contrib/pmdb/examples/tst-qzdb-paras.tex b/macros/latex/contrib/pmdb/examples/tst-qzdb-paras.tex
index eb6807eb6e..c7623e9d62 100644
--- a/macros/latex/contrib/pmdb/examples/tst-qzdb-paras.tex
+++ b/macros/latex/contrib/pmdb/examples/tst-qzdb-paras.tex
@@ -2,7 +2,7 @@
\usepackage{amstext}
\usepackage[forcolorpaper]{web}
\usepackage{exerquiz}[2019/12/17]
-\usepackage[dbmode,!tight]{pmdb}
+\usepackage[dbmode,tight]{pmdb}
\reversemarginpar
@@ -11,7 +11,11 @@
\useBeginQuizButton[\CA{Begin}]
\useEndQuizButton[\CA{End}]
+
%\previewOn\pmpvOn
+\editSourceOn
+\useEditBtn % the default
+%\useEditLnk % try it with links
\rfooter{\dirTOCItem} % \dirTOCItem from web
diff --git a/macros/latex/contrib/pmdb/examples/tst-qzdb.pdf b/macros/latex/contrib/pmdb/examples/tst-qzdb.pdf
new file mode 100644
index 0000000000..ba2db8a5fb
--- /dev/null
+++ b/macros/latex/contrib/pmdb/examples/tst-qzdb.pdf
Binary files differ
diff --git a/macros/latex/contrib/pmdb/examples/tst-qzdb.tex b/macros/latex/contrib/pmdb/examples/tst-qzdb.tex
index ac1898a83a..2abfe56995 100644
--- a/macros/latex/contrib/pmdb/examples/tst-qzdb.tex
+++ b/macros/latex/contrib/pmdb/examples/tst-qzdb.tex
@@ -16,6 +16,10 @@
\version{1.0}
\norevisionLabel
+\editSourceOn
+%\useEditBtn % the default
+%\useEditLnk % try it with links
+
\PTsHook{($\eqPTs^{\text{pts}}$)}
@@ -27,15 +31,16 @@
\useMCCircles
+
% Declares input for quiz items
\InputQuizItems
-
\begin{document}
\maketitle
\tableofcontents
+
\section{Section 1}
Expand the \cs{InputQuizItems} here.
@@ -55,7 +60,7 @@ Solve each of these problems, passing is 100\%.
\section{Section 2}
-%\InputQuizItems
+\InputQuizItems
\begin{quiz*}{myquiz2}
diff --git a/macros/latex/contrib/pmdb/pmdb.dtx b/macros/latex/contrib/pmdb/pmdb.dtx
index 6a0d209981..1d13d3d2f5 100644
--- a/macros/latex/contrib/pmdb/pmdb.dtx
+++ b/macros/latex/contrib/pmdb/pmdb.dtx
@@ -4,7 +4,7 @@
%<*copyright>
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% pmdb.sty package,, %%
-%% Copyright (C) 2019 D. P. Story %%
+%% Copyright (C) 2019-2021 D. P. Story %%
%% dpstory@uakron.edu dpstory@acrotex.net %%
%% %%
%% This program can redistributed and/or modified under %%
@@ -16,7 +16,7 @@
%</copyright>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{pmdb}
-%<package> \ProvidesPackage{pmdb}[2019/12/09 v0.4 Mark for input files]
+%<package> \ProvidesPackage{pmdb}[2021/06/07 v1.0 Mark for input files]
%<*driver>
\documentclass{ltxdoc}
\usepackage[colorlinks,hyperindex=false,linktocpage,bookmarksnumbered]{hyperref}
@@ -48,6 +48,7 @@
\renewcommand{\subparagraph}
{\@startsection{subparagraph}{5}{\parindent}{6pt}{-3pt}%
{\normalfont\normalsize\bfseries}}
+ \let\@latex@warning\@gobble
\makeatother
\InputIfFileExists{aebdocfmt.def}{\PackageInfo{pmdb}{Inputting aebdocfmt.def}}
{\def\IndexOpt{\DescribeMacro}\def\IndexKey{\DescribeMacro}\let\setupFullwidth\relax
@@ -117,6 +118,7 @@
%\paragraph*{The production stage:} After the document has been assembled (using \pkg{pmdb}), and you build your final document
%(perhaps an \pkg{exerquiz} quiz), the end user can use an appropriate PDF reader. If an \pkg{exerquiz} quiz is used, then
%a minimum of \app{Adobe Acrobat Reader} is required.
+%\changes{v1.0}{2021/06/07}{Upgrading v0.6 to v1.0 for publication}
% \section{The main code}
% \begin{macrocode}
\edef\th@dquoteCat{\the\catcode`\"}
@@ -125,23 +127,27 @@
% \end{macrocode}
%\subsection{Package options and package requirements}
%
-%\leavevmode\IndexOpt{dbmode} The default option is \opt{dbmode}. When in effect, check boxes
-%appear in the margins at each \cs{pmInput} point.
+%\leavevmode\IndexOpt{dbmode}^^A
+% The default option is \opt{dbmode}. When in effect, check boxes
+% appear in the margins at each \cs{pmInput} point.
% \begin{macrocode}
\DeclareOption{dbmode}{\pmdbmodetrue}
% \end{macrocode}
-%\leavevmode\IndexOpt[\protect\EXCL]{!dbmode} A convenient way to turn off the creation of the check boxes
-%is to simply place an exclamation point (!) in front of the \opt{dbmode} option.
+%\leavevmode\IndexOpt[\protect\EXCL]{!dbmode}^^A
+% A convenient way to turn off the creation of the check boxes
+% is to simply place an exclamation point (!) in front of the \opt{dbmode} option.
% \begin{macrocode}
\DeclareOption{!dbmode}{\pmdbmodefalse}
% \end{macrocode}
-%\leavevmode\IndexOpt{tight} When this option is taken, the checkboxes are tight against the text box
-%area.
+%\leavevmode\IndexOpt{tight}^^A
+% When this option is taken, the checkboxes are tight against the text box
+% area.
% \begin{macrocode}
\newif\ifpmdbtight \pmdbtightfalse
\DeclareOption{tight}{\pmdbtighttrue}
% \end{macrocode}
-%\leavevmode\IndexOpt[\protect\EXCL]{!tight} The default for the package, the checkboxes are placed
+%\leavevmode\IndexOpt[\protect\EXCL]{!tight}^^A
+%The default for the package, the checkboxes are placed
%to extreme left (or right) in the margins.
% \begin{macrocode}
\DeclareOption{!tight}{\pmdbtightfalse}
@@ -152,50 +158,105 @@
% One motivation for this package is to support the \pkg{thorshammer} package, to that end
% we make the following assignment, if Thor is not present.
% This is to prevent stoppage:
-% if your are inputting a \cs{RespBoxEssay} question that is accompanied by the
-% \cs{essayQ} command, defined in \pkg{thorshammer}.\medskip
+% if you are inputting a \cs{RespBoxEssay} question that is accompanied by the
+% \cs{essayQ} command, defined in \pkg{thorshammer}.
% \begin{macrocode}
\def\pmdb@ckThor{\@ifundefined{essayQ}{\let\essayQ\@gobble}{}}
\AtBeginDocument{\pmdb@ckThor}
% \end{macrocode}
-%\subsection{Form field creation}
-% \textbf{Some Booleans and counters}
+%\subsection{Some switches}
+% \textbf{Some Booleans and counters.}
+% The \cs{ifpmdbFP} switch is set to true when the path to the resource is a full path; otherwise, it is set to false.
+% The \cs{ifpmdbDQs} switch is set to true of double-quotes are detected; otherwise it is false.
% \begin{macrocode}
\newif\ifpmdbFP \pmdbFPfalse
\newif\ifpmdbDQs \pmdbDQsfalse
+% \end{macrocode}
+%\subsection{Form field creation}
+% In version dated 2021/01/03, we introduce a button to edit the resource directly in the default application.
+% If can be turned on with \DescribeMacro\editSourceOn\cs{editSourceOn} and off again with \DescribeMacro\editSourceOff
+% \cs{editSourceOff}. The default is off. These commands can be placed
+% anywhere in the document and affect all subsequent insertions of \cs{cbSelectInput}.
+% \changes{v0.6}{2021/01/03}{Added \string\cs{editSourceOn} and \string\cs{editSourceOff}}
+% \begin{macrocode}
+\newif\ifeditSource \editSourcefalse
+\def\editSourceOn{\editSourcetrue}
+\def\editSourceOff{\editSourcefalse}
\newcount\pmdb@Cnt
% \end{macrocode}
%
-%\subsubsection{Check box creation}
+%\subsubsection{Marginal edit source creation}
%
+% First up is the design for the edit pushbutton or link annotation.
+% \begin{macro}{\editSourceBtn}\hskip-\marginparsep\texttt{[\ameta{options}]\darg{\ameta{wd}}\darg{\ameta{ht}}}
+% The button to show the current referenced content in the default application.
+% \changes{v0.6}{2021/01/03}{Added \string\cs{editSourceBtn}}
+% \begin{macrocode}
+\newcommand{\editSourceBtn}[3][]{\def\@editSourceBtn##1{%
+ \pushButton[\A{/S/Launch/F(##1)}\protect\A#1
+ ]{editPb.\the\pmdb@Cnt}{#2}{#3}}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\editSourceBtn}\hskip-\marginparsep\texttt{[\ameta{options}]\darg{\ameta{wd}}\darg{\ameta{ht}}\darg{\ameta{txt}}}
+% The link version of the button.
+% \changes{v0.6}{2021/01/03}{Added \string\cs{editSourceLnk}}
+% \begin{macrocode}
+\newcommand{\editSourceLnk}[4][]{\def\@editSourceLnk##1{%
+ \raisebox{1bp}{\setLinkBbox[\A{/S/Launch/F(##1)}
+ \protect\A#1]{#2}{#3}[c]{\makebox[#2][l]{\thinspace#4}}}}}
+% \end{macrocode}
+% Declare the appearance of this push button and link
+% \begin{macrocode}
+\editSourceBtn[\TU{View in default editor}\S{S}]{11bp}{11bp}
+\editSourceLnk[\linktxtcolor{red}\H{N}]{11bp}{11bp}{E}
+% \end{macrocode}
+% We provide a control for setting the annot used to edit the source:
+% \DescribeMacro\useEditBtn\cs{useEditBtn}, a pushbutton is used;
+% \DescribeMacro\useEditLnk\cs{useEditLnk}, a link is used. The default
+% is to use a pushbutton.
+% \changes{v0.6}{2021/01/03}{Added \string\cs{useEditBtn} and \string\cs{useEditLnk}}
+% \begin{macrocode}
+\def\useEditBtn{\def\@editSourceBorL{\@editSourceBtn}}
+\def\useEditLnk{\def\@editSourceBorL{\@editSourceLnk}}
+\useEditBtn
+% \end{macrocode}
+%\subsubsection{Marginal checkbox creation}
%\DescribeMacro\cbSelectInput\nmpsep{\darg{\ameta{path}}} creates a check box with a tool tip of \ameta{path}
%The mouse up action \cs{ccBoxMU} fixes up relative paths, and defines a \uif{Ctrl+Click} action. When the check box
-%is so clicked, the \ameta{path} is opened in the default TEX editor. The \ameta{path} can be relative or absolute.
+%is so clicked, the \ameta{path} is opened in the default browser. The \ameta{path} can be relative or absolute.
%This command is used within \cs{insertCkBx}; its \ameta{path} argument is passed to it from \cs{insertCkBx}.
+%\changes{v0.6}{2021/01/03}{Added hard wired action to launch the default application.}
% \begin{macrocode}
\def\pmCBPresets#1{\def\pm@CBPresets{#1}}
\pmCBPresets{}
-\def\cbSelectInput#1{\checkBox[\TU{#1}\presets{\pm@CBPresets}
- \cmd{\bParams{#1}{\the\pmdb@Cnt}\eParams}
- \AAmouseup{\ccBoxMU}
- ]{pmdbCkBx.\the\pmdb@Cnt}{11bp}{11bp}{On}%
- \global\advance\pmdb@Cnt\@ne}
% \end{macrocode}
-%\leavevmode\DescribeMacro\insertCkBx\nmpsep{\darg{\ameta{method}}} The argument of this macro describes the method
+% Here is the check box that appears in the margins and the edit source button
+% \cs{ifeditSource} is true.
+% \begin{macrocode}
+\def\cbSelectInput#1{\mbox{\checkBox[\TU{#1}\presets{\pm@CBPresets}
+ \cmd{\bParams{#1}{\the\pmdb@Cnt}\eParams}
+ \AAmouseup{\ccBoxMU}]{pmdbCkBx.\the\pmdb@Cnt}{11bp}{11bp}{On}%
+ \ifeditSource\olBdry\@editSourceBorL{#1}\fi}\global
+ \advance\pmdb@Cnt\@ne
+}
+% \end{macrocode}
+% \end{macro}
+%\leavevmode\DescribeMacro\insertCkBx\nmpsep{\darg{\ameta{method}}}
+% The argument of this macro describes the method
%of inserting the checkbox. The default definition works well for a straightforward document, where you are inputting
%ordinary {\LaTeX} code (such as sections or chapters).\smallskip
% \begin{macrocode}
\def\insertCkBx#1{\def\@insertCkBx##1{#1}}
% \end{macrocode}
% Placement of check boxes in the margin. \DescribeMacro\pmAlignCB\cs{pmAlignCB} controls the marginpar placement.
-% \DescribeMacro\normalCBMargins\cs{normalCBMargins} places it according to the rules of \cs{marginpar};
% \DescribeMacro\altCBMargins\cs{altCBMargins} alternates the margin placement, forces the check box to the
% extreme left (on odd pages) and extreme right (on even pages).
% \begin{macrocode}
\def\setCBsMarg{%
\ifpmdbtight
\if@reversemargin
- \def\pmAlignCBAlt{\ifodd\value{page}\leavevmode\hfill\else\fi}\else
+ \def\pmAlignCBAlt{\ifodd\value{page}\leavevmode
+ \hfill\else\fi}\else
\def\pmAlignCBAlt{\ifodd\value{page}\else\hfill\fi}\fi
\else
\if@reversemargin
@@ -216,27 +277,47 @@
% This is the default declaration. It works well when you are inputting content
% that goes into horizontal mode. We insert the check box at the beginning of the
% first paragraph. When you are inputting files that come into a list environment, this method
-% does not work satisfactory.\medskip\par\noindent
-%\DescribeMacro\InputParas declares that the next \cs{pmInput} macros are for paragraph content.
-%This is the default state of the package. %\par\medskip
-%\paragraph*{pmInput states}
+% does not work satisfactory.
+%
+%\section{\tops{\cs}{\textbackslash}{pmInput} states}
+% The switch \cs{ifqzInput} is set to true when \cs{InputQuizItems} is expanded;
+% otherwise, it is set to false.
% \begin{macrocode}
-\def\InputParas{%\let\pmAlignCB\relax
+\newif\ifqzInput \qzInputfalse
+% \end{macrocode}
+% \DescribeMacro\InputParas This macro declares that the next \cs{pmInput} macros are for paragraph content.
+%This is the default state of the package.
+% \begin{macrocode}
+\def\InputParas{\global\qzInputfalse
\insertCkBx{\ifpmdbmode
- \everypar{\marginpar{\pmAlignCB\cbSelectInput{##1}}\global\everypar{}}\fi}}
+ \everypar{\marginpar{\pmAlignCB
+ \cbSelectInput{##1}}\global\everypar{}}\fi}}
+% \end{macrocode}
+% Set the default to be \cs{InputParas}
+% \begin{macrocode}
\InputParas
% \end{macrocode}
+% The \DescribeMacro\InputProbs\cs{InputProbs} is a command that declares
+% the next \cs{pmInput} is for questions for an \pkg{eqexam}
+% document. Currently this command is still under development.
+% \begin{macrocode}
+\def\InputProbs{\global\qzInputfalse
+ \insertCkBx{\ifpmdbmode
+ \def\prior@questionsHook{\marginpar
+ {\pmAlignCB\cbSelectInput{##1}}}\fi}}
+% \end{macrocode}
%\leavevmode
-%\DescribeMacro\InputQuizItems declares that the next \cs{pmInput} macros are for items in
+%\DescribeMacro\InputQuizItems The macro declares that the next \cs{pmInput} is for items in
%a \env{quiz} environment of \pkg{exerquiz}
%\changes{v0.4}{2019/12/09}{Modified to work when no points are specified}
% \begin{macrocode}
\newcount\saveQNo \saveQNo\z@
\def\pmHook@qzItems{%
\let\item@pmOld\item
- \def\item@pnNew{\item@pmOld\itemhook\let\item\item@pmOld}%
- \let\item\item@pnNew}
-\def\InputQuizItems{\let\pmHook\pmHook@qzItems
+ \def\item@pmNew{\item@pmOld\itemhook\let\item\item@pmOld}%
+ \let\item\item@pmNew}
+\def\InputQuizItems{\global\qzInputtrue
+ \let\pmHook\pmHook@qzItems
\saveQNo\z@
\insertCkBx{\def\cbInQzMargin{\cbSelectInput{##1}}}%
\ItemHook{\leavevmode\ifpmdbmode
@@ -245,7 +326,7 @@
\saveQNo=\arabic{eqquestionnoi}\fi}}
% \end{macrocode}
%\leavevmode
-%\DescribeMacro\InputItems declares that the next \cs{pmInput} macros are for items in
+%\DescribeMacro\InputItems This command declares that the next \cs{pmInput} macros are for items in
%an list environment 2019/12/09 v0.4
%\changes{v0.4}{2019/12/09}{Added \string\cs{InputItems}}
% \begin{macrocode}
@@ -262,12 +343,14 @@
\let\item\item@pmNew
}
\def\ItemHook#1{\def\itemhook{#1}}
-\def\InputItems{\let\pmHook\pmHook@item
+\def\InputItems{\global\qzInputfalse
+ \let\pmHook\pmHook@item
\insertCkBx{\def\cbInQzMargin{\cbSelectInput{##1}}}%
\ItemHook{\leavevmode\ifpmdbmode
\marginpar{\pmAlignCB\cbInQzMargin}\fi}}
% \end{macrocode}
-%\paragraph*{Place check box and input \ameta{path}}\leavevmode\par\medskip
+%
+%\paragraph*{Place checkbox and input \ameta{path}}\leavevmode\par\medskip
%\noindent
%\DescribeMacro\ckBxInput\nmpsep{\darg{\ameta{path}}} Places the check box and inputs the \ameta{path}.
% \begin{macrocode}
@@ -277,42 +360,61 @@
\def\donext{\pmHook\input{#1}}\fi
\donext}
% \end{macrocode}
-%\subsubsection{Push button creation}
+%\subsection{Other pushbutton creations}
%This package provides two form fields that are used for the DB step.\par\medskip
%\noindent
%\DescribeMacro\displayChoices\nmpsep{[\ameta{options}]\darg{\ameta{wd}}\darg{\ameta{ht}}} inserts a push button
%whose action is to display the selections in the console window. The argument \ameta{wd} can be empty, in which
%case, the width of the field is determined from the \cs{CA} key.
% \begin{macrocode}
-\def\displayChoiceCA#1{\def\displayChoice@CA{#1}}
-\def\displayChoiceTU#1{\def\displayChoice@TU{#1}}
-\displayChoiceCA{Display Choices}
-\displayChoiceTU{Lists all choices in the console window}
\newcommand{\displayChoices}[3][]{\pushButton[\TU{\displayChoice@TU}
\CA{\displayChoice@CA}#1\AAmouseup{\sldInputs}\protect\AA
]{sldInputs}{#2}{#3}}
% \end{macrocode}
+% Easy access to the \cs{CA} and \cs{TU} keys, for language localization, are provided.
+% These are \DescribeMacro\displayChoiceCA\cs{displayChoiceCA\darg{\ameta{text}}} and
+% \DescribeMacro\displayChoiceTU\cs{displayChoiceTU\darg{\ameta{text}}}.
+% \begin{macrocode}
+\def\displayChoiceCA#1{\def\displayChoice@CA{#1}}
+\def\displayChoiceTU#1{\def\displayChoice@TU{#1}}
+\displayChoiceCA{Display Choices}
+\displayChoiceTU{Display all choices in the console window}
+% \end{macrocode}
%\DescribeMacro\clrChoices\nmpsep{[\ameta{options}]\darg{\ameta{wd}}\darg{\ameta{ht}}} inserts a push button
% whose action is to clear all check boxes (and underlying JavaScript variables) created by this package.
% The argument \ameta{wd} can be empty, in which
% case, the width of the field is determined from the \cs{CA} key.
% \begin{macrocode}
+\newcommand{\clrChoices}[3][]{\pushButton[\TU{\clrChoices@TU}
+ \CA{\clrChoices@CA}#1\AAmouseup{\clrAction}\protect\AA
+]{Inputs}{#2}{#3}}
+% \end{macrocode}
+% Easy access to the \cs{CA} and \cs{TU} keys, for language localization, are provided.
+% These are \DescribeMacro\clrChoicesCA\cs{clrChoicesCA\darg{\ameta{text}}} and
+% \DescribeMacro\clrChoicesTU\cs{clrChoicesTU\darg{\ameta{text}}}.
+% \begin{macrocode}
\def\clrChoicesCA#1{\def\clrChoices@CA{#1}}
\def\clrChoicesTU#1{\def\clrChoices@TU{#1}}
+% \end{macrocode}
+% The default declarations for these two.
+% \begin{macrocode}
\clrChoicesCA{Clear Choices}
-\clrChoicesTU{Clears all check boxes created by pmdb}
-\newcommand{\clrChoices}[3][]{\pushButton[\TU{\clrChoices@TU}
- \CA{\clrChoices@CA}#1\AAmouseup{\clrAction}\protect\AA
-]{sldInputs}{#2}{#3}}
+\clrChoicesTU{Clear all check boxes created by pmdb}
% \end{macrocode}
%
-%\subsection{Defining the \cs{pmInput} command}
+%\subsection{Defining the \tops{\protect\cs}{}{pmInput} command}
%
-%\DescribeMacro\pmInput\nmpsep{[\ameta{arg}]\darg{\ameta{path}}} is the main user-interface for inputting a file; here,
-%the macros name is \cs{pmInput}, ultimately it calls \cs{input} with the same path. Paths with spaces
+%\DescribeMacro\pmInput\nmpsep{*[\ameta{arg}]\darg{\ameta{path}}} is the main user-interface for inputting a file; here,
+%the macro's name is \cs{pmInput}, ultimately it calls \cs{input} with the same path. Paths with spaces
%must be enclosed in double quotes (|\pmInput{my cool problem.tex}|) and the extensions must always be used.
+%It the \texttt* option is specified, \cs{pmInput} gobbles up all remaining arguments and does nothing otherwise.
+%The optional argument \ameta{arg} is only obeyed when \cs{InputItems} is in affect; it is passed on to
+%the underlying \cs{item}, as in \cs{item[\ameta{arg}]}. The \ameta{path} argument is the path to the content to be input;
+%if the \ameta{path} contains spaces, then the path must be enclosed in double quotes (\texttt{"my cool path/file.tex"}).
% \begin{macrocode}
-\def\pmInput{\@ifnextchar[%]
+\newcommand\@gobbleOR[2][]{}
+\def\pmInput{\@ifstar{\@gobbleOR}{\pmInput@i}}
+\def\pmInput@i{\@ifnextchar[%]
{\let\pm@Brk\ef@YES\inputConta}
{\let\pm@Brk\ef@NO\inputConta}}
\let\pm@Brk\ef@NO
@@ -352,16 +454,20 @@
% in other package, in particular in the \pkg{srcltx}. So we allow the use of \cs{Input}
% if \cs{Input} is not otherwise defined.
% \begin{macrocode}
-\def\pmInputWarni{\PackageWarningNoLine{pmdb}{The command \string\Input\space
- is already defined.\MessageBreak
+\def\pmInputWarni{\PackageWarningNoLine{pmdb}{The command
+ \string\Input\space is already defined.\MessageBreak
The checkboxes may not appear in the margins.\MessageBreak
Use the supported command \string\pmInput\space instead}}
\def\pmInputWarnii{\PackageWarningNoLine{pmdb}{Letting
\string\Input\space to \string\pmInput. You are \MessageBreak
encouraged to use the supported\MessageBreak
command \string\pmInput\space instead}}
-\def\pmInputChk{\@ifundefined{Input}{\let\Input\pmInput\pmInputWarnii}
- {\pmInputWarni}}
+\def\pmInputChk{%
+ \@ifundefined{Input}{%
+ \gdef\Input{\pmInputWarnii
+ \global\let\pmInputWarnii\relax
+ \global\let\pmInputWarni\relax
+ \pmInput}}{\pmInputWarni}}
\AtBeginDocument{\pmInputChk}
% \end{macrocode}
%
@@ -369,8 +475,9 @@
% \leavevmode
%\DescribeMacro\ccBoxMU
% This is the JavaScript action of the check box, used in \cs{cbSelectInput}
+% This code uses two parameters \cs{p(1)=\ameta{path}} and \cs{p(2)=\ameta{cnt}} (|\the\pmdb@Cnt|).
% \begin{macrocode}
-\begin{defineJS}[\makeesc\@\catcode`\%=14\relax]{\ccBoxMU}
+\begin{defineJS}[\makeesc\@\makecmt\%]{\ccBoxMU}
@ifpmdbFP%
event.target.userName=("@p(1)");
@else%
@@ -382,28 +489,48 @@ event.target.userName=("@p(1)");
var pos=this.path.lastIndexOf("/");
var thispath=this.path.substring(0,pos+1);
% \end{macrocode}
-% \enspace\verb|/<drive>/user/documents/.../myfolder/|
+% \enspace|/<drive>/user/documents/.../myfolder/|
% \begin{macrocode}
-pos=this.path.indexOf("/",1);
-var drive=thispath.substring(0,pos);
+pos=thispath.indexOf("/",1);
+var drive=thispath.substring(1,pos);
var platform=app.platform;
+% \end{macrocode}
+% \uif{Windows} platform
+% \begin{macrocode}
if (platform=="WIN")
% \end{macrocode}
-% \hskip\parindent\enspace\verb|/<drive>:/user/documents/.../myfolder/|
+% \enspace|<drive>:/user/documents/.../myfolder/|
% \begin{macrocode}
thispath=drive+":/"+thispath.substring(pos+1);
-event.target.userName=thispath+("@p(1)");
-@fi%
+% \end{macrocode}
+% \uif{MacOS} platform: I'm not familiar with the \uif{MacOS} file system, so we'll just
+% assume it is the same as with Windows.
+% \begin{macrocode}
+if (platform=="MAC")
+% \end{macrocode}
+% \enspace|<drive>/user/documents/.../myfolder/|
+% \begin{macrocode}
+ thispath=drive+"/"+thispath.substring(pos+1);
+event.target.userName=thispath+("@p(1)");@fi
if (event.modifier){
- var _to=app.setTimeOut("_restoreCCState('pmdbCkBx.@p(2)');",.05);
+ event.target.checkThisBox(0,!event.target.isBoxChecked(0));
try {
- aebTrustedFunctions(this,aebLaunchURL,
- {cURL: "file://"+event.target.userName});
+ aebTrustedFunctions(this,aebLaunchURL,%
+{cURL: "file:///"+event.target.userName});
} catch(e) {
console.show();
console.println("The Ctrl+Click action is not supported, %
-installation of aeb\_pro.js is required.");
+installation of aeb\_pro.js or aeb-reader.js is required.");
}
+% \end{macrocode}
+% (2020/04/29) Add a shift event for quizzes.
+% \changes{v0.5}{2020/04/29}{Added \string\texttt{event.shift} for quizzes}
+% \begin{macrocode}
+}
+if (event.shift) {
+ event.target.checkThisBox(0,!event.target.isBoxChecked(0));%
+@ifqzInput
+ this.gotoNamedDest("@currQuiz."+(@p(2)+1));@fi
} else {
if (event.target.isBoxChecked(0)){
_oSPaths["pmdbCkBx.@p(2)"]=%
@@ -425,18 +552,18 @@ installation of aeb\_pro.js is required.");
% and displays them in the console window of \app{Acrobat/Reader}, used in
% \cs{displayChoices}.
% \begin{macrocode}
-\begin{defineJS}[\catcode`\%=14\relax]{\sldInputs}
+\begin{defineJS}[\makecmt\%]{\sldInputs}
console.clear();console.show();
if (_numInputs==0) console.println("No inputs selected");
else {
for(var i=0;i<_aInputs.length;i++){
if (!!_aInputs[i]){
if(_oSPaths["pmdbCkBx."+i][1])
- console.println(%
-'\\\\input\{\\"'+(_oSPaths["pmdbCkBx."+i][0])+'\\"\}');
+ console.println('\\\\input\{\\"'+(_oSPaths["pmdbCkBx."+i][0])%
++'\\"\}');
else
- console.println(%
-'\\\\input\{'+(_oSPaths["pmdbCkBx."+i][0])+'\}');
+ console.println('\\\\input\{'+(_oSPaths["pmdbCkBx."+i][0])%
++'\}');
}
}
}
@@ -444,7 +571,7 @@ else {
% \end{macrocode}
%\leavevmode
%\DescribeMacro\clrAction
-% Mouse up action to clear the check boxes and to re-initialize internal
+% Mouse up action to clear the checkboxes and to re-initialize internal
% internal JS variables. Used in \cs{clrChoices}.
% \begin{macrocode}
\begin{defineJS}{\clrAction}
@@ -460,13 +587,6 @@ this.resetForm("pmdbCkBx");
var _oSPaths=new Object;
var _aInputs=new Array;
var _numInputs=0;
-function _restoreCCState(fName){
- var f=this.getField(fName);
- var _ccState=%
-(typeof f["_boxState"]=="undefined")?false:f["_boxState"];
- f["_boxState"]=_ccState;
- return f.checkThisBox(0,_ccState);
-}
\end{insDLJS}
% \end{macrocode}
% \begin{macrocode}
diff --git a/macros/latex/contrib/pythontex/NEWS.rst b/macros/latex/contrib/pythontex/NEWS.rst
index b0eccb7df5..69b60dad66 100644
--- a/macros/latex/contrib/pythontex/NEWS.rst
+++ b/macros/latex/contrib/pythontex/NEWS.rst
@@ -7,6 +7,26 @@ Version History
===============
+v0.18 (2021/06/06)
+------------------
+
+* ``\inputpygments`` now checks inputted files for modification, so that
+ typeset code will correctly update when the source is changed (#162).
+
+* Julia now uses project flag "``--project=@.``" (#157, #158).
+
+* Fixed bug in processing Pygments options (``pygopt``) when a key is used
+ without a value (#181).
+
+* Some error handling for Windows was incompatible with other operating
+ systems: replaced checks for ``WindowsError`` with checks for ``OSError``
+ (#177).
+
+* Rust support is now compatible with document and working directory paths
+ that contain spaces (#167).
+
+
+
v0.17 (2019/09/22)
------------------
diff --git a/macros/latex/contrib/pythontex/README b/macros/latex/contrib/pythontex/README
index 3994eca34c..8928d3d748 100644
--- a/macros/latex/contrib/pythontex/README
+++ b/macros/latex/contrib/pythontex/README
@@ -3,7 +3,7 @@
===================================================================
:Author: Geoffrey Poore
-:Version: 0.17 (2019/09/22)
+:Version: 0.18 (2021/06/06)
:License: LPPL v1.3 or later (LaTeX code) and BSD 3-Clause (Python code)
:Development: https://github.com/gpoore/pythontex
:Requirements: Python 2.7 or 3.2+; Pygments
diff --git a/macros/latex/contrib/pythontex/depythontex2.py b/macros/latex/contrib/pythontex/depythontex2.py
index f49fd22977..997a30d6ea 100644
--- a/macros/latex/contrib/pythontex/depythontex2.py
+++ b/macros/latex/contrib/pythontex/depythontex2.py
@@ -47,7 +47,7 @@ example, typeset code may have a different appearance or layout when it is
typeset with a different package.
-Copyright (c) 2013-2017, Geoffrey M. Poore
+Copyright (c) 2013-2021, Geoffrey M. Poore
All rights reserved.
Licensed under the BSD 3-Clause License:
http://www.opensource.org/licenses/BSD-3-Clause
@@ -86,7 +86,7 @@ import codecs
# Script parameters
# Version
-__version__ = '0.17'
+__version__ = '0.18'
# Functions and parameters for customizing the script output
diff --git a/macros/latex/contrib/pythontex/depythontex3.py b/macros/latex/contrib/pythontex/depythontex3.py
index 2d86edb591..e27abea118 100644
--- a/macros/latex/contrib/pythontex/depythontex3.py
+++ b/macros/latex/contrib/pythontex/depythontex3.py
@@ -47,7 +47,7 @@ example, typeset code may have a different appearance or layout when it is
typeset with a different package.
-Copyright (c) 2013-2017, Geoffrey M. Poore
+Copyright (c) 2013-2021, Geoffrey M. Poore
All rights reserved.
Licensed under the BSD 3-Clause License:
http://www.opensource.org/licenses/BSD-3-Clause
@@ -86,7 +86,7 @@ import codecs
# Script parameters
# Version
-__version__ = '0.17'
+__version__ = '0.18'
# Functions and parameters for customizing the script output
diff --git a/macros/latex/contrib/pythontex/pythontex.dtx b/macros/latex/contrib/pythontex/pythontex.dtx
index f18d8d3fae..38d44ffd9e 100644
--- a/macros/latex/contrib/pythontex/pythontex.dtx
+++ b/macros/latex/contrib/pythontex/pythontex.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright (C) 2012-2019 by Geoffrey M. Poore <gpoore@gmail.com>
+% Copyright (C) 2012-2021 by Geoffrey M. Poore <gpoore@gmail.com>
% ---------------------------------------------------------------------------
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
@@ -26,7 +26,7 @@
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{pythontex}
%<*package>
- [2019/09/22 v0.17 execute and typeset Python code and other languages]
+ [2021/06/06 v0.18 execute and typeset Python code and other languages]
%</package>
%
%<*driver>
@@ -168,6 +168,17 @@
%
%
%
+% \begin{changelog}{v0.18}{2021/06/06}
+% \begin{itemize}
+% \item \texttt{\string\inputpygments} now checks inputted files for modification, so that typeset code will correctly update when the source is changed (\#162).
+% \item Julia now uses project flag ``\texttt{-{}-project=@.}'' (\#157, \#158).
+% \item Fixed bug in processing Pygments options (\texttt{pygopt}) when a key is used without a value (\#181).
+% \item Some error handling for Windows was incompatible with other operating systems: replaced checks for \texttt{WindowsError} with checks for \texttt{OSError} (\#177).
+% \item Rust support is now compatible with document and working directory paths that contain spaces (\#167).
+% \end{itemize}
+% \end{changelog}
+%
+%
% \begin{changelog}{v0.17}{2019/09/22}
% \begin{itemize}
% \item Pygments syntax highlighting for the Python console (\texttt{pycon} lexer) now uses the \texttt{python3} option, and the default Python lexer is now \texttt{python3} (\#156).
@@ -891,7 +902,9 @@
%
% \DescribeMacro{\pys\oarg{session}\meta{opening~delim}\meta{code}\meta{closing~delim}}
%
-% This command performs variable and expression substitution, or string interpolation, on \meta{code}. Fields of the form |!{|\meta{expr}|}| in \meta{code} are replaced with the evaluated and printed output of \meta{expr}. The suffix |s| is an abbreviation of |sub|, for ``substitute.'' This command is useful for inserting Python-generated content in contexts where the normal |\py| and |\pyc| would not function or would be inconvenient due to the restrictions imposed by \LaTeX. Since Python processes \meta{code} and performs substitutions before the result is passed to \LaTeX, substitution fields may be anywhere.
+% This command performs variable and expression substitution, or string interpolation, on \meta{code}. Fields of the form |!{|\meta{expr}|}| in \meta{code} are replaced with the evaluated and printed output of \meta{expr}. Then the modified \meta{code} is inserted into the document and interpreted as \LaTeX. The suffix |s| is an abbreviation of |sub|, for ``substitute.''
+%
+% This command is useful for inserting Python-generated content in contexts where the normal |\py| and |\pyc| would not function or would be inconvenient due to the restrictions imposed by \LaTeX. Since Python processes \meta{code} and performs substitutions \emph{before} the result is passed to \LaTeX, substitution fields may be anywhere, including within parts of \meta{code} that will become \LaTeX\ comments.
%
% Literal exclamation points |!| in \meta{code} only need to be escaped when they immediately precede an opening curly brace |{|, or when they precede exclamation points that precede a brace. Escaping is performed by doubling. Thus, |!!{| would indicate a literal exclamation point followed by a literal curly brace (|!{|), not the beginning of a substitution field. And |!!!{| would indicate a literal exclamation point (|!!|) followed by a substitution field (|!{...}|). Because curly braces |{}| only have the meaning of field delimiters when immediately following a non-escaped exclamation point, curly braces never need to be escaped.
%
@@ -926,7 +939,7 @@
%
% \DescribeEnv{pysub~\oarg{session}\oarg{fancyvrb~settings}}
%
-% This environment performs variable and expression substitution, or string interpolation, on the enclosed code. Fields of the form |!{|\meta{expr}|}| in \meta{code} are replaced with the evaluated and printed output of \meta{expr}. See the description of the |\pys| command for details about substitution field syntax.
+% This environment performs variable and expression substitution, or string interpolation, on the enclosed code. Fields of the form |!{|\meta{expr}|}| in \meta{code} are replaced with the evaluated and printed output of \meta{expr}. See the description of the |\pys| command for details about substitution and the substitution field syntax.
%
%
%
@@ -1885,7 +1898,7 @@
% We store the name of the package in a macro for later use in warnings and error messages.
% \begin{macrocode}
\newcommand{\pytx@packagename}{PythonTeX}
-\newcommand{\pytx@packageversion}{0.17}
+\newcommand{\pytx@packageversion}{0.18}
% \end{macrocode}
%
% \subsection{Required packages}
diff --git a/macros/latex/contrib/pythontex/pythontex.ins b/macros/latex/contrib/pythontex/pythontex.ins
index aab14011f7..83dd081ef3 100644
--- a/macros/latex/contrib/pythontex/pythontex.ins
+++ b/macros/latex/contrib/pythontex/pythontex.ins
@@ -25,7 +25,7 @@
This is a generated file.
-Copyright (C) 2012-2019 by Geoffrey M. Poore <gpoore@gmail.com>
+Copyright (C) 2012-2021 by Geoffrey M. Poore <gpoore@gmail.com>
--------------------------------------------------------------------------
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either version 1.3
diff --git a/macros/latex/contrib/pythontex/pythontex.pdf b/macros/latex/contrib/pythontex/pythontex.pdf
index ad9183d3ac..f6cd05d922 100644
--- a/macros/latex/contrib/pythontex/pythontex.pdf
+++ b/macros/latex/contrib/pythontex/pythontex.pdf
Binary files differ
diff --git a/macros/latex/contrib/pythontex/pythontex2.py b/macros/latex/contrib/pythontex/pythontex2.py
index 34e151f417..661ef37f2f 100644
--- a/macros/latex/contrib/pythontex/pythontex2.py
+++ b/macros/latex/contrib/pythontex/pythontex2.py
@@ -13,7 +13,7 @@ should be in the same directory.
Licensed under the BSD 3-Clause License:
-Copyright (c) 2012-2019, Geoffrey M. Poore
+Copyright (c) 2012-2021, Geoffrey M. Poore
All rights reserved.
@@ -78,7 +78,7 @@ else:
# Script parameters
# Version
-__version__ = '0.17'
+__version__ = '0.18'
@@ -437,7 +437,7 @@ def load_code_get_settings(data, temp_data):
elif v in ('false', 'False'):
v = False
else:
- k = option
+ k = options
v = True
opt_dict[k] = v
if family != ':GLOBAL':
@@ -869,12 +869,15 @@ def hash_all(data, temp_data, old_data, engine_dict):
if family in pygments_settings:
if (not pygments_settings_changed[family] and
key in old_typeset_hash_dict and
- typeset_hash_dict[key] == old_typeset_hash_dict[key]):
+ typeset_hash_dict[key] == old_typeset_hash_dict[key] and
+ not modified_dependencies(key, data, old_data, temp_data)):
pygments_update[key] = False
if key in old_pygments_macros:
pygments_macros[key] = old_pygments_macros[key]
if key in old_pygments_files:
pygments_files[key] = old_pygments_files[key]
+ if key in old_dependencies:
+ dependencies[key] = old_dependencies[key]
else:
pygments_update[key] = True
else:
@@ -1229,7 +1232,7 @@ def do_multiprocessing(data, temp_data, old_data, engine_dict):
exec_cmd = shlex.split(command.format(file=script.replace('\\', '\\\\'), File=script_full.replace('\\', '\\\\')))
try:
proc = subprocess.Popen(exec_cmd)
- except (WindowsError, FileNotFoundError) as e:
+ except (OSError, FileNotFoundError) as e:
if platform.system() == 'Windows' and e.errno == 2:
# Batch files won't be found when called without extension. They
# would be found if `shell=True`, but then getting the right
@@ -1359,11 +1362,15 @@ def do_multiprocessing(data, temp_data, old_data, engine_dict):
# Add a Pygments process
if pygments_list:
+ # Uncomment the following for debugging
+ # do_pygments(encoding, outputdir, fvextfile, pygments_list,
+ # pygments_settings, typeset_cache, hashdependencies)
tasks.append(pool.apply_async(do_pygments, [encoding, outputdir,
fvextfile,
pygments_list,
pygments_settings,
- typeset_cache]))
+ typeset_cache,
+ hashdependencies]))
if verbose:
print(' - Pygments process')
@@ -1412,6 +1419,8 @@ def do_multiprocessing(data, temp_data, old_data, engine_dict):
if result['pygments_files'][k]:
new_files = True
break
+ for k, v in result['dependencies'].items():
+ dependencies[k] = v
pygments_macros.update(result['pygments_macros'])
errors += result['errors']
warnings += result['warnings']
@@ -1560,7 +1569,7 @@ def run_code(encoding, outputdir, workingdir,
proc = subprocess.Popen(exec_cmd, stdout=out_file, stderr=err_file)
else:
proc = subprocess.Popen(exec_cmd, stdout=out_file, stderr=subprocess.STDOUT)
- except WindowsError as e:
+ except OSError as e:
if e.errno == 2:
# Batch files won't be found when called without extension. They
# would be found if `shell=True`, but then getting the right
@@ -2362,7 +2371,7 @@ def run_code(encoding, outputdir, workingdir,
def do_pygments(encoding, outputdir, fvextfile, pygments_list,
- pygments_settings, typeset_cache):
+ pygments_settings, typeset_cache, hashdependencies):
'''
Create Pygments content.
@@ -2380,6 +2389,7 @@ def do_pygments(encoding, outputdir, fvextfile, pygments_list,
warnings = 0
messages = []
messages.append('\n---- Messages for Pygments ----')
+ dependencies = {}
# Create dicts of formatters and lexers.
formatter = dict()
@@ -2402,6 +2412,12 @@ def do_pygments(encoding, outputdir, fvextfile, pygments_list,
f = open(c.extfile, encoding=encoding)
content = f.read()
f.close()
+ if hashdependencies:
+ hasher = sha1()
+ hasher.update(content.encode(encoding))
+ dependencies[c.key_typeset] = {c.extfile: (os.path.getmtime(c.extfile), hasher.hexdigest())}
+ else:
+ dependencies[c.key_typeset] = {c.extfile: (os.path.getmtime(c.extfile), '')}
else:
content = None
messages.append('* PythonTeX error')
@@ -2440,6 +2456,7 @@ def do_pygments(encoding, outputdir, fvextfile, pygments_list,
return {'process': 'pygments',
'pygments_files': pygments_files,
'pygments_macros': pygments_macros,
+ 'dependencies': dependencies,
'errors': errors,
'warnings': warnings,
'messages': messages}
diff --git a/macros/latex/contrib/pythontex/pythontex3.py b/macros/latex/contrib/pythontex/pythontex3.py
index bc61f912ca..488c234c25 100644
--- a/macros/latex/contrib/pythontex/pythontex3.py
+++ b/macros/latex/contrib/pythontex/pythontex3.py
@@ -13,7 +13,7 @@ should be in the same directory.
Licensed under the BSD 3-Clause License:
-Copyright (c) 2012-2019, Geoffrey M. Poore
+Copyright (c) 2012-2021, Geoffrey M. Poore
All rights reserved.
@@ -78,7 +78,7 @@ else:
# Script parameters
# Version
-__version__ = '0.17'
+__version__ = '0.18'
@@ -437,7 +437,7 @@ def load_code_get_settings(data, temp_data):
elif v in ('false', 'False'):
v = False
else:
- k = option
+ k = options
v = True
opt_dict[k] = v
if family != ':GLOBAL':
@@ -869,12 +869,15 @@ def hash_all(data, temp_data, old_data, engine_dict):
if family in pygments_settings:
if (not pygments_settings_changed[family] and
key in old_typeset_hash_dict and
- typeset_hash_dict[key] == old_typeset_hash_dict[key]):
+ typeset_hash_dict[key] == old_typeset_hash_dict[key] and
+ not modified_dependencies(key, data, old_data, temp_data)):
pygments_update[key] = False
if key in old_pygments_macros:
pygments_macros[key] = old_pygments_macros[key]
if key in old_pygments_files:
pygments_files[key] = old_pygments_files[key]
+ if key in old_dependencies:
+ dependencies[key] = old_dependencies[key]
else:
pygments_update[key] = True
else:
@@ -1229,7 +1232,7 @@ def do_multiprocessing(data, temp_data, old_data, engine_dict):
exec_cmd = shlex.split(command.format(file=script.replace('\\', '\\\\'), File=script_full.replace('\\', '\\\\')))
try:
proc = subprocess.Popen(exec_cmd)
- except (WindowsError, FileNotFoundError) as e:
+ except (OSError, FileNotFoundError) as e:
if platform.system() == 'Windows' and e.errno == 2:
# Batch files won't be found when called without extension. They
# would be found if `shell=True`, but then getting the right
@@ -1359,11 +1362,15 @@ def do_multiprocessing(data, temp_data, old_data, engine_dict):
# Add a Pygments process
if pygments_list:
+ # Uncomment the following for debugging
+ # do_pygments(encoding, outputdir, fvextfile, pygments_list,
+ # pygments_settings, typeset_cache, hashdependencies)
tasks.append(pool.apply_async(do_pygments, [encoding, outputdir,
fvextfile,
pygments_list,
pygments_settings,
- typeset_cache]))
+ typeset_cache,
+ hashdependencies]))
if verbose:
print(' - Pygments process')
@@ -1412,6 +1419,8 @@ def do_multiprocessing(data, temp_data, old_data, engine_dict):
if result['pygments_files'][k]:
new_files = True
break
+ for k, v in result['dependencies'].items():
+ dependencies[k] = v
pygments_macros.update(result['pygments_macros'])
errors += result['errors']
warnings += result['warnings']
@@ -1560,7 +1569,7 @@ def run_code(encoding, outputdir, workingdir,
proc = subprocess.Popen(exec_cmd, stdout=out_file, stderr=err_file)
else:
proc = subprocess.Popen(exec_cmd, stdout=out_file, stderr=subprocess.STDOUT)
- except WindowsError as e:
+ except OSError as e:
if e.errno == 2:
# Batch files won't be found when called without extension. They
# would be found if `shell=True`, but then getting the right
@@ -2362,7 +2371,7 @@ def run_code(encoding, outputdir, workingdir,
def do_pygments(encoding, outputdir, fvextfile, pygments_list,
- pygments_settings, typeset_cache):
+ pygments_settings, typeset_cache, hashdependencies):
'''
Create Pygments content.
@@ -2380,6 +2389,7 @@ def do_pygments(encoding, outputdir, fvextfile, pygments_list,
warnings = 0
messages = []
messages.append('\n---- Messages for Pygments ----')
+ dependencies = {}
# Create dicts of formatters and lexers.
formatter = dict()
@@ -2402,6 +2412,12 @@ def do_pygments(encoding, outputdir, fvextfile, pygments_list,
f = open(c.extfile, encoding=encoding)
content = f.read()
f.close()
+ if hashdependencies:
+ hasher = sha1()
+ hasher.update(content.encode(encoding))
+ dependencies[c.key_typeset] = {c.extfile: (os.path.getmtime(c.extfile), hasher.hexdigest())}
+ else:
+ dependencies[c.key_typeset] = {c.extfile: (os.path.getmtime(c.extfile), '')}
else:
content = None
messages.append('* PythonTeX error')
@@ -2440,6 +2456,7 @@ def do_pygments(encoding, outputdir, fvextfile, pygments_list,
return {'process': 'pygments',
'pygments_files': pygments_files,
'pygments_macros': pygments_macros,
+ 'dependencies': dependencies,
'errors': errors,
'warnings': warnings,
'messages': messages}
diff --git a/macros/latex/contrib/pythontex/pythontex_engines.py b/macros/latex/contrib/pythontex/pythontex_engines.py
index 4928826bf1..6b00dbbf6f 100644
--- a/macros/latex/contrib/pythontex/pythontex_engines.py
+++ b/macros/latex/contrib/pythontex/pythontex_engines.py
@@ -17,7 +17,7 @@ document (script for execution).
-Copyright (c) 2012-2018, Geoffrey M. Poore
+Copyright (c) 2012-2021, Geoffrey M. Poore
All rights reserved.
Licensed under the BSD 3-Clause License:
http://www.opensource.org/licenses/BSD-3-Clause
@@ -1107,14 +1107,14 @@ julia_wrapper = '''
julia_sub = '''println("{field_delim}")\nprintln({field})\n'''
-CodeEngine('julia', 'julia', '.jl', '{julia} "{file}.jl"', julia_template,
+CodeEngine('julia', 'julia', '.jl', '{julia} --project=@. "{file}.jl"', julia_template,
julia_wrapper, 'println(jltex.formatter({code}))', julia_sub,
'ERROR:', 'WARNING:', ':{number}', True)
SubCodeEngine('julia', 'jl')
-CodeEngine('juliacon', 'julia', '.jl', '{julia} -e "using Weave; weave(\\"{File}.jl\\", \\"tex\\")"', '{body}\n',
+CodeEngine('juliacon', 'julia', '.jl', '{julia} --project=@. -e "using Weave; weave(\\"{File}.jl\\", \\"tex\\")"', '{body}\n',
'#+ term=true\n{code}\n', '', '',
'ERROR:', 'WARNING:', ':{number}', True, created='{File}.tex')
@@ -1537,7 +1537,7 @@ rust_sub = '''
CodeEngine('rust', 'rust', '.rs',
# The full script name has to be used in order to make Windows and Unix behave nicely
# together when naming executables. Despite appearances, using `.exe` works on Unix too.
- ['{rustc} --crate-type bin -o {File}.exe -L {workingdir} {file}.rs', '{File}.exe'],
+ ['{rustc} --crate-type bin -o "{File}.exe" -L "{workingdir}" {file}.rs', '"{File}.exe"'],
rust_template, rust_wrapper, '{{ let val = {{ {code} }}; println!("{{}}", rstex.formatter(val)); }}', rust_sub,
errors='error:', warnings='warning:', linenumbers='.rs:{number}',
created='{File}.exe')
diff --git a/macros/latex/contrib/siunitx/CHANGELOG.md b/macros/latex/contrib/siunitx/CHANGELOG.md
index 10450afb9c..a465aea145 100644
--- a/macros/latex/contrib/siunitx/CHANGELOG.md
+++ b/macros/latex/contrib/siunitx/CHANGELOG.md
@@ -1,4 +1,4 @@
-Standard# Changelog
+# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a
@@ -7,10 +7,20 @@ Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to
## [Unreleased]
+## [v3.0.11]
+
+### Changed
+- Improve some fallback unit definitions
+
+### Fixed
+- Printing of symbols with encodings other than UTF-8 (issue #470)
+- Argument order for `\DeclareSIPrefix` (issue #471)
+- Emulation of `number-unit-separator` (issue #473)
+
## [v3.0.10]
### Changed
-- Documenation improvements
+- Documentation improvements
### Fixed
- Incompatibility with REVTeX (issue #469)
@@ -1351,7 +1361,8 @@ Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to
### Added
- First public testing release (as `si`)
-[Unreleased]: https://github.com/josephwright/siunitx/compare/v3.0.10...HEAD
+[Unreleased]: https://github.com/josephwright/siunitx/compare/v3.0.11...HEAD
+[v3.0.11]: https://github.com/josephwright/siunitx/compare/v3.0.10...v3.0.11
[v3.0.10]: https://github.com/josephwright/siunitx/compare/v3.0.9...v3.0.10
[v3.0.9]: https://github.com/josephwright/siunitx/compare/v3.0.8...v3.0.9
[v3.0.8]: https://github.com/josephwright/siunitx/compare/v3.0.7...v3.0.8
diff --git a/macros/latex/contrib/siunitx/siunitx-code.pdf b/macros/latex/contrib/siunitx/siunitx-code.pdf
index 123afd32cf..d4f36b226f 100644
--- a/macros/latex/contrib/siunitx/siunitx-code.pdf
+++ b/macros/latex/contrib/siunitx/siunitx-code.pdf
Binary files differ
diff --git a/macros/latex/contrib/siunitx/siunitx-emulation.dtx b/macros/latex/contrib/siunitx/siunitx-emulation.dtx
index cc60aa85e8..9d0133affb 100644
--- a/macros/latex/contrib/siunitx/siunitx-emulation.dtx
+++ b/macros/latex/contrib/siunitx/siunitx-emulation.dtx
@@ -776,6 +776,13 @@
{ quantity-product }
\l_keys_value_tl
} ,
+ number-unit-separator .code:n =
+ {
+ \@@_option_deprecated:nnV
+ { number-unit-separator }
+ { quantity-product }
+ \l_keys_value_tl
+ } ,
prefixes-as-symbols .choice: ,
prefixes-as-symbols / false . code:n =
{
@@ -1044,25 +1051,31 @@
\bar { bar }
\barn { b }
\bohr
- { \text { \ensuremath { a } } \char_generate:nn { `\_ } { 8 } { 0 } }
+ {
+ \exp_not:N \text
+ { \exp_not:N \ensuremath { a } } \char_generate:nn { `\_ } { 8 } { 0 }
+ }
\clight
- { \text { \ensuremath { c } } \char_generate:nn { `\_ } { 8 } { 0 } }
+ {
+ \exp_not:N \text
+ { \exp_not:N \ensuremath { c } } \char_generate:nn { `\_ } { 8 } { 0 }
+ }
\electronmass
{
- \text { \ensuremath { m } }
+ \exp_not:N \text { \exp_not:N \ensuremath { m } }
\char_generate:nn { `\_ } { 8 } { \exp_not:N \mathrm { e } }
}
\elementarycharge { \text { \ensuremath { e } } }
\hartree
{
- \text { \ensuremath { E } }
+ \exp_not:N \text { \exp_not:N \ensuremath { E } }
\char_generate:nn { `\_ } { 8 } { \exp_not:N \mathrm { h } }
}
\knot { kn }
\mmHg { mmHg }
\nauticalmile { M }
\planckbar
- { \text { \ensuremath { \exp_not:N \hbar } } }
+ { \exp_not:N \text { \exp_not:N \ensuremath { \exp_not:N \hbar } } }
\q_recursion_tail { }
\q_recursion_stop
\@ifpackageloaded { fontspec }
diff --git a/macros/latex/contrib/siunitx/siunitx-symbol.dtx b/macros/latex/contrib/siunitx/siunitx-symbol.dtx
index 8ba65fc417..251d257c4b 100644
--- a/macros/latex/contrib/siunitx/siunitx-symbol.dtx
+++ b/macros/latex/contrib/siunitx/siunitx-symbol.dtx
@@ -114,12 +114,14 @@
}
\cs_new:Npn \@@_non_latin:nnnn #1#2#3#4
{
+ \@@_deal_with_utf:
\exp_after:wN \exp_after:wN \exp_after:wN
\exp_not:N \char_generate:nn {#1} { 13 }
\exp_after:wN \exp_after:wN \exp_after:wN
\exp_not:N \char_generate:nn {#2} { 13 }
}
}
+\cs_new:Npn \@@_deal_with_utf: { }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -128,13 +130,17 @@
% A test to see if the unit definition which applies is still one we expect:
% here that means it is just using a (Unicode) codepoint. The comparison
% is string-based as \pkg{unicode-math} (at least) can alter some of them.
+% Active characters are set to \cs{scan_stop:} so that the code here gives
+% exactly the tokens (bytes) we want: needed for encodings other than
+% \textsc{utf}-8.
% \begin{macrocode}
\prg_new_protected_conditional:Npnn \@@_if_replace:Nn #1#2 { T , TF }
{
\group_begin:
- \tl_set:Nx \l_@@_tmpa_tl { \@@_non_latin:n {#2} }
\protected@edef \l_@@_tmpa_tl
- { \exp_not:N \mathrm { \l_@@_tmpa_tl } }
+ { \exp_not:N \mathrm { \@@_non_latin:n {#2} } }
+ \int_step_inline:nnn { "80 } { "FF }
+ { \char_set_active_eq:nN {##1} \scan_stop: }
\keys_set:nn { siunitx } { parse-units = false }
\siunitx_unit_format:nN {#1} \l_@@_tmpb_tl
\str_if_eq:VVTF \l_@@_tmpa_tl \l_@@_tmpb_tl
@@ -143,6 +149,7 @@
\prg_return_true:
}
{
+ \show\l_@@_tmpa_tl \show\l_@@_tmpb_tl
\group_end:
\prg_return_false:
}
@@ -178,8 +185,12 @@
{
\siunitx_declare_unit:Nxn \degree
{
- \siunitx_print_text:n
- { \@@_non_latin:n { "00B0 } }
+ \exp_not:N \text
+ {
+ \@ifpackageloaded { inputenc }
+ { \exp_not:N \textdegree }
+ { \@@_non_latin:n { "00B0 } }
+ }
}
{ quantity-product = { } }
}
@@ -202,8 +213,13 @@
{
\siunitx_declare_unit:Nx \degreeCelsius
{
- \siunitx_print_text:n
- { \@@_non_latin:n { "00B0 } } C
+ \exp_not:N \text
+ {
+ \@ifpackageloaded { inputenc }
+ { \exp_not:N \textdegree }
+ { \@@_non_latin:n { "00B0 } }
+ }
+ C
}
}
}
@@ -221,7 +237,7 @@
{ \exp_not:N \upOmega }
{ \exp_not:N \Omega }
\exp_not:N \else
- \siunitx_print_text:n
+ \exp_not:N \text
{
\bool_lazy_or:nnTF
{ \sys_if_engine_luatex_p: }
@@ -240,7 +256,7 @@
{
\siunitx_declare_prefix:Nnx \micro { -6 }
{
- \siunitx_print_text:n
+ \exp_not:N \text
{
\bool_lazy_or:nnTF
{ \sys_if_engine_luatex_p: }
diff --git a/macros/latex/contrib/siunitx/siunitx-unit.dtx b/macros/latex/contrib/siunitx/siunitx-unit.dtx
index 01f85be714..3cbfa728fc 100644
--- a/macros/latex/contrib/siunitx/siunitx-unit.dtx
+++ b/macros/latex/contrib/siunitx/siunitx-unit.dtx
@@ -220,7 +220,7 @@
%
% \begin{function}{\siunitx_declare_power:NNn}
% \begin{syntax}
-% \cs{siunitx_declare_power:NnN} \meta{pre-power} \meta{post-power} \Arg{value}
+% \cs{siunitx_declare_power:NNn} \meta{pre-power} \meta{post-power} \Arg{value}
% \end{syntax}
% Defines \emph{two} symbolic \meta{powers} (which should be control
% sequences such as |\squared|) to be converted by the parser to the
diff --git a/macros/latex/contrib/siunitx/siunitx.dtx b/macros/latex/contrib/siunitx/siunitx.dtx
index d6f8821495..03d06b4cb3 100644
--- a/macros/latex/contrib/siunitx/siunitx.dtx
+++ b/macros/latex/contrib/siunitx/siunitx.dtx
@@ -121,7 +121,7 @@
%
% Identify the package and give the over all version information.
% \begin{macrocode}
-\ProvidesExplPackage {siunitx} {2021-06-04} {3.0.10}
+\ProvidesExplPackage {siunitx} {2021-06-07} {3.0.11}
{A comprehensive (SI) units package}
% \end{macrocode}
%
@@ -246,7 +246,7 @@
}
\NewDocumentCommand \DeclareSIPrefix { +m m m }
{
- \siunitx_declare_prefix:Nnn #1 {#2} {#3}
+ \siunitx_declare_prefix:Nnn #1 {#3} {#2}
}
\NewDocumentCommand \DeclareSIQualifier { +m m }
{
diff --git a/macros/latex/contrib/siunitx/siunitx.pdf b/macros/latex/contrib/siunitx/siunitx.pdf
index 426815f99c..62115e1004 100644
--- a/macros/latex/contrib/siunitx/siunitx.pdf
+++ b/macros/latex/contrib/siunitx/siunitx.pdf
Binary files differ
diff --git a/macros/latex/contrib/suftesi/suftesi.dtx b/macros/latex/contrib/suftesi/suftesi.dtx
index 2ded276ca5..02fec48f52 100644
--- a/macros/latex/contrib/suftesi/suftesi.dtx
+++ b/macros/latex/contrib/suftesi/suftesi.dtx
@@ -56,7 +56,7 @@ This work has the LPPL maintenance status "author-maintained".
%<class>\NeedsTeXFormat{LaTeX2e}[2005/12/01]
%<class>\ProvidesClass{suftesi}
%<*class>
- [2021/06/05 v3.1.2 A class for typesetting theses, books and articles]
+ [2021/06/06 v3.1.3 A class for typesetting theses, books and articles]
%</class>
%<*driver>
\documentclass[12pt]{ltxdoc}
@@ -338,7 +338,7 @@ cochineal,mathpazo,bera,amsthm}
%</driver>
% \fi
%
-% \CheckSum{5683}
+% \CheckSum{5686}
%
% \CharacterTable
% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
@@ -356,6 +356,10 @@ cochineal,mathpazo,bera,amsthm}
% Grave accent \` Left brace \{ Vertical bar \|
% Right brace \} Tilde \~}
%
+% \changes{v3.1.3}{2021/06/06}{Maintenance release.
+% Moved commands for breaking titles after \opt{titletoc} settings.
+% Corrected a bug in \cmd{maketitle} with the \opt{collection} structure.
+% Added \sty{etoolbox}, previously removed by mistake.}
% \changes{v3.1.2}{2021/06/05}{Corrected a bug with \opt{reverseauthortitle} option.}
% \changes{v3.1.1}{2021/05/23}{Redefined some boolean options. Renamed some private commands. Corrected a bug in headers numbering (\cmd{protect} removed). Disabled automatic partial ToC functionality. Improved \opt{fewfootnotes} option via \sty{zref}. Updated documentation.}
% \changes{v3.1.0}{2021/05/20}{Replaced \cmd{val}\cmd{nr} with \cmd{suftesi@val}\cmd{suftesi@nr}. Corrected a bug with \cmd{maketitle} in \opt{collection} structure. New options \opt{partialtoc} and \opt{maketitlestyle}. New commands for customizing the partial ToC. New value \opt{justify} for \opt{quotestyle} option. Improved \opt{quotesize} option. Renamed the \opt{revauthortitle} option to \opt{reverseauthortitle}. The options \opt{titlefont}, \opt{authorfont}, \opt{reverseauthortitle} now work for every structure. Renewed documentation}
@@ -457,7 +461,7 @@ cochineal,mathpazo,bera,amsthm}
% \DoNotIndex{\titlepage,\vss,\vtop,\xdef,\@gobbletwo,\color,\dimexpr}
% \DoNotIndex{\huge,\large,\makebox,\ProcessOptions,\renewcommand}
%
-%\nocite{appendix,caption,color,crop,enumitem,emptypage,fancyhdr,fixltxhyph,fontsize,mathalpha,libertinust1math,newtx,geometry,iftex,microtype,multicol,titlesec,titletoc,xkeyval,cclicenses,substitutefont,luatex85,lm,textcomp,newpx,biolinum,inconsolata,libertine,cochineal,mathpazo,bera,amsthm,zref}
+%\nocite{appendix,caption,color,crop,enumitem,emptypage,fancyhdr,fixltxhyph,fontsize,mathalpha,libertinust1math,newtx,geometry,iftex,microtype,multicol,titlesec,titletoc,xkeyval,cclicenses,substitutefont,luatex85,lm,textcomp,newpx,biolinum,inconsolata,libertine,cochineal,mathpazo,bera,amsthm,zref,etoolbox}
%
% \thispagestyle{empty}
%
@@ -610,7 +614,7 @@ cochineal,mathpazo,bera,amsthm}
% \toprule
% \multicolumn{2}{c}{\textbf{Context}} & \multicolumn{1}{c}{\textbf{Packages}} \\
% \midrule
-% & \textrm{Global} & appendix, caption, color, crop, enumitem, emptypage,
+% & \textrm{Global} & appendix, caption, color, crop, enumitem, emptypage, etoolbox,
% fancyhdr, fixltxhyph, fontenc, fontsize, geometry, iftex,
% microtype, multicol, titlesec, titletoc,
% xkeyval, cclicenses*, zref** \\
@@ -2437,7 +2441,6 @@ cochineal,mathpazo,bera,amsthm}
\def\SUF@chapswitch{}
\or
\suftesi@collectiontrue
- \SUF@titlepagefalse
\setkeys{}{headerstyle=authortitleinner}
\def\SUF@chapswitch{}
\fi}
@@ -3788,6 +3791,10 @@ cochineal,mathpazo,bera,amsthm}
\RequirePackage{luatex85}
\fi
% \end{macrocode}
+% The \sty{etoolbox} package is required to use \cmd{AtEndPreamble} (see \pageref{page:atendpreamble}).
+% \begin{macrocode}
+\RequirePackage{etoolbox}
+% \end{macrocode}
% The FSPL style requires a verbose colophon which uses specific icons:
% \begin{macrocode}
\ifsuftesi@FSPL
@@ -4015,7 +4022,7 @@ cochineal,mathpazo,bera,amsthm}
\fi
\fi
% \end{macrocode}
-%The following macro was created by Claudio Beccari. Some time later, Massimiliano Dominici suggested the use of \cmd{AtEndPreamble} instead of \cmd{AtBeginDocument}, to make the \env{otherlanguage} environment work.
+%The following macro was created by Claudio Beccari. Some time later, Massimiliano Dominici suggested the use of \cmd{AtEndPreamble} instead of \cmd{AtBeginDocument}, to make the \env{otherlanguage} environment work.\label{page:atendpreamble}
% \begin{macrocode}
\AtEndPreamble{
\substitutefont{LGR}{\rmdefault}{\SUF@greekfamily}
@@ -4406,46 +4413,6 @@ cochineal,mathpazo,bera,amsthm}
{\relax}}
\fi
% \end{macrocode}
-% \subsubsection{Commands for sections font}
-% \begin{macrocode}
-\newcommand{\partfont}[1]{\def\SUF@PART@font{#1}}
-\newcommand{\chapfont}[1]{\def\SUF@CHAP@font{#1}}
-\newcommand{\secfont}[1]{\def\SUF@SEC@font{#1}}
-\newcommand{\subsecfont}[1]{\def\SUF@SUBSEC@font{#1}}
-\newcommand{\subsubsecfont}[1]{\def\SUF@SUBSUBSEC@font{#1}}
-\newcommand{\partnumfont}[1]{\def\SUF@PART@font{#1}}\partnumfont{}
-\newcommand{\chapnumfont}[1]{\def\SUF@thechapter{#1}}
-\newcommand{\secnumfont}[1]{\def\SUF@thesection{#1}}
-\newcommand{\subsecnumfont}[1]{\def\SUF@thesubsection{#1}}
-\newcommand{\subsubsecnumfont}[1]{\def\SUF@thesubsubsection{#1}}
-\newcommand{\titlefont}[1]{\def\SUF@titlestyle{#1}\let\SUF@titlefont\relax}
-\newcommand{\authorfont}[1]{\def\SUF@authorstyle{#1}\let\SUF@authorfont\relax}
-\newcommand{\datefont}[1]{\def\SUF@datefont{#1}}
-% \end{macrocode}
-% \subsubsection{Commands for breaking titles}
-% Two commands for manual breaks active, respectively, only in the table of contents and in the body text. The solution was initially made available by Enrico Gregorio many years ago in one of the first versions of the class (at that time the commands were called \cmd{headbreak} and \cmd{xheadbreak}). Later, while I was working on version 3.0, I noticed an alignment problem in the chapter titles when using the \opt{chapstyle=left} option. So I added the \cmd{breakinbodyleft} command and updated the command names to make them more recognizable. Old names are in any case available for backwards compatibility.
-% \begin{macrocode}
-\newif\ifbreakintoc\breakintocfalse
-\newif\ifbreakinbody\breakinbodytrue
-\DeclareRobustCommand{\breakintoc}
- {\ifbreakintoc\\\else\fi}
-\DeclareRobustCommand{\breakinbody}
- {\ifbreakinbody\\\else\fi}
-\DeclareRobustCommand{\breakinbodyleft}
- {\ifbreakinbody\newline\else\fi}
-\let\origtableofcontents\tableofcontents
-\renewcommand{\tableofcontents}{%
- \begingroup
- \breakintoctrue\breakinbodyfalse%
- \origtableofcontents
- \endgroup}
-\DeclareRobustCommand{\headbreak}
- {\ifbreakintoc\\\else\fi}
-\DeclareRobustCommand{\xheadbreak}
- {\ifbreakinbody\\\else\fi}
-\DeclareRobustCommand{\yheadbreak}
- {\ifbreakinbody\newline\else\fi}
-% \end{macrocode}
% \subsubsection{Abstract}
% \begin{macrocode}
\ifsuftesi@collection
@@ -5241,33 +5208,7 @@ cochineal,mathpazo,bera,amsthm}
}
\fi
% \end{macrocode}
-% \subsubsection{Commands for sections font in ToC}
-% \begin{macrocode}
-\newcommand{\tocpartname}[1]{\def\SUF@tocpartname{#1}}
- \tocpartname{\partname}
-\newcommand{\tocpartfont}[1]{\def\SUF@tocPART@font{#1}}
-\newcommand{\tocchapfont}[1]{\def\SUF@tocCHAP@font{#1}}
-\newcommand{\tocsecfont}[1]{\def\SUF@tocSEC@font{#1}}
-\newcommand{\tocsubsecfont}[1]{\def\SUF@tocSUBSEC@font{#1}}
-\newcommand{\tocsubsubsecfont}[1]{\def\SUF@tocSUBSUBSEC@font{#1}}
-\newcommand{\tocparfont}[1]{\def\SUF@tocPAR@font{#1}}
-\newcommand{\tocsubparfont}[1]{\def\SUF@tocSUBPAR@font{#1}}
-\newcommand{\tocpartnumfont}[1]{\def\SUF@tocPARTnum@font{#1}}\tocpartnumfont{}
-\newcommand{\tocchapnumfont}[1]{%
- \def\SUF@CHAP@contentslabel{\begingroup#1\thecontentslabel\endgroup}}
-\newcommand{\tocsecnumfont}[1]{%
- \def\SUF@SEC@contentslabel{\begingroup#1\thecontentslabel\endgroup}}
-\newcommand{\tocsubsecnumfont}[1]{%
- \def\SUF@SUBSEC@contentslabel{\begingroup#1\thecontentslabel\endgroup}}
-\newcommand{\tocsubsubsecnumfont}[1]{%
- \def\SUF@SUBSUBSEC@contentslabel{\begingroup#1\thecontentslabel\endgroup}}
-\newcommand{\tocparnumfont}[1]{%
- \def\SUF@PAR@contentslabel{\begingroup#1\thecontentslabel\endgroup}}
-\newcommand{\tocsubparnumfont}[1]{%
- \def\SUF@SUBPAR@contentslabel{\begingroup#1\thecontentslabel\endgroup}}
-\tocparnumfont{}
-\tocsubparnumfont{}
-% \end{macrocode}
+% \subsection{Customizing entries}
% \subsubsection{The partial ToC}
% \begin{macrocode}
\newcommand{\partialtocsize}[1]{%
@@ -5316,6 +5257,73 @@ cochineal,mathpazo,bera,amsthm}
\partialtocbeforecode{}
\partialtocaftercode{}
% \end{macrocode}
+% \subsubsection{Sections font}
+% \begin{macrocode}
+\newcommand{\partfont}[1]{\def\SUF@PART@font{#1}}
+\newcommand{\chapfont}[1]{\def\SUF@CHAP@font{#1}}
+\newcommand{\secfont}[1]{\def\SUF@SEC@font{#1}}
+\newcommand{\subsecfont}[1]{\def\SUF@SUBSEC@font{#1}}
+\newcommand{\subsubsecfont}[1]{\def\SUF@SUBSUBSEC@font{#1}}
+\newcommand{\partnumfont}[1]{\def\SUF@PART@font{#1}}\partnumfont{}
+\newcommand{\chapnumfont}[1]{\def\SUF@thechapter{#1}}
+\newcommand{\secnumfont}[1]{\def\SUF@thesection{#1}}
+\newcommand{\subsecnumfont}[1]{\def\SUF@thesubsection{#1}}
+\newcommand{\subsubsecnumfont}[1]{\def\SUF@thesubsubsection{#1}}
+\newcommand{\titlefont}[1]{\def\SUF@titlestyle{#1}\let\SUF@titlefont\relax}
+\newcommand{\authorfont}[1]{\def\SUF@authorstyle{#1}\let\SUF@authorfont\relax}
+\newcommand{\datefont}[1]{\def\SUF@datefont{#1}}
+% \end{macrocode}
+% \subsubsection{Sections font in ToC}
+% \begin{macrocode}
+\newcommand{\tocpartname}[1]{\def\SUF@tocpartname{#1}}
+ \tocpartname{\partname}
+\newcommand{\tocpartfont}[1]{\def\SUF@tocPART@font{#1}}
+\newcommand{\tocchapfont}[1]{\def\SUF@tocCHAP@font{#1}}
+\newcommand{\tocsecfont}[1]{\def\SUF@tocSEC@font{#1}}
+\newcommand{\tocsubsecfont}[1]{\def\SUF@tocSUBSEC@font{#1}}
+\newcommand{\tocsubsubsecfont}[1]{\def\SUF@tocSUBSUBSEC@font{#1}}
+\newcommand{\tocparfont}[1]{\def\SUF@tocPAR@font{#1}}
+\newcommand{\tocsubparfont}[1]{\def\SUF@tocSUBPAR@font{#1}}
+\newcommand{\tocpartnumfont}[1]{\def\SUF@tocPARTnum@font{#1}}\tocpartnumfont{}
+\newcommand{\tocchapnumfont}[1]{%
+ \def\SUF@CHAP@contentslabel{\begingroup#1\thecontentslabel\endgroup}}
+\newcommand{\tocsecnumfont}[1]{%
+ \def\SUF@SEC@contentslabel{\begingroup#1\thecontentslabel\endgroup}}
+\newcommand{\tocsubsecnumfont}[1]{%
+ \def\SUF@SUBSEC@contentslabel{\begingroup#1\thecontentslabel\endgroup}}
+\newcommand{\tocsubsubsecnumfont}[1]{%
+ \def\SUF@SUBSUBSEC@contentslabel{\begingroup#1\thecontentslabel\endgroup}}
+\newcommand{\tocparnumfont}[1]{%
+ \def\SUF@PAR@contentslabel{\begingroup#1\thecontentslabel\endgroup}}
+\newcommand{\tocsubparnumfont}[1]{%
+ \def\SUF@SUBPAR@contentslabel{\begingroup#1\thecontentslabel\endgroup}}
+\tocparnumfont{}
+\tocsubparnumfont{}
+% \end{macrocode}
+% \subsubsection{Breaking titles}
+% Two commands for manual breaks active, respectively, only in the table of contents and in the body text. The solution was initially made available by Enrico Gregorio many years ago in one of the first versions of the class (at that time the commands were called \cmd{headbreak} and \cmd{xheadbreak}). Later, while I was working on version 3.0, I noticed an alignment problem in the chapter titles when using the \opt{chapstyle=left} option. So I added the \cmd{breakinbodyleft} command and updated the command names to make them more recognizable. Old names are in any case available for backwards compatibility.
+% \begin{macrocode}
+\newif\ifbreakintoc\breakintocfalse
+\newif\ifbreakinbody\breakinbodytrue
+\DeclareRobustCommand{\breakintoc}
+ {\ifbreakintoc\\\else\fi}
+\DeclareRobustCommand{\breakinbody}
+ {\ifbreakinbody\\\else\fi}
+\DeclareRobustCommand{\breakinbodyleft}
+ {\ifbreakinbody\newline\else\fi}
+\let\origtableofcontents\tableofcontents
+\renewcommand{\tableofcontents}{%
+ \begingroup
+ \breakintoctrue\breakinbodyfalse%
+ \origtableofcontents
+ \endgroup}
+\DeclareRobustCommand{\headbreak}
+ {\ifbreakintoc\\\else\fi}
+\DeclareRobustCommand{\xheadbreak}
+ {\ifbreakinbody\\\else\fi}
+\DeclareRobustCommand{\yheadbreak}
+ {\ifbreakinbody\newline\else\fi}
+% \end{macrocode}
% \subsection{Headers and footers}
% \begin{macrocode}
\RequirePackage{fancyhdr}
@@ -5570,69 +5578,6 @@ cochineal,mathpazo,bera,amsthm}
\penalty\@highpenalty
\endgroup
\fi}
-\renewcommand\maketitle{\par
- \begingroup
- \renewcommand\thefootnote{\@fnsymbol\c@footnote}%
- \def\@makefnmark{\rlap{\@textsuperscript{\normalfont\@thefnmark}}}%
- \long\def\@makefntext##1{\parindent 1em\noindent
- \hb@xt@1.8em{%
- \hss\@textsuperscript{\normalfont\@thefnmark}}##1}%
- \if@twocolumn
- \ifnum \col@number=\@ne
- \@maketitle
- \else
- \twocolumn[\@maketitle]%
- \fi
- \else
- \newpage
- \global\@topnum\z@ % Prevents figures from going at top of page.
- \@maketitle
- \fi
- \thispagestyle{plain}\@thanks%
- \endgroup
- \setcounter{section}{0}%
-% \setcounter{footnote}{0}%
-% \global\let\thanks\relax
-% \global\let\maketitle\relax
-% \global\let\@maketitle\relax
-% \global\let\@thanks\@empty
-% \global\let\@author\@empty
-% \global\let\@date\@empty
-% \global\let\@title\@empty
-% \global\let\title\relax
-% \global\let\author\relax
-% \global\let\date\relax
- \global\let\and\relax
- \let\thanks\@gobble}
-\AtBeginDocument{\def\@maketitle{%
- \refstepcounter{article}
- \SUF@chaptersize
- \SUF@authortitle@align
- \let\footnote\thanks
- \parindent=0pt
- {\SUF@second\par}%
- \label{begin:\thearticle}
-% \end{macrocode}
-% Check if you don't use \sty{hyperrref} provided by Enrico Gregorio
-% (\url{https://tex.stackexchange.com/a/427203/231952}):
-% \begin{macrocode}
- \@ifundefined{Hy@raisedlink}{\let\texorpdfstring\@firstoftwo}{%
- \xdef\@currentHref{title.\thearticle}%
- \Hy@raisedlink{\hyper@anchorstart{\@currentHref}\hyper@anchorend}%
- }%
-% \end{macrocode}
-% \begin{macrocode}
- \csname toc@entry@\endcsname
- \begingroup%
- \let\thanks\@gobble
- \addcontentsline{toc}{title}{%
- {\SUF@tocAUT@font{\@author}}\texorpdfstring{\newline}{, }%
- {\SUF@tocTIT@font{\@headtitle}}}
- \endgroup%
- \par\nobreak\vspace{2ex}
- {\SUF@first\par%
- \vskip1.5cm}}%
- }
% \newenvironment{article}
% {\begingroup
% \global\let\@thanks\@empty
@@ -5717,6 +5662,71 @@ cochineal,mathpazo,bera,amsthm}
\protect\ClassWarningNoLine{suftesi}{%
No \string\author\space given\MessageBreak%
See the class documentation for explanation}}
+\ifsuftesi@collection
+\renewcommand\maketitle{\par
+ \begingroup
+ \renewcommand\thefootnote{\@fnsymbol\c@footnote}%
+ \def\@makefnmark{\rlap{\@textsuperscript{\normalfont\@thefnmark}}}%
+ \long\def\@makefntext##1{\parindent 1em\noindent
+ \hb@xt@1.8em{%
+ \hss\@textsuperscript{\normalfont\@thefnmark}}##1}%
+ \if@twocolumn
+ \ifnum \col@number=\@ne
+ \@maketitle
+ \else
+ \twocolumn[\@maketitle]%
+ \fi
+ \else
+ \newpage
+ \global\@topnum\z@ % Prevents figures from going at top of page.
+ \@maketitle
+ \fi
+ \thispagestyle{plain}\@thanks%
+ \endgroup
+ \setcounter{section}{0}%
+% \setcounter{footnote}{0}%
+% \global\let\thanks\relax
+% \global\let\maketitle\relax
+% \global\let\@maketitle\relax
+% \global\let\@thanks\@empty
+% \global\let\@author\@empty
+% \global\let\@date\@empty
+% \global\let\@title\@empty
+% \global\let\title\relax
+% \global\let\author\relax
+% \global\let\date\relax
+ \global\let\and\relax
+ \let\thanks\@gobble}
+\AtBeginDocument{\def\@maketitle{%
+ \refstepcounter{article}
+ \SUF@chaptersize
+ \SUF@authortitle@align
+ \let\footnote\thanks
+ \parindent=0pt
+ {\SUF@second\par}%
+ \label{begin:\thearticle}
+% \end{macrocode}
+% Check if you don't use \sty{hyperrref} provided by Enrico Gregorio
+% (\url{https://tex.stackexchange.com/a/427203/231952}):
+% \begin{macrocode}
+ \@ifundefined{Hy@raisedlink}{\let\texorpdfstring\@firstoftwo}{%
+ \xdef\@currentHref{title.\thearticle}%
+ \Hy@raisedlink{\hyper@anchorstart{\@currentHref}\hyper@anchorend}%
+ }%
+% \end{macrocode}
+% \begin{macrocode}
+ \csname toc@entry@\endcsname
+ \begingroup%
+ \let\thanks\@gobble
+ \addcontentsline{toc}{title}{%
+ {\SUF@tocAUT@font{\@author}}\texorpdfstring{\newline}{, }%
+ {\SUF@tocTIT@font{\@headtitle}}}
+ \endgroup%
+ \par\nobreak\vspace{2ex}
+ {\SUF@first\par%
+ \vskip1.5cm}}%
+ }
+\else
\ifSUF@titlepage
\renewcommand\maketitle{%
\begin{titlepage}
@@ -5788,6 +5798,7 @@ cochineal,mathpazo,bera,amsthm}
\end{center}%
\par
\vskip 1.5em}
+ \fi
\fi
% \end{macrocode}
% \subsection{Cover page}
@@ -5935,7 +5946,7 @@ cochineal,mathpazo,bera,amsthm}
\fi\fi\fi\fi\fi\fi\fi\fi\fi}
{\relax}}}
% \end{macrocode}
-% \paragraph{Colophon or copyright notice}
+% \subsection{Colophon}
% \begin{macrocode}
\newcommand{\colophon}[3][]{%
\thispagestyle{empty}
@@ -6572,6 +6583,16 @@ Janusz M.~Nowacki.
version = {v1.5e}
}
+@manual{etoolbox,
+ title = {The \sty{etoolbox} package},
+ subtitle = {An e-\TeX Toolbox for Class and Package Authors},
+ author = {Philipp Lehman and Joseph Wright},
+ url = {http://www.ctan.org/pkg/etoolbox},
+ urldate = {2021-06-06},
+ date = {2020-10-05},
+ version = {v2.5k}
+}
+
%</bib>
% \fi
% \Finale
diff --git a/macros/latex/contrib/suftesi/suftesi.pdf b/macros/latex/contrib/suftesi/suftesi.pdf
index 935cbaf61c..ec961c454b 100644
--- a/macros/latex/contrib/suftesi/suftesi.pdf
+++ b/macros/latex/contrib/suftesi/suftesi.pdf
Binary files differ
diff --git a/macros/latex/contrib/tiscreen/README b/macros/latex/contrib/tiscreen/README
index 651328b28e..d5e7e22e3f 100644
--- a/macros/latex/contrib/tiscreen/README
+++ b/macros/latex/contrib/tiscreen/README
@@ -4,6 +4,7 @@ This package mimics the screen of older Texas instruments dot matrix display
calculators, specifically the TI-82 STATS.
Changes:
+- 2021/07/07 Simplified characters table in documentation
- 2021/06/01 Added more characters
- 2021/05/21 Minor README and documentation issues
- 2021/05/17 Initial version
diff --git a/macros/latex/contrib/tiscreen/doc/tiscreen-doc.pdf b/macros/latex/contrib/tiscreen/doc/tiscreen-doc.pdf
index dfb03700e2..145a8be716 100644
--- a/macros/latex/contrib/tiscreen/doc/tiscreen-doc.pdf
+++ b/macros/latex/contrib/tiscreen/doc/tiscreen-doc.pdf
Binary files differ
diff --git a/macros/latex/contrib/tiscreen/doc/tiscreen-doc.tex b/macros/latex/contrib/tiscreen/doc/tiscreen-doc.tex
index adf8b59ca3..b4112c2524 100644
--- a/macros/latex/contrib/tiscreen/doc/tiscreen-doc.tex
+++ b/macros/latex/contrib/tiscreen/doc/tiscreen-doc.tex
@@ -5,6 +5,7 @@
\usepackage{parskip}
\usepackage[color]{tiscreen}
\usepackage{multicol}
+\usepackage{hyperref}
\usepackage{listings}
\lstset{
@@ -41,7 +42,7 @@
\tiscreen
|4+1 |
| 5|
-|Ans{sq} |
+|Ans{sq} |
| 25|
| |
| |
@@ -58,7 +59,7 @@
\tiscreen
|4+1 |
| 5|
-|Ans{sq} |
+|Ans{sq} |
| 25|
| |
| |
@@ -102,34 +103,32 @@ or by using the original {\textbackslash LCD} command.
\section{Additional defined characters} \LCDcolors{black}{white}
\begin{tabular}{l|l|l}
- Name & Symbol & Code \\
\hline
- E (scientific notation) & \LCDsymb{sciE} & \LCDcode{sciE} \\
- Sigma (lowercase) & \LCDsymb{sigma} & \LCDcode{sigma} \\
- $\bar x$ & \LCDsymb{barx} & \LCDcode{barx} \\
- $\bar y$ & \LCDsymb{bary} & \LCDcode{bary} \\
- $^\wedge 2$ (power of two) & \LCDsymb{sq} & \LCDcode{sq} \\
- $^\wedge (-1)$ & \LCDsymb{ar} & \LCDcode{ar} \\
- $_1$ & \LCDsymb{sub1} & \LCDcode{sub1} \\
- $_2$ & \LCDsymb{sub2} & \LCDcode{sub2} \\
- $_3$ & \LCDsymb{sub3} & \LCDcode{sub3} \\
- $_4$ & \LCDsymb{sub4} & \LCDcode{sub4} \\
- $_5$ & \LCDsymb{sub5} & \LCDcode{sub5} \\
- $_6$ & \LCDsymb{sub6} & \LCDcode{sub6} \\
-\end{tabular}
-
-\subsection{Redefined characters}
-Predefined characters that where redefined to match the TI-82 STATS.
-
-\begin{tabular}{l|l|l}
- Name & Symbol & Code \\
+ \multicolumn{3}{c}{\textbf{Added characters}} \\
+ \hline \hline
+ Name & Symbol & Code \\
+ \hline
+ E & \LCDsymb{sciE} & \LCDcode{sciE} \\
+ $\sigma$ & \LCDsymb{sigma} & \LCDcode{sigma} \\
+ $\bar x$ & \LCDsymb{barx} & \LCDcode{barx} \\
+ $\bar y$ & \LCDsymb{bary} & \LCDcode{bary} \\
+ $^\wedge 2$ & \LCDsymb{sq} & \LCDcode{sq} \\
+ $^\wedge (-1)$ & \LCDsymb{ar} & \LCDcode{ar} \\
+ $_1$ & \LCDsymb{sub1} & \LCDcode{sub1} \\
+ $_2$ & \LCDsymb{sub2} & \LCDcode{sub2} \\
+ $_3$ & \LCDsymb{sub3} & \LCDcode{sub3} \\
+ $_4$ & \LCDsymb{sub4} & \LCDcode{sub4} \\
+ $_5$ & \LCDsymb{sub5} & \LCDcode{sub5} \\
+ $_6$ & \LCDsymb{sub6} & \LCDcode{sub6} \\
\hline
- ! & \LCDsymb{!} & \LCDcode{!} \\
- $\sqrt{\hphantom{0}}$ (Square root) & \LCDsymb{sqrt} & \LCDcode{sqrt} \\
- e & \LCDsymb{e} & \texttt{e} \\
- i & \LCDsymb{i} & \texttt{i} \\
- v & \LCDsymb{v} & \texttt{v} \\
- w & \LCDsymb{w} & \texttt{w} \\
+ \multicolumn{3}{c}{\textbf{Redefined characters}} \\
+ \hline \hline
+ ! & \LCDsymb{!} & \LCDcode{!} \\
+ $\sqrt{\hphantom{0}}$ & \LCDsymb{sqrt} & \LCDcode{sqrt} \\
+ e & \LCDsymb{e} & \texttt{e} \\
+ i & \LCDsymb{i} & \texttt{i} \\
+ v & \LCDsymb{v} & \texttt{v} \\
+ w & \LCDsymb{w} & \texttt{w} \\
\end{tabular}
\end{document}
diff --git a/macros/latex/contrib/tiscreen/tex/tiscreen.sty b/macros/latex/contrib/tiscreen/tex/tiscreen.sty
index e227e11bac..d1693eb1b2 100644
--- a/macros/latex/contrib/tiscreen/tex/tiscreen.sty
+++ b/macros/latex/contrib/tiscreen/tex/tiscreen.sty
@@ -4,7 +4,7 @@
% license is at: http://www.latex-project.org/lppl.txt
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{tiscreen}[2021/05/17 Ti calculator screen]
+\ProvidesPackage{tiscreen}[2021/06/07 Ti calculator screen]
% TODO
% Scaling option
diff --git a/macros/luatex/generic/luatexja/README b/macros/luatex/generic/luatexja/README
index 3a433c20d4..9e51dd5766 100644
--- a/macros/luatex/generic/luatexja/README
+++ b/macros/luatex/generic/luatexja/README
@@ -1,4 +1,4 @@
-The LuaTeX-ja Package 20210521.0
+The LuaTeX-ja Package 20210607.0
--------------------------------
Copyright (c) 2011--2021 The LuaTeX-ja project
License: modified BSD (see COPYING)
@@ -42,9 +42,9 @@ Installation
2. If you must/want to install manually:
a. Download the source archive from CTAN,
- or tagged as 20210521.0 in the Git repository by
+ or tagged as 20210607.0 in the Git repository by
<http://git.osdn.jp/view?p=luatex-ja/luatexja.git
- ;a=snapshot;h=refs/tags/20210521.0;sf=tgz>
+ ;a=snapshot;h=refs/tags/20210607.0;sf=tgz>
b. Extract the archive and process following three files by LuaLaTeX
to generate classes for Japanese typesetting:
@@ -93,4 +93,4 @@ Notes
This file and ltj-kinsoku.lua are not used anymore.
(Do not remove ltj-kinsoku.tex.)
-Last commit date: Fri May 21 21:07:11 2021 +0900
+Last commit date: Mon Jun 7 20:50:27 2021 +0900
diff --git a/macros/luatex/generic/luatexja/doc/luatexja-en.pdf b/macros/luatex/generic/luatexja/doc/luatexja-en.pdf
index 4a31080cc1..6d9f8a3cd5 100644
--- a/macros/luatex/generic/luatexja/doc/luatexja-en.pdf
+++ b/macros/luatex/generic/luatexja/doc/luatexja-en.pdf
Binary files differ
diff --git a/macros/luatex/generic/luatexja/doc/luatexja-ja.pdf b/macros/luatex/generic/luatexja/doc/luatexja-ja.pdf
index ba8dad3586..4ca3182ca0 100644
--- a/macros/luatex/generic/luatexja/doc/luatexja-ja.pdf
+++ b/macros/luatex/generic/luatexja/doc/luatexja-ja.pdf
Binary files differ
diff --git a/macros/luatex/generic/luatexja/src/ltj-direction.lua b/macros/luatex/generic/luatexja/src/ltj-direction.lua
index 47b4aec1d0..d7cdbd9364 100644
--- a/macros/luatex/generic/luatexja/src/ltj-direction.lua
+++ b/macros/luatex/generic/luatexja/src/ltj-direction.lua
@@ -319,7 +319,7 @@ end
local create_dir_whatsit_vbox
do
local wh = {}
- local id_glue, sid_parskip = node.id 'glue', 3
+ local id_glue = node.id 'glue'
create_dir_whatsit_vbox = function (hd, gc)
ltjs.list_dir = get_dir_count()
-- remove dir whatsit
@@ -331,8 +331,8 @@ do
if hd==wh[1] then
ltjs.list_dir =has_attr(hd,attr_dir)
local x = node_next(hd)
- if getid(x)==id_glue and getsubtype(x)==sid_parskip then
- node_remove(hd,x); node_free(x)
+ while x and getid(x)==id_glue and getsubtype(x)==3 do
+ node_remove(hd,x); node_free(x); x = node_next(hd)
end
end
for i=1,#wh do
@@ -345,10 +345,10 @@ do
end
return hd
else
- local n =node_next(hd)
+ local n = node_next(hd)
if gc=='vtop' then
local w = create_dir_whatsit(hd, gc, ltjs.list_dir)
- -- move dir whatsit after hd
+ -- move dir whatsit after hd
setfield(hd, 'next', w); setfield(w, 'next', n)
return hd
else
diff --git a/macros/luatex/generic/luatexja/src/luatexja.sty b/macros/luatex/generic/luatexja/src/luatexja.sty
index 0eec4c94c0..d2646d5785 100644
--- a/macros/luatex/generic/luatexja/src/luatexja.sty
+++ b/macros/luatex/generic/luatexja/src/luatexja.sty
@@ -35,13 +35,13 @@
\expandafter\let\csname ifltj@in@latex\expandafter\endcsname
\csname iftrue\endcsname
\NeedsTeXFormat{LaTeX2e}
- \ProvidesPackage{luatexja}[2021-05-21 Japanese Typesetting with Lua(La)TeX]
+ \ProvidesPackage{luatexja}[2021-06-07 Japanese Typesetting with Lua(La)TeX]
\DeclareOption{disablejfam}{\ltj@disablejfamtrue}
\DeclareOption*{}
\ProcessOptions\relax
\fi %</LaTeX>
%%%% VERSION
-\def\LuaTeXjaversion{20210521.0}
+\def\LuaTeXjaversion{20210607.0}
\directlua{require('ltj-unicode-ccfix.lua')}% catcode of ideographs
diff --git a/macros/luatex/generic/luatexja/src/patches/lltjfont.sty b/macros/luatex/generic/luatexja/src/patches/lltjfont.sty
index 31f0f645d8..1e9abe047b 100644
--- a/macros/luatex/generic/luatexja/src/patches/lltjfont.sty
+++ b/macros/luatex/generic/luatexja/src/patches/lltjfont.sty
@@ -3,14 +3,16 @@
%
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{lltjfont}[2021-04-29 Patch to NFSS2 for LuaTeX-ja]
+\ProvidesPackage{lltjfont}[2021-05-26 Patch to NFSS2 for LuaTeX-ja]
%%%%%%%% LaTeX2e version detection
\newcount\ltj@@latex@plv \ltj@@latex@plv=-1
\ifltj@ltfilehook@avail
- \IfHookExistsTF{selectfont}%
+\ExplSyntaxOn
+ \cs_if_exist:NTF \__shipout_execute_main_cont:Nnnn
{\ltj@@latex@plv=1500}% 2021-06-01
- {\ifnum\patch@level>2 \ltj@@latex@plv=1300\else \ltj@@latex@plv=1000\fi}% 2020-10-01
+ {\ifnum\patch@level>2\relax \ltj@@latex@plv=1300\else \ltj@@latex@plv=1000\fi}% 2020-10-01
+\ExplSyntaxOff
\else\ifdefined\@rmfamilyhook % 2020-02-02
\ifx\@forced@seriestrue\@undefined % 2020-02-02 pl0--2
\@latex@error
@@ -27,7 +29,6 @@
\fi
\fi\fi
-
%% patching \DeclareTextComposite
\def\ltj@chardef@text@cmd#1{%
\let\@ifdefinable\@@ifdefinable%